11

私はSymfony2.0.16で作業しています

UserProviderにメソッドgetRolesがあります

public function getRoles()
{
    /**
     * @var \Doctrine\Common\Collections\ArrayCollection $rol
     */
    return $this->rol->toArray();
}

私のRolエンティティにはロールインターフェイスがあります

class Rol implements \Symfony\Component\Security\Core\Role\RoleInterface
//...
public function getRole()
{
    return $this->getName();
}

しかし、ログインしようとすると、次のエラーが発生します

致命的なエラー:57行目のC:\ Users \ julian \ Code \ parqueadero \ vendor \ symfony \ src \ Symfony \ Bundle \ SecurityBundle \ DataCollector \ SecurityDataCollector.phpの非オブジェクトでメンバー関数getRole()を呼び出す

クラスSecurityDataCollectorを読み取ると、クロージャによってエラーがスローされます

array_map(function ($role){ return $role->getRole();}, $token->getRoles()

今、私はこれをに変更します

array_map(function ($role){ var_dump($role); return $role->getRole();}, $token->getRoles()

驚いたことに、$roleオブジェクトRolですが、なぜエラーが発生するのか理解できません。

4

3 に答える 3

14

問題はPHP 5.4 (私が使用している php)のバグある解決策を見つけましたserialize/unserializejson_encode/json_decode

class User implements \Serializable

//...

/**
 * Serializes the content of the current User object
 * @return string
 */
public function serialize()
{
    return \json_encode(
            array($this->username, $this->password, $this->salt,
                    $this->rol, $this->id));
}

/**
 * Unserializes the given string in the current User object
 * @param serialized
 */
public function unserialize($serialized)
{
    list($this->username, $this->password, $this->salt,
                    $this->rol, $this->id) = \json_decode(
            $serialized);
}

正しい名前のプロパティのみを変更する必要があります

于 2012-09-03T17:56:18.637 に答える
11

同じ問題(Windows、PHP 5.4.5)があり、5.4.7に更新しましたが、それでも機能しませんでした。それでも、メンテナンスの必要が少ない回避策を思いつきました(前述の記事で説明されているようにシリアル化関数を上書きする場合は、フィールドを追加/削除するときにそれらを最新の状態に保つ必要があります)。これまでのところ、それは私にとってはうまくいきますが、私が忘れていたかもしれない回避策に起因する他の問題がないことを願っています。次のようにユーザーのgetRoles()機能を変更するだけです。

/**
 * @inheritDoc
 */
public function getRoles()
{
    $roles = array();
    foreach ($this->userRoles as $role) {
        $roles[] = $role->getRole();
    }

    return $roles;
}

$role->getRole()はロール名を文字列として返すことに注意してください(例ROLE_ADMIN)。

于 2012-09-26T15:54:14.660 に答える
6

この問題の解決策は非常に簡単です。あなたUserRoleオブジェクトでの循環参照に関連するすべての問題。したがってUser::$rolesRole::$usersフィールドをシリアル化する必要はありません。

と を見てSymfony\Component\Security\Core\Authentication\Token\AbstractToken::__construct()くださいSymfony\Component\Security\Core\Authentication\Token\AbstractToken::serialize()

ご覧のとおり、Symfony はUserInterface::getRoles()シリアル化の前に呼び出してユーザーの役割を引き受けます。そして連載UserRoles分けて。

およびエンティティ\Serializableにインターフェイスを実装する必要があります。UserRole

例:

/**
 * Acme\Bundle\UserBundle\Entity\User
 * 
 * @ORM\Table(name="`user`")
 * @ORM\Entity(repositoryClass="Acme\Bundle\UserBundle\Entity\UserRepository")
 */
class User implements AdvancedUserInterface, EquatableInterface, \Serializable
{
    /**
     * @var integer $id
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @var string $username
     * 
     * @ORM\Column(type="string", length=30, unique=true)
     */
    private $username;

    /**
     * @var string $email
     * 
     * @ORM\Column(type="string", length=100, unique=true)
     */
    private $email;

    /**
     * @var string $salt
     *
     * @ORM\Column(type="string", length=40)
     */
    private $salt;

    /**
     * @var string $password
     *
     * @ORM\Column(type="string", length=128)
     */
    private $password;

    /**
     * @var boolean $isActive
     *
     * @ORM\Column(type="boolean")
     */
    private $isActive;

    /**
     * User's roles. (Owning Side)
     * 
     * @var ArrayCollection
     * 
     * @ORM\ManyToMany(targetEntity="Role", inversedBy="users")
     */
    private $roles;

    // .....

    /**
     * @see \Serializable::serialize()
     */
    public function serialize()
    {
        /*
         * ! Don't serialize $roles field !
         */
        return \serialize(array(
            $this->id,
            $this->username,
            $this->email,
            $this->salt,
            $this->password,
            $this->isActive
        ));
    }

    /**
     * @see \Serializable::unserialize()
     */
    public function unserialize($serialized)
    {
        list (
            $this->id,
            $this->username,
            $this->email,
            $this->salt,
            $this->password,
            $this->isActive
        ) = \unserialize($serialized);
    }

}
/**
 * Acme\Bundle\UserBundle\Entity\Role
 *
 * @ORM\Table(name="role")
 * @ORM\Entity
 * 
 */
class Role implements RoleInterface, \Serializable
{
    /**
     * @var integer $id
     *
     * @ORM\Column(type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @var string $role
     *
     * @ORM\Column(name="role", type="string", length=20, unique=true)
     */
    private $role;

    /**
     * Users in group (Inverse Side)
     * 
     * @var ArrayCollection
     * 
     * @ORM\ManyToMany(targetEntity="User", mappedBy="roles")
     */
    private $users;

    // .....    

    /**
     * @see \Serializable::serialize()
     */
    public function serialize()
    {
        /*
         * ! Don't serialize $users field !
         */
        return \serialize(array(
            $this->id,
            $this->role
        ));
    }

    /**
     * @see \Serializable::unserialize()
     */
    public function unserialize($serialized)
    {
        list(
            $this->id,
            $this->role
        ) = \unserialize($serialized);
    }
}

そして、すべてが正しくシリアライズ/アンシリアライズされます。

https://github.com/symfony/symfony/issues/3691でディスカスを参照してください。

参照: http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/cookbook/entities-in-session.html#serializing-entity-into-the-session

于 2012-11-06T17:01:05.050 に答える