Thanks to visit codestin.com
Credit goes to github.com

Skip to content

DoctrineOrmTypeGuesser throw an exception with embedded class #26543

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

Closed
pink6440 opened this issue Mar 15, 2018 · 3 comments
Closed

DoctrineOrmTypeGuesser throw an exception with embedded class #26543

pink6440 opened this issue Mar 15, 2018 · 3 comments

Comments

@pink6440
Copy link

Q A
Bug report? yes
Feature request? no
BC Break report? no
RFC? no
Symfony version 3.4.4

The use case :

  • i got a doctrine embeddable (example: Identity)
  • in forms, i want that my IdentityFormType to be used automatically

So :

  • i make a Type Guesser which handle guessing for property of type Identity (as embeddable)

But :

  • as all guessers are trieds by the ChainGuesser
  • as the DoctrineOrmTypeGuesser threw an exception

So : that doesn't work

The Exception :
No mapping found for field 'identite' on class 'NSF\CoreBundle\Entity\Client'.
in vendor\doctrine\orm\lib\Doctrine\ORM\Mapping\MappingException.php (line 163)

My solution was to fix (in my way) into the DoctrineOrmTypeGuesser and to use my updated class with composer/autoload/file directive.

@fancyweb
Copy link
Contributor

Hello, can you provide the full exception trace please ?
AFAIK, mapping exceptions are caught and silenced when trying to get the metadata in the DoctrineOrmTypeGuesser.

@pink6440
Copy link
Author

pink6440 commented Mar 16, 2018

@fancyweb : indeed, it is silenced for getting the class metadata but it is not if something happen while trying to get some information on a property.

Here is the trace

Doctrine\ORM\Mapping\MappingException: 
No mapping found for field 'identite' on class 'NSF\CoreBundle\Entity\Security\User'.

  at vendor\doctrine\orm\lib\Doctrine\ORM\Mapping\MappingException.php:163
  at Doctrine\ORM\Mapping\MappingException::mappingNotFound('NSF\\CoreBundle\\Entity\\Security\\User', 'identite')
     (vendor\doctrine\orm\lib\Doctrine\ORM\Mapping\ClassMetadataInfo.php:1232)
  at Doctrine\ORM\Mapping\ClassMetadataInfo->getFieldMapping('identite')
     (vendor\symfony\doctrine-bridge\Form\DoctrineOrmTypeGuesser.php:130)
  at Symfony\Bridge\Doctrine\Form\DoctrineOrmTypeGuesser->guessMaxLength('NSF\\CoreBundle\\Entity\\Security\\User', 'identite')
     (vendor\symfony\form\FormTypeGuesserChain.php:71)
  at Symfony\Component\Form\FormTypeGuesserChain->Symfony\Component\Form\{closure}(object(DoctrineOrmTypeGuesser))
     (vendor\symfony\form\FormTypeGuesserChain.php:100)
  at Symfony\Component\Form\FormTypeGuesserChain->guess(object(Closure))
     (vendor\symfony\form\FormTypeGuesserChain.php:72)
  at Symfony\Component\Form\FormTypeGuesserChain->guessMaxLength('NSF\\CoreBundle\\Entity\\Security\\User', 'identite')
     (vendor\symfony\form\FormFactory.php:95)
  at Symfony\Component\Form\FormFactory->createBuilderForProperty('NSF\\CoreBundle\\Entity\\Security\\User', 'identite', null, array('label' => false))
     (vendor\symfony\form\FormBuilder.php:109)
  at Symfony\Component\Form\FormBuilder->create('identite', null, array('label' => false))
     (vendor\symfony\form\FormBuilder.php:269)
  at Symfony\Component\Form\FormBuilder->resolveChildren()
     (vendor\symfony\form\FormBuilder.php:215)
  at Symfony\Component\Form\FormBuilder->getForm()
     (vendor\symfony\form\FormFactory.php:30)
  at Symfony\Component\Form\FormFactory->create('NSF\\CoreBundle\\Form\\Security\\CreateUserImplantationType', object(User), array())
     (vendor\symfony\framework-bundle\Controller\ControllerTrait.php:395)
  at Symfony\Bundle\FrameworkBundle\Controller\Controller->createForm('NSF\\CoreBundle\\Form\\Security\\CreateUserImplantationType', object(User))
     (NSF\CoreBundle\Controller\App\ImplantationController.php:223)
  at NSF\CoreBundle\Controller\App\ImplantationController->createUser(object(Request), object(Implantation), object(Screen), object(Profil), object(UserFactory), object(UserManager))
     (vendor\symfony\http-kernel\HttpKernel.php:151)
  at Symfony\Component\HttpKernel\HttpKernel->handleRaw(object(Request), 1)
     (vendor\symfony\http-kernel\HttpKernel.php:68)
  at Symfony\Component\HttpKernel\HttpKernel->handle(object(Request), 1, true)
     (vendor\symfony\http-kernel\Kernel.php:202)
  at Symfony\Component\HttpKernel\Kernel->handle(object(Request))
     (public\index.php:37)

Here is a part of my "kick fix" in the DoctrineOrmTypeGuesser :

use Doctrine\Common\Annotations\AnnotationReader;
use Doctrine\ORM\Mapping\Embedded;
use Doctrine\Common\Annotations\AnnotationReader;

class DoctrineOrmTypeGuesser implements FormTypeGuesserInterface {

 ....

   /**
     * @var AnnotationReader
     */
    private $annotation_reader ;

 /**
     * @return AnnotationReader
     */
    public function getAnnotationReader()
    {
        if ($this->annotation_reader === null)
            $this->annotation_reader = new AnnotationReader();

        return $this->annotation_reader;
    }
  
    protected function getEmbeddedAnnotation($class,$property) {

        $rc = new \ReflectionClass($class);

        if (!$rc->hasProperty($property)) {
            return ;
        }

       $rc->getProperty($property);

        return $this->getAnnotationReader()->getPropertyAnnotation($rp,Embedded::class);
    }


 /**
     * {@inheritdoc}
     */
    public function guessMaxLength($class, $property)
    {

        $ret = $this->getMetadata($class);
        if ($ret && $ret[0]->hasField($property) && !$ret[0]->hasAssociation($property)) {

            //------- the fix -----
            if ($embed = $this->getEmbeddedAnnotation($class,$property))
                return ;
           // -------------------
            $mapping = $ret[0]->getFieldMapping($property);

            if (isset($mapping['length'])) {
                return new ValueGuess($mapping['length'], Guess::HIGH_CONFIDENCE);
            }

            if (in_array($ret[0]->getTypeOfField($property), array(Type::DECIMAL, Type::FLOAT))) {
                return new ValueGuess(null, Guess::MEDIUM_CONFIDENCE);
            }
        }
    }

( Maybe i have to change VERY_HIGH_CONFIDENCE to a lower value ; it's some vestige when i was trying to see if the guesser chain will stop when a VERY_HIGH_CONFIDENCE is hinted. )

I also got same kind of fix for the guessRequired, guessPattern, etc. methods but i'm not sure about what to return for the required value for an embedded ; i guess required fields are usually inside the embedded form type rather than in the parent container.

Well, at least, it is ok for my project :)

And yes, i will have to change the code for working when using xml or yaml mapping :] (as i had warned : it's ugly) :/

@fancyweb
Copy link
Contributor

fancyweb commented Mar 16, 2018

I have checked and IMHO there is a bug.
It only appears for people using Doctrine 2.6+.
The method hasField of ClassMetadataInfo was changed and now considers fields mapped as embedded as real fields (cf doctrine/orm#6462).

fabpot added a commit that referenced this issue Mar 18, 2018
… in DoctrineOrmTypeGuesser anymore (fancyweb)

This PR was merged into the 2.7 branch.

Discussion
----------

[DoctrineBridge] Don't rely on ClassMetadataInfo->hasField in DoctrineOrmTypeGuesser anymore

| Q             | A
| ------------- | ---
| Branch?       | 2.7
| Bug fix?      | yes
| New feature?  | no
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | #26543
| License       | MIT
| Doc PR        | -

Discussion and explanations in the linked issue #26543

Commits
-------

f656dc2 [DoctrineBridge] Don't rely on ClassMetadataInfo->hasField in DoctrineOrmTypeGuesser anymore
@fabpot fabpot closed this as completed Mar 18, 2018
symfony-splitter pushed a commit to symfony/doctrine-bridge that referenced this issue Mar 18, 2018
… in DoctrineOrmTypeGuesser anymore (fancyweb)

This PR was merged into the 2.7 branch.

Discussion
----------

[DoctrineBridge] Don't rely on ClassMetadataInfo->hasField in DoctrineOrmTypeGuesser anymore

| Q             | A
| ------------- | ---
| Branch?       | 2.7
| Bug fix?      | yes
| New feature?  | no
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | symfony/symfony#26543
| License       | MIT
| Doc PR        | -

Discussion and explanations in the linked issue symfony/symfony#26543

Commits
-------

f656dc2082 [DoctrineBridge] Don't rely on ClassMetadataInfo->hasField in DoctrineOrmTypeGuesser anymore
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants