简体   繁体   中英

How to provide SF/Sonata RepeatedType (pw) on User/edit for Admins

we are working with symfony 4.4 and use sonata for our entity administration. we implemented a pretty lightweight usermanagement and also have the possibility to add products to a user in a second tab on the user edit page. so now the admin wants to assign products to a user but the problem is that the password field does not allow that behaviour. first the password field was required, but setting it to false does not help at all because then the field just gets submitted empty.

so a solution i tried is to use the preUpdate function within my admin class to prevent that error.

    public function preUpdate($object)
{
    /** @var EntityManagerInterface $em */
    $em = $this->getConfigurationPool()->getContainer()->get('Doctrine')->getManager();
    /** @var UserRepository $repository */
    $repository = $em->getRepository(User::class)->find($object->getId());

    $password = $object->getPassword();
    if (!empty($password)) {
        $salt = md5(time());

        $encoderservice = $this->getConfigurationPool()->getContainer()->get('security.encoder_factory');
        $encoder = $encoderservice->getEncoder($object);
        $encoded_pass = $encoder->encodePassword($object->getPassword(), $salt);
        $object->setSalt($salt);
        $object->setPassword($encoded_pass);
    } else {
        $object->setPassword($repository->getPassword());
    }

    return $object;

}

so if the password is not empty - we take the given value and update the password. if the field is empty we use the existing password, so its no problem to just add products and update the user entity.

that would be nice but the triggering error comes before the preUpdate function could help.

so the given error is:

Expected argument of type "string", "null" given at property path "password".

without the preUpdate taking any effect.

what would be the solution here?

full stacktrace:

Symfony\Component\PropertyAccess\Exception\InvalidArgumentException:
Expected argument of type "string", "null" given at property path "password".

  at vendor/symfony/property-access/PropertyAccessor.php:198
  at Symfony\Component\PropertyAccess\PropertyAccessor::throwInvalidArgumentException('string', array(array('file' => '/var/www/vendor/symfony/property-access/PropertyAccessor.php', 'line' => 548, 'function' => 'setPassword', 'class' => 'App\\Entity\\User', 'type' => '->', 'args' => array(null)), array('file' => '/var/www/vendor/symfony/property-access/PropertyAccessor.php', 'line' => 114, 'function' => 'writeProperty', 'class' => 'Symfony\\Component\\PropertyAccess\\PropertyAccessor', 'type' => '->', 'args' => array(array(object(User)), 'password', null)), array('file' => '/var/www/vendor/symfony/form/Extension/Core/DataMapper/PropertyPathMapper.php', 'line' => 86, 'function' => 'setValue', 'class' => 'Symfony\\Component\\PropertyAccess\\PropertyAccessor', 'type' => '->', 'args' => array(object(User), object(PropertyPath), null)), array('file' => '/var/www/vendor/symfony/form/Form.php', 'line' => 632, 'function' => 'mapFormsToData', 'class' => 'Symfony\\Component\\Form\\Extension\\Core\\DataMapper\\PropertyPathMapper', 'type' => '->', 'args' => array(object(RecursiveIteratorIterator), object(User))), array('file' => '/var/www/vendor/symfony/form/Extension/HttpFoundation/HttpFoundationRequestHandler.php', 'line' => 109, 'function' => 'submit', 'class' => 'Symfony\\Component\\Form\\Form', 'type' => '->', 'args' => array(array(), true)), array('file' => '/var/www/vendor/symfony/form/Form.php', 'line' => 493, 'function' => 'handleRequest', 'class' => 'Symfony\\Component\\Form\\Extension\\HttpFoundation\\HttpFoundationRequestHandler', 'type' => '->', 'args' => array(object(Form), object(Request))), array('file' => '/var/www/vendor/sonata-project/admin-bundle/src/Controller/CRUDController.php', 'line' => 331, 'function' => 'handleRequest', 'class' => 'Symfony\\Component\\Form\\Form', 'type' => '->', 'args' => array(object(Request))), array('file' => '/var/www/vendor/symfony/http-kernel/HttpKernel.php', 'line' => 158, 'function' => 'editAction', 'class' => 'Sonata\\AdminBundle\\Controller\\CRUDController', 'type' => '->', 'args' => array(null)), array('file' => '/var/www/vendor/symfony/http-kernel/HttpKernel.php', 'line' => 80, 'function' => 'handleRaw', 'class' => 'Symfony\\Component\\HttpKernel\\HttpKernel', 'type' => '->', 'args' => array(object(Request), 1)), array('file' => '/var/www/vendor/symfony/http-kernel/Kernel.php', 'line' => 201, 'function' => 'handle', 'class' => 'Symfony\\Component\\HttpKernel\\HttpKernel', 'type' => '->', 'args' => array(object(Request), 1, true)), array('file' => '/var/www/public/index.php', 'line' => 25, 'function' => 'handle', 'class' => 'Symfony\\Component\\HttpKernel\\Kernel', 'type' => '->', 'args' => array(object(Request)))), 0, 'password')
     (vendor/symfony/property-access/PropertyAccessor.php:118)
  at Symfony\Component\PropertyAccess\PropertyAccessor->setValue(object(User), object(PropertyPath), null)
     (vendor/symfony/form/Extension/Core/DataMapper/PropertyPathMapper.php:86)
  at Symfony\Component\Form\Extension\Core\DataMapper\PropertyPathMapper->mapFormsToData(object(RecursiveIteratorIterator), object(User))
     (vendor/symfony/form/Form.php:632)
  at Symfony\Component\Form\Form->submit(array(), true)
     (vendor/symfony/form/Extension/HttpFoundation/HttpFoundationRequestHandler.php:109)
  at Symfony\Component\Form\Extension\HttpFoundation\HttpFoundationRequestHandler->handleRequest(object(Form), object(Request))
     (vendor/symfony/form/Form.php:493)
  at Symfony\Component\Form\Form->handleRequest(object(Request))
     (vendor/sonata-project/admin-bundle/src/Controller/CRUDController.php:331)
  at Sonata\AdminBundle\Controller\CRUDController->editAction(null)
     (vendor/symfony/http-kernel/HttpKernel.php:158)
  at Symfony\Component\HttpKernel\HttpKernel->handleRaw(object(Request), 1)
     (vendor/symfony/http-kernel/HttpKernel.php:80)
  at Symfony\Component\HttpKernel\HttpKernel->handle(object(Request), 1, true)
     (vendor/symfony/http-kernel/Kernel.php:201)
  at Symfony\Component\HttpKernel\Kernel->handle(object(Request))
     (public/index.php:25) 

can i somehow apply the behaviour of the preUpdate somewhere else?

and here is the formMapper:

        $formMapper
        ->tab("Information")
            ->add('email', TextType::class, [
                'attr' => [
                    'readonly' => $emailDisabledState,
                ],
            ])
            ->add('password', RepeatedType::class, [
                'type' => PasswordType::class,
                'invalid_message' => 'The password fields must match.',
                'options' => ['attr' => ['class' => 'password-field']],
                'required' => false,
                'first_options'  => ['label' => 'Password'],
                'second_options' => ['label' => 'Repeat Password'],
            ])
            ->add('isActive', BooleanType::class)
            ->add('roles', ChoiceType::class, [
                'choices' => array_flip($flattendRoles),
                'multiple' => true,
                'expanded' => false,
            ])
            ->end()
        ->end()
        ->tab("Products")
            ->add("products", EntityType::class, [
                'class' => Product::class,
                'multiple' => true
            ])
            ->end()
        ->end();

help is much appreciated

Declaration of repeated type seems good.

You shouldn't have to prevent error in preUpdate.

Is parameter optional in your entity?

    public function setPassword(?string $password): self
    {
        $this->password = $password;

        return $this;
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM