feature #31486 [Doctrine][PropertyInfo] Detect if the ID is writeable (dunglas)
This PR was merged into the 4.3 branch.
Discussion
----------
[Doctrine][PropertyInfo] Detect if the ID is writeable
| Q | A
| ------------- | ---
| Branch? | 4.3
| Bug fix? | yes
| New feature? | yes <!-- please update src/**/CHANGELOG.md files -->
| BC breaks? | no <!-- see https://symfony.com/bc -->
| Deprecations? | yes/no <!-- please update UPGRADE-*.md and src/**/CHANGELOG.md files -->
| Tests pass? | yes <!-- please add some, will be required by reviewers -->
| Fixed tickets | n/a
| License | MIT
| Doc PR | n/a
Companion of #31481. Allows to detect that ids with a generated value aren't writable (because the DBMS will generate the ID by itself). It could be considered as a bug fix or as a new feature. I prefer to not merge in in 3.4. However, it becomes necessary for autovalidation to work with such entities, so it should be in 4.3:
```php
/**
* @Entity
*/
class Foo
{
/**
* @Id
* @GeneratedValue(strategy="AUTO")
* @Column(type="integer")
*/
public $id;
}
```
Commits
-------
4598235192
[Doctrine][PropertyInfo] Detect if the ID is writeable
This commit is contained in:
commit
0d196c46a5
@ -15,8 +15,10 @@ use Doctrine\Common\Persistence\Mapping\ClassMetadataFactory;
|
||||
use Doctrine\Common\Persistence\Mapping\MappingException;
|
||||
use Doctrine\DBAL\Types\Type as DBALType;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Doctrine\ORM\Mapping\ClassMetadata;
|
||||
use Doctrine\ORM\Mapping\ClassMetadataInfo;
|
||||
use Doctrine\ORM\Mapping\MappingException as OrmMappingException;
|
||||
use Symfony\Component\PropertyInfo\PropertyAccessExtractorInterface;
|
||||
use Symfony\Component\PropertyInfo\PropertyListExtractorInterface;
|
||||
use Symfony\Component\PropertyInfo\PropertyTypeExtractorInterface;
|
||||
use Symfony\Component\PropertyInfo\Type;
|
||||
@ -26,7 +28,7 @@ use Symfony\Component\PropertyInfo\Type;
|
||||
*
|
||||
* @author Kévin Dunglas <dunglas@gmail.com>
|
||||
*/
|
||||
class DoctrineExtractor implements PropertyListExtractorInterface, PropertyTypeExtractorInterface
|
||||
class DoctrineExtractor implements PropertyListExtractorInterface, PropertyTypeExtractorInterface, PropertyAccessExtractorInterface
|
||||
{
|
||||
private $entityManager;
|
||||
private $classMetadataFactory;
|
||||
@ -51,12 +53,8 @@ class DoctrineExtractor implements PropertyListExtractorInterface, PropertyTypeE
|
||||
*/
|
||||
public function getProperties($class, array $context = [])
|
||||
{
|
||||
try {
|
||||
$metadata = $this->entityManager ? $this->entityManager->getClassMetadata($class) : $this->classMetadataFactory->getMetadataFor($class);
|
||||
} catch (MappingException $exception) {
|
||||
return;
|
||||
} catch (OrmMappingException $exception) {
|
||||
return;
|
||||
if (null === $metadata = $this->getMetadata($class)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$properties = array_merge($metadata->getFieldNames(), $metadata->getAssociationNames());
|
||||
@ -77,12 +75,8 @@ class DoctrineExtractor implements PropertyListExtractorInterface, PropertyTypeE
|
||||
*/
|
||||
public function getTypes($class, $property, array $context = [])
|
||||
{
|
||||
try {
|
||||
$metadata = $this->entityManager ? $this->entityManager->getClassMetadata($class) : $this->classMetadataFactory->getMetadataFor($class);
|
||||
} catch (MappingException $exception) {
|
||||
return;
|
||||
} catch (OrmMappingException $exception) {
|
||||
return;
|
||||
if (null === $metadata = $this->getMetadata($class)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if ($metadata->hasAssociation($property)) {
|
||||
@ -176,6 +170,39 @@ class DoctrineExtractor implements PropertyListExtractorInterface, PropertyTypeE
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isReadable($class, $property, array $context = [])
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isWritable($class, $property, array $context = [])
|
||||
{
|
||||
if (
|
||||
null === ($metadata = $this->getMetadata($class))
|
||||
|| ClassMetadata::GENERATOR_TYPE_NONE === $metadata->generatorType
|
||||
|| !\in_array($property, $metadata->getIdentifierFieldNames(), true)
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private function getMetadata(string $class): ?ClassMetadata
|
||||
{
|
||||
try {
|
||||
return $this->entityManager ? $this->entityManager->getClassMetadata($class) : $this->classMetadataFactory->getMetadataFor($class);
|
||||
} catch (MappingException | OrmMappingException $exception) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether an association is nullable.
|
||||
*
|
||||
|
@ -16,6 +16,7 @@ use Doctrine\ORM\EntityManager;
|
||||
use Doctrine\ORM\Tools\Setup;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Bridge\Doctrine\PropertyInfo\DoctrineExtractor;
|
||||
use Symfony\Bridge\Doctrine\Tests\PropertyInfo\Fixtures\DoctrineGeneratedValue;
|
||||
use Symfony\Component\PropertyInfo\Type;
|
||||
|
||||
/**
|
||||
@ -223,4 +224,13 @@ class DoctrineExtractorTest extends TestCase
|
||||
{
|
||||
$this->assertNull($this->createExtractor($legacy)->getTypes('Not\Exist', 'baz'));
|
||||
}
|
||||
|
||||
public function testGeneratedValueNotWritable()
|
||||
{
|
||||
$extractor = $this->createExtractor();
|
||||
$this->assertFalse($extractor->isWritable(DoctrineGeneratedValue::class, 'id'));
|
||||
$this->assertNull($extractor->isReadable(DoctrineGeneratedValue::class, 'id'));
|
||||
$this->assertNull($extractor->isWritable(DoctrineGeneratedValue::class, 'foo'));
|
||||
$this->assertNull($extractor->isReadable(DoctrineGeneratedValue::class, 'foo'));
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Bridge\Doctrine\Tests\PropertyInfo\Fixtures;
|
||||
|
||||
use Doctrine\ORM\Mapping\Column;
|
||||
use Doctrine\ORM\Mapping\Entity;
|
||||
use Doctrine\ORM\Mapping\GeneratedValue;
|
||||
use Doctrine\ORM\Mapping\Id;
|
||||
|
||||
/**
|
||||
* @author Kévin Dunglas <dunglas@gmail.com>
|
||||
*
|
||||
* @Entity
|
||||
*/
|
||||
class DoctrineGeneratedValue
|
||||
{
|
||||
/**
|
||||
* @Id
|
||||
* @GeneratedValue(strategy="AUTO")
|
||||
* @Column(type="integer")
|
||||
*/
|
||||
public $id;
|
||||
|
||||
/**
|
||||
* @Column
|
||||
*/
|
||||
public $foo;
|
||||
}
|
Reference in New Issue
Block a user