-
-
Notifications
You must be signed in to change notification settings - Fork 72
Decouple from annotations #246
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
This file was deleted.
This file was deleted.
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
Note about upgrading: Doctrine uses static and runtime mechanisms to raise | ||
awareness about deprecated code. | ||
|
||
- Use of `@deprecated` docblock that is detected by IDEs (like PHPStorm) or | ||
Static Analysis tools (like Psalm, phpstan) | ||
- Use of our low-overhead runtime deprecation API, details: | ||
https://github.com/doctrine/deprecations/ | ||
|
||
# Upgrade to 2.4 | ||
|
||
## Deprecated `AnnotationDriver` | ||
|
||
Since attributes were introduced in PHP 8.0, annotations are deprecated. Use | ||
`ColocatedMappingDriver` instead. This will involve implementing | ||
`isTransient()` as well as `__construct()` and `getReader()` to | ||
retain backward compatibility. | ||
|
||
# Upgrade to 2.3 | ||
|
||
## Deprecated using short namespace alias syntax in favor of `::class` syntax. | ||
|
||
Before: | ||
|
||
```php | ||
$objectManager->find('MyPackage:MyClass', $id); | ||
$objectManager->createQuery('SELECT u FROM MyPackage:MyClass'); | ||
``` | ||
|
||
After: | ||
|
||
```php | ||
$objectManager->find(MyClass::class, $id); | ||
$objectManager->createQuery('SELECT u FROM '. MyClass::class); | ||
``` | ||
|
||
# Upgrade to 2.2 | ||
|
||
## Deprecated `doctrine/cache` usage for metadata caching | ||
|
||
The `setCacheDriver` and `getCacheDriver` methods in | ||
`Doctrine\Persistence\Mapping\AbstractMetadata` have been deprecated. Please | ||
use `getCache` and `setCache` with a PSR-6 implementation instead. Note that | ||
even after switching to PSR-6, `getCacheDriver` will return a cache instance | ||
that wraps the PSR-6 cache. Note that if you use a custom implementation of | ||
doctrine/cache, the library may not be able to provide a forward compatibility | ||
layer. The cache implementation MUST extend the | ||
`Doctrine\Common\Cache\CacheProvider` class. | ||
|
||
# Upgrade to 1.2 | ||
|
||
## Deprecated `ObjectManager::merge()` and `ObjectManager::detach()` | ||
|
||
Please handle merge operations in your application, and use | ||
`ObjectManager::clear()` instead. | ||
|
||
## Deprecated `PersistentObject` | ||
|
||
Please implement this functionality directly in your application if you want | ||
ActiveRecord style functionality. |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -159,7 +159,7 @@ Mapping Driver | |
|
||
In order to load ``ClassMetadata`` instances you can use the ``Doctrine\Persistence\Mapping\Driver\MappingDriver`` | ||
interface. This is the interface that does the core loading of mapping information from wherever they are stored. | ||
That may be in files, annotations, yaml, xml, etc. | ||
That may be in files, attributes, yaml, xml, etc. | ||
|
||
.. code-block:: php | ||
|
||
|
@@ -174,8 +174,8 @@ That may be in files, annotations, yaml, xml, etc. | |
public function isTransient($className); | ||
} | ||
|
||
The Doctrine Persistence project offers a few base implementations that make it easy to implement your own XML, | ||
Annotations or YAML drivers. | ||
The Doctrine Persistence project offers a few base implementations that | ||
make it easy to implement your own XML, Attributes or YAML drivers. | ||
|
||
FileDriver | ||
---------- | ||
|
@@ -233,45 +233,9 @@ AnnotationDriver | |
|
||
.. note:: | ||
|
||
This driver requires the ``doctrine/annotations`` project. You can install it with composer. | ||
This driver requires the ``doctrine/annotations`` project and is | ||
deprecated because of that. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'd add a note about attributes superseding annotations There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also why removing the docs below? The feature is deprecated but documentation is still valuable :) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it feels weird to deprecate a feature yet help people build on it. I thought I would make it harder for people to shoot themselves in the foot. |
||
|
||
.. code-block:: php | ||
|
||
composer require doctrine/annotations | ||
|
||
The AnnotationDriver reads the mapping metadata from docblock annotations. | ||
|
||
.. code-block:: php | ||
|
||
final class MyAnnotationDriver extends AnnotationDriver | ||
{ | ||
public function loadMetadataForClass($className, ClassMetadata $metadata) | ||
{ | ||
/** @var ClassMetadata $class */ | ||
$reflClass = $class->getReflectionClass(); | ||
|
||
$classAnnotations = $this->reader->getClassAnnotations($reflClass); | ||
|
||
// Use the reader to read annotations from your classes to then populate the $metadata instance. | ||
} | ||
} | ||
|
||
Now you can use it like the following: | ||
|
||
.. code-block:: php | ||
|
||
use App\Model\User; | ||
use Doctrine\Annotations\AnnotationReader; | ||
use Doctrine\Persistence\Mapping\ClassMetadata; | ||
|
||
$annotationReader = new AnnotationReader(); | ||
|
||
$annotationDriver = new AnnotationDriver($annotationReader, '/path/to/classes/with/annotations'); | ||
|
||
$classMetadata = new ClassMetadata(); | ||
|
||
// looks for a PHP file at /path/to/classes/with/annotations/App/Model/User.php | ||
$annotationDriver->loadMetadataForClass(User::class, $classMetadata); | ||
|
||
PHPDriver | ||
--------- | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,68 +3,26 @@ | |
namespace Doctrine\Persistence\Mapping\Driver; | ||
|
||
use Doctrine\Common\Annotations\Reader; | ||
use Doctrine\Persistence\Mapping\MappingException; | ||
use FilesystemIterator; | ||
use RecursiveDirectoryIterator; | ||
use RecursiveIteratorIterator; | ||
use RecursiveRegexIterator; | ||
use ReflectionClass; | ||
use RegexIterator; | ||
|
||
use function array_merge; | ||
use function array_unique; | ||
use function assert; | ||
use function get_class; | ||
use function get_declared_classes; | ||
use function in_array; | ||
use function is_dir; | ||
use function preg_match; | ||
use function preg_quote; | ||
use function realpath; | ||
use function str_replace; | ||
use function strpos; | ||
|
||
/** | ||
* The AnnotationDriver reads the mapping metadata from docblock annotations. | ||
* | ||
* @deprecated extend ColocatedMappingDriver directly instead. | ||
*/ | ||
abstract class AnnotationDriver implements MappingDriver | ||
{ | ||
use ColocatedMappingDriver; | ||
|
||
/** | ||
* The annotation reader. | ||
* | ||
* @var Reader | ||
*/ | ||
protected $reader; | ||
|
||
/** | ||
* The paths where to look for mapping files. | ||
* | ||
* @var string[] | ||
*/ | ||
protected $paths = []; | ||
|
||
/** | ||
* The paths excluded from path where to look for mapping files. | ||
* | ||
* @var string[] | ||
*/ | ||
protected $excludePaths = []; | ||
|
||
/** | ||
* The file extension of mapping documents. | ||
* | ||
* @var string | ||
*/ | ||
protected $fileExtension = '.php'; | ||
|
||
/** | ||
* Cache for AnnotationDriver#getAllClassNames(). | ||
* | ||
* @var string[]|null | ||
* @psalm-var list<class-string>|null | ||
*/ | ||
protected $classNames; | ||
|
||
/** | ||
* Name of the entity annotations as keys. | ||
* | ||
|
@@ -82,57 +40,10 @@ abstract class AnnotationDriver implements MappingDriver | |
public function __construct($reader, $paths = null) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should the constructor trigger a runtime deprecation? |
||
{ | ||
$this->reader = $reader; | ||
if (! $paths) { | ||
return; | ||
} | ||
|
||
$this->addPaths((array) $paths); | ||
} | ||
|
||
/** | ||
* Appends lookup paths to metadata driver. | ||
* | ||
* @param string[] $paths | ||
* | ||
* @return void | ||
*/ | ||
public function addPaths(array $paths) | ||
{ | ||
$this->paths = array_unique(array_merge($this->paths, $paths)); | ||
} | ||
|
||
/** | ||
* Retrieves the defined metadata lookup paths. | ||
* | ||
* @return string[] | ||
*/ | ||
public function getPaths() | ||
{ | ||
return $this->paths; | ||
} | ||
|
||
/** | ||
* Append exclude lookup paths to metadata driver. | ||
* | ||
* @param string[] $paths | ||
* | ||
* @return void | ||
*/ | ||
public function addExcludePaths(array $paths) | ||
{ | ||
$this->excludePaths = array_unique(array_merge($this->excludePaths, $paths)); | ||
} | ||
|
||
/** | ||
* Retrieve the defined metadata lookup exclude paths. | ||
* | ||
* @return string[] | ||
*/ | ||
public function getExcludePaths() | ||
{ | ||
return $this->excludePaths; | ||
} | ||
|
||
/** | ||
* Retrieve the current annotation reader | ||
* | ||
|
@@ -144,34 +55,6 @@ public function getReader() | |
} | ||
|
||
/** | ||
* Gets the file extension used to look for mapping files under. | ||
* | ||
* @return string | ||
*/ | ||
public function getFileExtension() | ||
{ | ||
return $this->fileExtension; | ||
} | ||
|
||
/** | ||
* Sets the file extension used to look for mapping files under. | ||
* | ||
* @param string $fileExtension The file extension to set. | ||
* | ||
* @return void | ||
*/ | ||
public function setFileExtension($fileExtension) | ||
{ | ||
$this->fileExtension = $fileExtension; | ||
} | ||
|
||
/** | ||
* Returns whether the class with the specified name is transient. Only non-transient | ||
* classes, that is entities and mapped superclasses, should have their metadata loaded. | ||
* | ||
* A class is non-transient if it is annotated with an annotation | ||
* from the {@see AnnotationDriver::entityAnnotationClasses}. | ||
* | ||
* {@inheritDoc} | ||
*/ | ||
public function isTransient($className) | ||
|
@@ -186,75 +69,4 @@ public function isTransient($className) | |
|
||
return true; | ||
} | ||
|
||
/** | ||
* {@inheritDoc} | ||
*/ | ||
public function getAllClassNames() | ||
{ | ||
if ($this->classNames !== null) { | ||
return $this->classNames; | ||
} | ||
|
||
if (! $this->paths) { | ||
throw MappingException::pathRequired(); | ||
} | ||
|
||
$classes = []; | ||
$includedFiles = []; | ||
|
||
foreach ($this->paths as $path) { | ||
if (! is_dir($path)) { | ||
throw MappingException::fileMappingDriversRequireConfiguredDirectoryPath($path); | ||
} | ||
|
||
$iterator = new RegexIterator( | ||
new RecursiveIteratorIterator( | ||
new RecursiveDirectoryIterator($path, FilesystemIterator::SKIP_DOTS), | ||
RecursiveIteratorIterator::LEAVES_ONLY | ||
), | ||
'/^.+' . preg_quote($this->fileExtension) . '$/i', | ||
RecursiveRegexIterator::GET_MATCH | ||
); | ||
|
||
foreach ($iterator as $file) { | ||
$sourceFile = $file[0]; | ||
|
||
if (preg_match('(^phar:)i', $sourceFile) === 0) { | ||
$sourceFile = realpath($sourceFile); | ||
} | ||
|
||
foreach ($this->excludePaths as $excludePath) { | ||
$realExcludePath = realpath($excludePath); | ||
assert($realExcludePath !== false); | ||
$exclude = str_replace('\\', '/', $realExcludePath); | ||
$current = str_replace('\\', '/', $sourceFile); | ||
|
||
if (strpos($current, $exclude) !== false) { | ||
continue 2; | ||
} | ||
} | ||
|
||
require_once $sourceFile; | ||
|
||
$includedFiles[] = $sourceFile; | ||
} | ||
} | ||
|
||
$declared = get_declared_classes(); | ||
|
||
foreach ($declared as $className) { | ||
$rc = new ReflectionClass($className); | ||
$sourceFile = $rc->getFileName(); | ||
if (! in_array($sourceFile, $includedFiles) || $this->isTransient($className)) { | ||
continue; | ||
} | ||
|
||
$classes[] = $className; | ||
} | ||
|
||
$this->classNames = $classes; | ||
|
||
return $classes; | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Attributes, or YAML