Field不是实体的有效字段 - DoctrineEncryptBundle Symfony

时间:2015-09-22 14:23:53

标签: php forms symfony encryption doctrine-orm

我的应用程序中有一个注册表单,我想使用vmelnik-ukraine / DoctrineEncryptBundle为Symfony加密数据。 注册表格来自FOSUserBundle。

我已经配置并安装了捆绑包并在实体中导入了@Encrypted注释,如下所示:

namespace AppBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use FOS\UserBundle\Model\User as BaseUser;
use Symfony\Component\Validator\Constraints as Assert;
use VMelnik\DoctrineEncryptBundle\Configuration\Encrypted;

    /**
    * Developer
    *
    * @ORM\Entity
    * @ORM\Table(name="fos_user")
    */
    class Developer extends BaseUser
    {
       ...

       /**
        * @var string
        * @ORM\Column(name="firstname", type="string", length=255)
        * @Encrypted
        * @Assert\Length(
        *      min = 2,
        *      max = 50,
        *      minMessage = "profile.register.notification.name.too-short",
        *      maxMessage = "profile.register.notification.name.too-long"
        * )
        */
       private $firstname;

但是现在,提交表单时,我收到以下错误:

Field "firstname" is not a valid field of the entity "AppBundle\Entity\Developer" in PreUpdateEventArgs.

我做错了什么?

1 个答案:

答案 0 :(得分:2)

我使用a noticeably similar extension作为Doctrine / Zend,我遇到了同样的问题。我注意到它发生在:

  1. 我标记了一个字段@Encrypted(例如names
  2. 我在数据库中留下了未加密的值(例如bob
  3. 我写了那个表格行而没有更改未加密的值(例如(id, bob, x, y, z)
  4. 我将问题追溯到DoctrineEncryptSubscriber.php的源代码(这在vmelnik-ukraine / DoctrineEncryptBundle中是相同的):

    public function preUpdate(PreUpdateEventArgs $args) {
        $reflectionClass = new ReflectionClass($args->getEntity());
        $properties = $reflectionClass->getProperties();
        foreach ($properties as $refProperty) {
            if ($this->annReader->getPropertyAnnotation($refProperty, self::ENCRYPTED_ANN_NAME)) {
                $propName = $refProperty->getName();
                $args->setNewValue($propName, $this->encryptor->encrypt($args->getNewValue($propName))); // this line is the problem
            }
        }
    }
    

    $args->setNewValue(...)来电assertValidField($field),会检查@ {加密字段是否在entityChangeSet中...它不是,因为我没有做任何更改它。所以它引发了一个例外。当数据库中的值已经加密时,这种情况不会发生,因为entityChangeset具有旧值的加密值和新值的明文。

    我使用的补丁仅在我们实际更改字段时才调用setNewValue(),如下所示:

    public function preUpdate(PreUpdateEventArgs $args)
    {
        $reflectionClass = new ReflectionClass($args->getEntity());
        $properties = $reflectionClass->getProperties();
        foreach ($properties as $refProperty) {
            if ($this->annReader->getPropertyAnnotation($refProperty, self::ENCRYPTED_ANN_NAME)) {
                $propName = $refProperty->getName();
                if ($args->hasChangedField($propName)) {
                    $args->setNewValue($propName, $this->encryptor->encrypt($args->getNewValue($propName)));
                }
            }
        }
    }