当我们尝试setFilters()
/
getFilters()
时,我们都面临过这个问题:“实体必须被管理”
那么如何以通用方式处理过滤器的会话存储,以避免
merging
和 detaching
或 re-hydrating
手动实体?
请参阅下面的答案。
嗯,工作中的一些同事(@benji07)写了这个:
/**
* Set filters
* @param string $name Name of the key to store filters
* @param array $filters Filters
*/
public function setFilters($name, array $filters = array())
{
foreach ($filters as $key => $value) {
// Transform entities objects into a pair of class/id
if (is_object($value)) {
if ($value instanceof ArrayCollection) {
if (count($value)) {
$filters[$key] = array(
'class' => get_class($value->first()),
'ids' => array()
);
foreach ($value as $v) {
$identifier = $this->getDoctrine()->getEntityManager()->getUnitOfWork()->getEntityIdentifier($v);
$filters[$key]['ids'][] = $identifier['id'];
}
}
}
elseif (!$value instanceof \DateTime) {
$filters[$key] = array(
'class' => get_class($value),
'id' => $this->getDoctrine()->getEntityManager()->getUnitOfWork()->getEntityIdentifier($value)
);
}
}
}
$this->getRequest()->getSession()->set(
$name,
$filters
);
}
/**
* Get Filters
* @param string $name Name of the key to get filters
* @param array $filters Filters
*
* @return array
*/
public function getFilters($name, array $filters = array())
{
$filters = array_merge(
$this->getRequest()->getSession()->get(
$name,
array()
),
$filters
);
foreach ($filters as $key => $value) {
// Get entities from pair of class/id
if (is_array($value) && isset($value['class']) && isset($value['id'])) {
$filters[$key] = $this->getDoctrine()->getEntityManager()->find($value['class'], $value['id']);
} elseif (isset($value['ids'])) {
$data = $this->getDoctrine()->getEntityManager()->getRepository($value['class'])->findBy(array('id' => $value['ids']));
$filters[$key] = new ArrayCollection($data);
}
}
return $filters;
}
它适用于基本实体和多值选择
PS:不要忘记为
ArrayCollection
添加使用声明
免责声明,我们不知道这是否是一种好的做法,但我们知道至少有一个限制:您必须确保尝试在会话中保存的对象具有
id
(为 99.9%)案例)