Я конвертирую свое работающее в остальном приложение Symfony2 для использования MongoDB через Doctrine-ODM. У меня работает подавляющее большинство системы, но я не могу заставить работать часть ролей пользователей. Я могу войти в систему, но тогда к пользователю не привязаны роли.
Соответствующие классы документов представлены здесь со всем, кроме того, что имеет значение.
Пользователь
<?php
namespace XXXXX\UserBundle\Document;
use Doctrine\ODM\MongoDB\Mapping\Annotations as MongoDB;
use Doctrine\Common\Collections\ArrayCollection;
use XXXXX\UserBundle\Interfaces\UserInterface;
/**
*
* @MongoDB\Document( collection="user")
*
*/
class User implements UserInterface {
/**
* @MongoDB\Id
*/
protected $id;
/**
* @MongoDB\ReferenceMany(targetDocument="Group")
*/
protected $groups;
/**
* Constructor
*/
public function __construct() {
$this->groups = new ArrayCollection();
$this->salt = base_convert(sha1(uniqid(mt_rand(), true)), 16, 36);
}
public function getRoles() {
$array = array();
//parse the roles down to an array
foreach ($this->getGroups() as $group) {
/* @var $group Group */
foreach ($group->getRoles() as $role) {
/* @var $role Role */
if(!$role->getName())
throw new \Exception('Role must exist in group: '.$group->getName().' with ID: '.$group->getId().'.');
$array[$role->getName()] = $role->getName();
}
}
sort($array);
return $array;
}
/**
* Get groups
*
* @return Doctrine\Common\Collections\Collection
*/
public function getGroups() {
return $this->groups;
}
}
Группа
<?php
namespace XXXXX\UserBundle\Document;
use Doctrine\ODM\MongoDB\Mapping\Annotations as MongoDB;
use XXXXX\UserBundle\Interfaces\UserInterface;
use XXXXX\UserBundle\Interfaces\RoleInterface;
use XXXXX\UserBundle\Interfaces\GroupInterface;
use Doctrine\Common\Collections\ArrayCollection;
/**
* @MongoDB\Document( collection="user_group" )
*/
class Group implements GroupInterface {
/**
* @MongoDB\Id
*/
protected $id;
/**
* @MongoDB\String
* @var string
*/
protected $name;
/**
* @MongoDB\ReferenceMany(targetDocument="User")
*/
protected $users;
/**
* @MongoDB\ReferenceMany(targetDocument="Role", inversedBy="groups")
*/
protected $roles;
/**
* Constructor
*/
public function __construct() {
$this->users = new ArrayCollection();
$this->roles = new ArrayCollection();
}
/**
* Get id
*
* @return integer
*/
public function getId()
{
return $this->id;
}
/**
* Get name
*
* @return string
*/
public function getName()
{
return $this->name;
}
/**
* Get roles
*
* @return Doctrine\Common\Collections\Collection
*/
public function getRoles()
{
return $this->roles;
}
}
Роль
<?php
namespace XXXXX\UserBundle\Document;
use Doctrine\ODM\MongoDB\Mapping\Annotations as MongoDB;
use XXXXX\UserBundle\Interfaces\UserInterface;
use XXXXX\UserBundle\Interfaces\GroupInterface;
use XXXXX\UserBundle\Interfaces\RoleInterface;
use Doctrine\Common\Collections\ArrayCollection;
/**
* @MongoDB\Document( collection="user_role")
*/
class Role implements RoleInterface {
/**
* @MongoDB\Id
*/
protected $id;
/**
* @MongoDB\String
* @var string
*/
protected $name;
/**
* @MongoDB\String
* @var string
*/
protected $description;
/**
* @MongoDB\ReferenceMany(targetDocument="Group", mappedBy="roles")
*/
protected $groups;
/**
* Set name
*
* @param string $name
* @return RoleInterface
*/
public function setName($name) {
$this->name = $name;
return $this;
}
/**
* Get name
*
* @return string
*/
public function getName() {
return $this->name;
}
public function getId() {
return $this->id;
}
public function getDescription() {
return $this->description;
}
public function setDescription($description) {
$this->description = $description;
}
}
Я использую фикстуры для загрузки данных в базу данных, и данные в MongoDB выглядят следующим образом. (Я удалил дополнительные элементы данных.)
Пользователь.
{ "_id" : ObjectId("5091a7241311fae01f00000d"), "groups" : [ DBRef("user_group", ObjectId("5091a7241311fae01f00000b")), DBRef("user_group", ObjectId("5091a7241311fae01f00000c")) ] }
Группы, на которые ссылается Пользователь. (Это из запроса, который запускается Symfony2)
db.user_group.find({ "_id": { "$in": { "5091a7241311fae01f00000b":ObjectId("5091a7241311fae01f00000b"), "5091a7241311fae01f00000c": ObjectId("5091a7241311fae01f00000c") } } }).sort([ ]);
{ "_id" : ObjectId("5091a7241311fae01f00000b"), "name" : "Base.Users", "roles" : [ DBRef("user_role", ObjectId("5091a7241311fae01f000009")) ] }
{ "_id" : ObjectId("5091a7241311fae01f00000c"), "name" : "AdminPortal.Base", "roles" : [ DBRef("user_role", ObjectId("5091a7241311fae01f000009")), DBRef("user_role", ObjectId("5091a7241311fae01f00000a")) ] }
И, наконец, роли, на которые ссылаются группы. (Также взято из точного запроса, выполняемого Symfony2)
db.user_role.find({ "_id": { "$in": { "5091a7241311fae01f000009": ObjectId("5091a7241311fae01f000009") } } }).sort([ ]);
{ "_id" : ObjectId("5091a7241311fae01f000009"), "name" : "ROLE_USER", "description" : "Role required for all system users." }
Далее вызывается исключение в функции getRoles() для пользователя и возвращается следующий текст.
Роль должна существовать в группе: Base.Users с идентификатором: 5091a7241311fae01f00000b.
Проблема в том, что роли запрашиваются из базы данных, но затем не заполняются в объект роли. Я могу убедиться, что они загружаются, так как, когда я комментирую исключение, оно запускается и пытается добавить правильное количество ролей в группу. Проблема в том, что свойство имени роли имеет значение NULL. Сам объект роли является сохраненным и загруженным объектом, как если бы я выполнял команду print_r($role);exit; непосредственно перед оператором if я получу чрезвычайно рекурсивный вывод, который демонстрируют объекты доктрины. Единственное, что не происходит, это то, что свойства «имя» (и другие) не загружаются из базы данных.
Любое понимание того, как я могу решить эту проблему, будет очень признательно. Спасибо.