BEAR.QueryRepository 1.13.0 has removed the dependency on doctrine/annotations and now exclusively uses native PHP 8 attributes. This guide will help you migrate your application code from Doctrine annotations to PHP 8 attributes.
- doctrine/annotations is Abandoned: The
doctrine/annotationspackage has been officially abandoned by its maintainers. Continuing to use it poses security and compatibility risks as it will no longer receive updates or security patches. - Native PHP Support: PHP 8 attributes are a built-in language feature, providing first-class support without external dependencies
- Better Performance: No runtime annotation parsing overhead - attributes are compiled and cached by PHP itself
- Modern Syntax: Cleaner, more readable code that follows PHP 8+ best practices
- No Extra Dependencies: Eliminates the need for the abandoned doctrine/annotations package
- Future-Proof: Attributes are the official PHP standard for metadata, ensuring long-term compatibility
Rector is an automated refactoring tool that can convert annotations to attributes:
composer require --dev rector/rectorBEAR.QueryRepository provides a Rector configuration file for automated migration:
# Dry-run to preview changes
vendor/bin/rector process src --config=vendor/bear/query-repository/rector-migrate.php --dry-run
# Apply the changes
vendor/bin/rector process src --config=vendor/bear/query-repository/rector-migrate.phpIf you have tests that use annotations:
vendor/bin/rector process tests --config=vendor/bear/query-repository/rector-migrate.phpReview the changes made by Rector and adjust if necessary. Pay special attention to:
- Multi-line annotations with complex values
- Annotations with custom parameters
- Import statements (Rector should handle these automatically)
After migration, you can safely remove the doctrine/annotations dependency:
composer remove doctrine/annotationsBefore (Doctrine Annotation):
use BEAR\RepositoryModule\Annotation\Cacheable;
/**
* @Cacheable(expiry="short", type="value")
*/
class User extends ResourceObject
{
public function onGet($id)
{
// ...
}
}After (PHP 8 Attribute):
use BEAR\RepositoryModule\Annotation\Cacheable;
#[Cacheable(expiry: "short", type: "value")]
class User extends ResourceObject
{
public function onGet($id)
{
// ...
}
}Before (Doctrine Annotation):
use BEAR\RepositoryModule\Annotation\HttpCache;
/**
* @HttpCache(maxAge=60, sMaxAge=600)
*/
class News extends ResourceObject
{
public function onGet()
{
// ...
}
}After (PHP 8 Attribute):
use BEAR\RepositoryModule\Annotation\HttpCache;
#[HttpCache(maxAge: 60, sMaxAge: 600)]
class News extends ResourceObject
{
public function onGet()
{
// ...
}
}Before (Doctrine Annotation):
use BEAR\RepositoryModule\Annotation\Refresh;
use BEAR\RepositoryModule\Annotation\Purge;
class User extends ResourceObject
{
/**
* @Refresh(uri="app://self/users")
* @Purge(uri="app://self/user/{id}")
*/
public function onPut($id, $name)
{
// ...
}
}After (PHP 8 Attribute):
use BEAR\RepositoryModule\Annotation\Refresh;
use BEAR\RepositoryModule\Annotation\Purge;
class User extends ResourceObject
{
#[Refresh(uri: "app://self/users")]
#[Purge(uri: "app://self/user/{id}")]
public function onPut($id, $name)
{
// ...
}
}Before (Doctrine Annotation):
use BEAR\RepositoryModule\Annotation\Cacheable;
use BEAR\RepositoryModule\Annotation\HttpCache;
/**
* @Cacheable(expiry="medium", expirySecond=3600, type="view", update=true)
* @HttpCache(maxAge=60, sMaxAge=600, isPrivate=false, mustRevalidate=true)
*/
class Article extends ResourceObject
{
// ...
}After (PHP 8 Attribute):
use BEAR\RepositoryModule\Annotation\Cacheable;
use BEAR\RepositoryModule\Annotation\HttpCache;
#[Cacheable(expiry: "medium", expirySecond: 3600, type: "view", update: true)]
#[HttpCache(maxAge: 60, sMaxAge: 600, isPrivate: false, mustRevalidate: true)]
class Article extends ResourceObject
{
// ...
}Before (Doctrine Annotation):
use BEAR\RepositoryModule\Annotation\DonutCache;
class Page extends ResourceObject
{
/**
* @DonutCache
*/
public function onGet()
{
// ...
}
}After (PHP 8 Attribute):
use BEAR\RepositoryModule\Annotation\DonutCache;
class Page extends ResourceObject
{
#[DonutCache]
public function onGet()
{
// ...
}
}The following BEAR.QueryRepository annotations are automatically converted:
@Cacheable→#[Cacheable]- Resource caching configuration@HttpCache→#[HttpCache]- HTTP cache control headers@NoHttpCache→#[NoHttpCache]- Disable HTTP caching@Refresh→#[Refresh]- Invalidate dependent caches@Purge→#[Purge]- Purge specific cache entries@DonutCache→#[DonutCache]- Donut caching pattern@RefreshCache→#[RefreshCache]- Refresh cache after command@Commands→#[Commands]- Cache invalidation commands
Note: This migration tool only handles BEAR.QueryRepository annotations. For Ray.Di annotations (such as @Inject, @Named, etc.), please refer to the Ray.Di migration guide.
- Syntax Change: Use
#[AttributeName]instead of@AttributeNamein docblocks - Named Parameters: Use colons for parameters (e.g.,
expiry: "short"instead ofexpiry="short") - Placement: Attributes go before the class/method declaration, not in docblocks
- Import Statements: Add proper
usestatements for all attributes - Multiple Attributes: Stack multiple attributes on separate lines or combine with commas
Make sure your code is using fully qualified class names in use statements:
// Correct
use BEAR\RepositoryModule\Annotation\Cacheable;
// Incorrect - Rector won't recognize this
use BEAR\RepositoryModule\Annotation as Cache;Rector should automatically update import statements, but if it doesn't:
- Manually verify
usestatements are present - Run your IDE's "Optimize Imports" feature
- Use tools like PHP-CS-Fixer to clean up unused imports
For annotations with complex array values, you may need to manually adjust the syntax:
Before:
/**
* @HttpCache(etag={"id", "updated_at"})
*/After:
#[HttpCache(etag: ["id", "updated_at"])]After migration, ensure all tests pass:
vendor/bin/phpunitIf you prefer not to use Rector, you can manually convert annotations:
- Replace
/** @AnnotationName */with#[AnnotationName] - Move attributes from docblocks to the line before the method/property/class
- Convert parameter syntax from
key="value"tokey: "value" - Ensure all necessary
usestatements are present - For multiple attributes, place each on a new line or combine:
#[Attr1, Attr2]
If you encounter issues during migration:
- Check the BEAR.QueryRepository documentation
- Review the PHP 8 Attributes documentation
- Open an issue on GitHub