【问题标题】:Doctrine Proxy does not initializeDoctrine Proxy 未初始化
【发布时间】:2013-12-18 12:08:50
【问题描述】:

当我将文件上传到 Symfony 时,它是按应有的方式上传的。我使用了 Symfony 文件上传教程,并对其进行了修改以满足我的需要。

if($form->isValid())
{
    $em = $this->oStarter->getEntityManager();

    // Save file to database
    $uploadedFile = new ProfilePicture();
    $uploadedFile->setFile($formData["profile_picture"]);
    $user->setProfilePicture($uploadedFile);
    $uploadedFile->setUser($user);

    $em->persist($uploadedFile);
    $em->persist($user);

    $em->flush();

    // Other things like Twig templates etc..

此代码用于上传图片并将其设置为用户的头像。通过 Controller 中的$this->getUser() 找到用户。当我在刷新后输出实体时,它会向我显示一个有效实体的转储,就像我所期望的那样。

当我访问该用户的个人资料页面时,找不到该图像。当我检查 MySQL 表时,我发现 ProfilePicture 的有效条目具有正确的 ID 和路径。正如您所期望的,用户还具有对 ProfilePicture 的 ID 的引用。相反,该页面向我显示了以下转储:

$avatar = $user->getProfilePicture();
$path = $avatar->getWebPath();
Debug::dump($avatar);


object(stdClass)#938 (8) 
{
  ["__CLASS__"]=>
  string(42) "Takeabyte\CoreBundle\Entity\ProfilePicture"
  ["__IS_PROXY__"]=>
  bool(true)
  ["__PROXY_INITIALIZED__"]=>
  bool(false)
  ["id"]=>
  NULL
  ["user"]=>
  object(stdClass)#1011 (52) {
    ["__CLASS__"]=>
    string(32) "Takeabyte\CoreBundle\Entity\User"
    ["id"]=>
    int(11)
    // lots of user info
    }
  ["file"]=>
  NULL
  ["path"]=>
  NULL
  ["temp"]=>
  NULL
}

转储显示没有设置路径。即使调用了 Proxy 的一个函数,实际数据似乎也没有被加载。我做错了什么?

编辑 实体如下:

/**
 * @author Tim Cocu
 * @author Rick Slinkman
 *
 * @ORM\Entity
 * @ORM\Table(name="profilepictures")
 * @Database(target="client")
 */
class ProfilePicture extends Image
{
    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @ORM\OneToOne(targetEntity="\Takeabyte\CoreBundle\Entity\User", mappedBy="profilePicture")
     */
    private $user;

    // accessors and mutators
}

/**
 * Description of Image
 *
 * @ORM\MappedSuperclass
 * @Database(target="client")
 * @author Rick Slinkman (r.slinkman@take-a-byte.eu)
 */
class Image extends MediaFile
{
    /**
     * @param ClassMetadata $metadata
     */
    public static function loadValidatorMetadata(ClassMetadata $metadata)
    {
        $metadata->addPropertyConstraint('file', new Assert\File(array(
            'maxSize' => 6000000,
            'mimeTypes' => array(
                "image/jpeg",
                "image/png",
                "image/gif"
            ),
        )));
    }

    // other functions
}

/**
 * Standard container of an uploaded media file
 * @author Rick Slinkman
 * @author Tim Cocu
 * 
 * @ORM\HasLifecycleCallbacks
 * @ORM\MappedSuperclass
 * @Database(target="client")
 * 
 * Based on:
 * http://symfony.com/doc/current/cookbook/doctrine/file_uploads.html
 */
class MediaFile 
{
    /**
     * @Assert\File(maxSize="6000000")
     */
    protected $file;

    /**
     * @ORM\Column(type="string", length=255, nullable=true)
     */
    protected $path;

    /**
     * Temporary storage on file moving.
     */
    protected $temp;

    /**
     * @ORM\PrePersist()
     * @ORM\PreUpdate()
     */
    public function preUpload()
    {
        if (null !== $this->getFile()) 
        {
            // do whatever you want to generate a unique name
            $filename = sha1(uniqid(mt_rand(), true));
            $this->path = $filename.'.'.$this->getFile()->guessExtension();
        }
    }

    /**
     * @ORM\PostPersist()
     * @ORM\PostUpdate()
     */
    public function upload()
    {
        if (null === $this->getFile()) 
        {
            return;
        }

        // if there is an error when moving the file, an exception will
        // be automatically thrown by move(). This will properly prevent
        // the entity from being persisted to the database on error
        $this->getFile()->move($this->getUploadRootDir(), $this->path);

        // check if we have an old image
        if (isset($this->temp)) 
        {
            // delete the old image
            unlink($this->getUploadRootDir().'/'.$this->temp);
            // clear the temp image path
            $this->temp = null;
        }
        $this->file = null;
    }

    /**
     * @ORM\PostRemove()
     */
    public function removeUpload()
    {
        if ($file = $this->getAbsolutePath()) 
        {
            unlink($file);
        }
    }

    // other functions 
}

/**
 * @author: Jordy - j.deruijter@take-a-byte.eu
 * @author: Rick - r.slinkman@take-a-byte.eu
 * @author: Tim - t.cocu@take-a-byte.eu
 * @since: 25-10-13
 *
 * @ORM\Entity
 * @ORM\Table(name="fos_user_user")
 * @Database(target="client")
 */
class User extends BaseUser
{
    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;

    // Lots of data

    /**
     * @var ProfilePicture
     * @ORM\OneToOne(targetEntity="\Takeabyte\CoreBundle\Entity\ProfilePicture", inversedBy="user")
     */
    protected $profilePicture;

    // Even more data
}

【问题讨论】:

  • 清除缓存后会发生什么?
  • 清除缓存无效。我已尝试清除 prod 和 dev 缓存,但没有结果。
  • 可以添加实体的代码吗?
  • 还有Takeabyte\CoreBundle\Entity\User? :)
  • 抱歉,忘了那个 ;)

标签: php mysql symfony doctrine-orm


【解决方案1】:

我想我大约一年前遇到过类似的错误。

您会看到,当您进行身份验证时,User 实体的序列化(文本)版本存储在您的会话中。当您访问防火墙后的页面时,它会被反序列化并再次转换为User。但是,由于您与ProfilePicture 的关系不急切,并且在序列化期间,此属性未序列化。代理对象不可序列化...

因此,当它尝试从会话中检索经过身份验证的用户时,其 $profilePicture 属性设置为 NULL

这是你的情况吗?

想法 #1:

  1. User 实体中将关系设置为EAGER
  2. 尝试设置 always_authenticate_before_granting: true 在你的 confir.ymlsecurity 块)

我相信这会导致安全性进入数据库并在每次页面访问时重新获取 User 实体...

想法 #2:

刷新您的用户实体并手动获取profilePicture。也许您也可以在会话中单独存储用户个人资料图片?

【讨论】:

  • 哇,这成功了!我尝试了您的第一个想法,并在关系中添加了渴望获取。在我的User 实体中,关系现在如下所示:/** * @var ProfilePicture * @ORM\OneToOne(targetEntity="\Takeabyte\CoreBundle\Entity\ProfilePicture", inversedBy="user", fetch="EAGER") */ protected $profilePicture; 之后,我通过删除app/cache 中的所有文件夹来清除缓存。图片立刻出现了!非常感谢。
  • 我只想说一声“谢谢!”对于这个回应。我沮丧地把头撞在桌子上,试图弄清楚为什么信息没有显示出来。使用您的第一个想法后,它立即生效。谢谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-11
  • 1970-01-01
  • 2018-12-13
相关资源
最近更新 更多