lphuberdeau / Neo4j-PHP-OGM

A doctrine2 style library to access neo4j graphs
156 stars 45 forks source link

Autoload proxy classes #64

Closed frne closed 10 years ago

frne commented 10 years ago

Unserializing and Entity e.g. from the session ends up in a catchable fatal error, because the generated proxy class neo4jProxyFrne_Bundle_Neo4jUserBundle_Entity_User is not loaded at this time:

Catchable Fatal Error: Object of class __PHP_Incomplete_Class could not be converted to string...

The unserialized Entity (e.g. a User) looks like this:

object(__PHP_Incomplete_Class)[419]
  public '__PHP_Incomplete_Class_Name' => string 'neo4jProxyFrne_Bundle_Neo4jUserBundle_Entity_User' (length=49)
  protected 'username' => string 'frank' (length=5)
  protected 'password' => string 'ZB0b9NjRer/eV9UzH0h9YqFkOleMsZSv1LHkE3NoKdpnxbFnzwcPKLDOWoq+ctea9yU61jf/g2G2gJyTQdgXAg==' (length=88)
  protected 'salt' => string 'NTM0MDJkZjczZDU5ZDMuNDg5NzA3MDUxZmI0NmVlM2RmY2FhZmY0OWYzODdiMzgzNWRjNmE5ODRmODdhZTMx' (length=84)
  protected 'roles' => 
    array (size=2)
      0 => string 'ROLE_USER' (length=9)
      1 => string 'ROLE_ADMIN_CREATED' (length=18)
  protected 'id' => int 50

A possible solution will be autoloading of the generated proxy classes. As a temporary fix, I dehydrated the proxy class to the original entity, but thats not a real solution of the problem I think.

Concrete use-case is to use Neo4j as a Symfony2 user provider's storage engine

The unhydrated class looks like this:

<?php

namespace Frne\Bundle\Neo4jUserBundle\Entity;

use HireVoice\Neo4j\Annotation as OGM;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\User\EquatableInterface;

/**
 * @OGM\Entity(labels="User")
 */
class User implements UserInterface, EquatableInterface
{
    /**
     * @var string
     * @OGM\Auto
     */
    protected $id;

    /**
     * @var string
     * @OGM\Property
     * @OGM\Index
     */
    protected $username;

    /**
     * @var string
     */
    protected $plainPassword;

    /**
     * @var string
     * @OGM\Property
     */
    protected $password;

    /**
     * @var string
     * @OGM\Property
     */
    protected $salt;

    /**
     * @var array
     * @OGM\Property
     */
    protected $roles;

    /**
     * @param string|null $username
     * @param string|null $password
     * @param string|null $salt
     * @param array|null $roles
     */
    public function __construct($username = null, $password = null, $salt = null, array $roles = array('ROLE_USER'))
    {
        $this->username = $username;
        $this->password = $password;
        $this->salt = $salt;
        $this->roles = $roles;
    }

    /**
     * @return string
     */
    public function __toString()
    {
        return strval($this->id);
    }

    /**
     * @return string
     */
    public function getId()
    {
        return $this->id;
    }

   // getters and setter for the props

    public function eraseCredentials()
    {
        $this->plainPassword = null;
    }

    public function isEqualTo(UserInterface $user)
    {
        if (!$user instanceof User) {
            return false;
        }

        if ($this->password !== $user->getPassword()) {
            return false;
        }

        if ($this->getSalt() !== $user->getSalt()) {
            return false;
        }

        if ($this->username !== $user->getUsername()) {
            return false;
        }

        return true;
    }
}
lphuberdeau commented 10 years ago

This is a known issue. The proxy needs to be initialized, which cannot happen during unserialization. You can use getEntity() to extract the plain php object before serializing and use reload() on the entity manager when you need to access more than what is serialized. On Apr 6, 2014 8:22 AM, "Frank Neff" notifications@github.com wrote:

Unserializing and Entity e.g. from the session ends up in a catchable fatal error, because the generated proxy class neo4jProxyFrne_Bundle_Neo4jUserBundle_Entity_User is not loaded at this time:

_Catchable Fatal Error: Object of class __PHP_IncompleteClass could not be converted to string...

The unserialized Entity (e.g. a User) looks like this:

object(PHP_Incomplete_Class)[419] public 'PHP_Incomplete_Class_Name' => string 'neo4jProxyFrne_Bundle_Neo4jUserBundle_Entity_User' (length=49) protected 'username' => string 'frank' (length=5) protected 'password' => string 'ZB0b9NjRer/eV9UzH0h9YqFkOleMsZSv1LHkE3NoKdpnxbFnzwcPKLDOWoq+ctea9yU61jf/g2G2gJyTQdgXAg==' (length=88) protected 'salt' => string 'NTM0MDJkZjczZDU5ZDMuNDg5NzA3MDUxZmI0NmVlM2RmY2FhZmY0OWYzODdiMzgzNWRjNmE5ODRmODdhZTMx' (length=84) protected 'roles' => array (size=2) 0 => string 'ROLE_USER' (length=9) 1 => string 'ROLE_ADMIN_CREATED' (length=18) protected 'id' => int 50

A possible solution will be autoloading of the generated proxy classes. As a temporary fix, I dehydrated the proxy class to the original entity, but thats not a real solution of the problem I think.

Concrete use-case is to use Neo4j as a Symfony2 user provider's storage engine

The unhydrated class looks like this:

<?php namespace Frne\Bundle\Neo4jUserBundle\Entity; use HireVoice\Neo4j\Annotation as OGM;use Symfony\Component\Security\Core\User\UserInterface;use Symfony\Component\Security\Core\User\EquatableInterface; /* * @OGM\Entity(labels="User") /class User implements UserInterface, EquatableInterface{ /* * @var string * @OGM\Auto / protected $id;

/**     * @var string     * @OGM\Property     * @OGM\Index     */
protected $username;

/**     * @var string     */
protected $plainPassword;

/**     * @var string     * @OGM\Property     */
protected $password;

/**     * @var string     * @OGM\Property     */
protected $salt;

/**     * @var array     * @OGM\Property     */
protected $roles;

/**     * @param string|null $username     * @param string|null $password     * @param string|null $salt     * @param array|null $roles     */
public function __construct($username = null, $password = null, $salt = null, array $roles = array('ROLE_USER'))
{
    $this->username = $username;
    $this->password = $password;
    $this->salt = $salt;
    $this->roles = $roles;
}

/**     * @return string     */
public function __toString()
{
    return strval($this->id);
}

/**     * @return string     */
public function getId()
{
    return $this->id;
}

/**     * @return string     */
public function getUsername()
{
    return $this->username;
}

/**     * @param string $username     * @return UserInterface|User     */
public function setUsername($username)
{
    $this->username = $username;

    return $this;
}

/**     * @return string     */
public function getPlainPassword()
{
    return $this->plainPassword;
}

/**     * @param string $plainPassword     * @return UserInterface|User     */
public function setPlainPassword($plainPassword)
{
    $this->plainPassword = $plainPassword;

    return $this;
}

/**     * @return string     */
public function getPassword()
{
    return $this->password;
}

/**     * @param string $password     * @return UserInterface|User     */
public function setPassword($password)
{
    $this->password = $password;

    return $this;
}

/**     * @return null|string     */
public function getSalt()
{
    return $this->salt;
}

/**     * @param string $salt     * @return UserInterface|User     */
public function setSalt($salt)
{
    $this->salt = $salt;

    return $this;
}

/**     * @return array|\Symfony\Component\Security\Core\Role\Role[]     */
public function getRoles()
{
    return $this->roles;
}

/**     * @param array $roles     * @return UserInterface|User     */
public function setRoles(array $roles)
{
    $this->roles = $roles;

    return $this;
}

public function eraseCredentials()
{
    $this->plainPassword = null;
}

public function isEqualTo(UserInterface $user)
{
    if (!$user instanceof User) {
        return false;
    }

    if ($this->password !== $user->getPassword()) {
        return false;
    }

    if ($this->getSalt() !== $user->getSalt()) {
        return false;
    }

    if ($this->username !== $user->getUsername()) {
        return false;
    }

    return true;
}}

Reply to this email directly or view it on GitHubhttps://github.com/lphuberdeau/Neo4j-PHP-OGM/issues/64 .

frne commented 10 years ago

KTHX ;)