Ваша проблема - это сочетание ответа mjh_ca и проблемы с вашей реализацией AbstractEntity
.
Поскольку вы показываете, что обращаетесь к полям сущностей следующим образом:
$user->userGroup->name;
Полагаю, ваш базовый класс AbstractEntity
использует магические методы __get()
и __set()
вместо правильных методов получения и установки:
function getUserGroup()
{
return $this->userGroup;
}
function setUserGroup(UserGroup $userGroup)
{
$this->userGroup = $userGroup;
}
Вы нарушаете ленивую загрузку:
"... всякий раз, когда вы получаете доступ к общедоступному свойству прокси-объекта, который еще не был инициализирован, возвращаемое значение будет нулевым. Doctrine не может подключиться к этому процессу и волшебным образом замедлить загрузку объекта."
Источник: Лучшие практики доктрины: не используйте публичные свойства для сущностей
Вместо этого вы должны обращаться к полям следующим образом:
$user->getUserGroup()->getName();
Вторая часть вашей проблемы точно такая, как написала mjh_ca - Zend_Auth
отсоединяет вашу сущность от менеджера сущностей, когда она сериализует ее для хранения в сеансе. Установка cascade={"merge"}
для вашей ассоциации не будет работать, потому что это фактическая сущность, которая отсоединена. Вы должны объединить десериализованную сущность User
с менеджером сущностей.
$detachedIdentity = Zend_Auth::getInstance()->getIdentity();
$identity = $em->merge($detachedIdentity);
Вопрос в том, как сделать это чисто. Вы можете рассмотреть реализацию магического метода __wakeup()
для вашей User
сущности, но это также противоречит лучшим доктринам ...
Источник: Реализация пробуждения или клонирования
Поскольку речь идет о Zend_Auth
, вы можете расширить Zend_Auth
и переопределить функцию getIdentity()
, чтобы она была осведомлена о сущности.
use Doctrine\ORM\EntityManager,
Doctrine\ORM\UnitOfWork;
class My_Auth extends \Zend_Auth
{
protected $_entityManager;
/**
* override otherwise self::$_instance
* will still create an instance of Zend_Auth
*/
public static function getInstance()
{
if (null === self::$_instance) {
self::$_instance = new self();
}
return self::$_instance;
}
public function getEntityManager()
{
return $this->_entityManager;
}
public function setEntityManager(EntityManager $entityManager)
{
$this->_entityManager = $entityManager;
}
public function getIdentity()
{
$storage = $this->getStorage();
if ($storage->isEmpty()) {
return null;
}
$identity = $storage->read();
$em = $this->getEntityManager();
if(UnitOfWork::STATE_DETACHED === $em->getUnitOfWork()->getEntityState($identity))
{
$identity = $em->merge($identity);
}
return $identity;
}
}
И затем добавьте функцию _init
к вашей начальной загрузке:
public function _initAuth()
{
$this->bootstrap('doctrine');
$em = $this->getResource('doctrine')->getEntityManager();
$auth = My_Auth::getInstance();
$auth->setEntityManager($em);
}
В этот момент вызов $user->getUserGroup()->getName();
должен работать как положено.