条令-实体在分离后持有代理以进行会话管理


Doctrine - Entity holds proxy after detaching for session management

上下文

我需要使用Doctrine 2.3(使用PHP 5.4)将一个实体保持在会话中,一旦设置了$_SESSION变量,我就会遇到问题。

代码

我有以下课程:

Persistente

用于保存有关持久类的信息的超类。

/**
 * @MappedSuperclass
 */
abstract class Persistente
{
    public function __construct()
    {}
    public function getId()
    {
        return $this->id;
    }
    public function setId($id)
    {
        $this->id = $id;
    }
    /**
     * @Id
     * @GeneratedValue
     * @Column(type="integer")
     */
    protected $id;
}

Persona

保存一个人的基本信息。

/**
 * @Entity
 * @AttributeOverrides({
 *      @AttributeOverride(name="id",
 *          column=@Column(
 *              name="Persona_Id",
 *              type="integer"
 *          )
 *      )
 * })
 */
class Persona extends Persistente
{
    ...
    public function getContInformacion()
    {
        return $this->contInformacion;
    }
    public function setContInformacion(ContenedorInformacion $contInformacion)
    {
        $this->contInformacion = $contInformacion;
    }
    ...
    /**
     * @OneToOne(targetEntity="ContenedorInformacion", cascade={"all"}  )
     * @JoinColumn(name="ContInfo_Id", referencedColumnName="ContInfo_Id")
     */
    private $contInformacion;
}

参赛者信息

类,该类包含有关人员的信息,这些信息可以根据某些验证规则动态添加到对象中。

/**
 * @Entity
 * @AttributeOverrides({
 *      @AttributeOverride(name="id",
 *          column=@Column(
 *              name="ContInfo_Id",
 *              type="integer"
 *          )
 *      )
 * })
 */
class ContenedorInformacion extends Persistente
{
    ...
    /**
     * @OneToMany(targetEntity="UnidadInformacion", mappedBy="contInformacion", cascade={"all"}, indexBy="clave")
     */
    private $unidadesInformacion;
    /**
     * @OneToMany(targetEntity="Rol", mappedBy="contInformacion", cascade={"all"}, indexBy="clave")
     */
    private $roles;
}

问题

每当我将Persona添加到会话中时,就会执行以下代码:

public function login(Persona $t)
{
    if ($this->autorizar($t) === false) {
        return false;
    }
    $dao = new DAOManejadorMsSql();
    $daoPersona = $dao->fabricarDAO("'Codesin'Colegios'Personas'Persona");
    $t = $this->buscarPersona($t);
    $daoPersona->soltar($t);
    $dao->cerrar();
    $_SESSION['usuario'] = $t;
    if ($t->getContInformacion()->existeRol('SYSADMIN') === true) {
        return 'SYSADMIN';
    }
}

soltar()从EntityManager执行detach()方法,从而有效地使实体处于非托管状态。然而,Persona中的ContenedorInformacion对象是Doctrine生成的代理,而不是所需对象。为什么会发生这种情况?事先谢谢。

编辑:这就是错误。

Warning: require(C:'xampp'htdocs/Zeus/lib/vendor/DoctrineProxies/__CG__/Codesin/Colegios/Personas/ContenedorInformacion.php): failed to open stream: No such file or directory in C:'xampp'htdocs'Zeus'Common'Utils'autoload.php on line 8
Fatal error: require(): Failed opening required 'C:'xampp'htdocs/Zeus/lib/vendor/DoctrineProxies/__CG__/Codesin/Colegios/Personas/ContenedorInformacion.php' (include_path='.;C:'xampp'php'PEAR') in C:'xampp'htdocs'Zeus'Common'Utils'autoload.php on line 8

我不得不使用一种非常粗糙的方法。

我发现了以下内容:考虑到我不会立即重新附加信息,我重新制作了另一个ContenedorInformacion,它包含与代理完全相同的信息。考虑到ArrayCollection没有使用代理,而是使用整个对象,我这样做了。

public function login(Persona $t)
{
    if ($this->autorizar($t) === false) {
        return false;
    }
    $dao = new DAOManejadorMsSql();
    $daoPersona = $dao->fabricarDAO("'Codesin'Colegios'Personas'Persona");
    $t = $this->buscarPersona($t);
    $daoPersona->soltar($t);
    $dao->cerrar();
    /***** NEW LINES START HERE *****/
    $contInfo = new ContenedorInformacion();
    $contInfo->setId($t->getContInformacion()->getId());
    $contInfo->setUnidadesInformacion(new ArrayCollection($t->getContInformacion()->getUnidadesInformacion()->toArray()));
    $contInfo->setRoles(new ArrayCollection($t->getContInformacion()->getRoles()->toArray()));
    $t->setContInformacion($contInfo);
    /***** NEW LINES END HERE *****/
    $_SESSION['usuario'] = $t;
    if ($t->getContInformacion()->existeRol('SYSADMIN') === true) {
        return 'SYSADMIN';
    }
}

它很脏,但很有魅力。