Chr*_*ber 15 php doctrine serializer jmsserializerbundle
我在我的Zend项目中使用Doctrine 2 ORM,并且需要在几种情况下将我的实体序列化为JSON.
ATM我使用Querybuilder并加入我需要的所有表.但是我的序列化程序导致学说延迟加载每个相关的实体,导致相当大的数据量并引发递归.
现在我正在寻找一种完全禁用Doctrines延迟加载行为的方法.
我选择数据的方法如下:
$qb= $this->_em->createQueryBuilder()
->from("\Project\Entity\Personappointment", 'pa')
->select('pa', 't', 'c', 'a', 'aps', 'apt', 'p')
->leftjoin('pa.table', 't')
->leftjoin('pa.company', 'c')
->leftjoin('pa.appointment', 'a')
->leftjoin('a.appointmentstatus', 'aps')
->leftjoin('a.appointmenttype', 'apt')
->leftjoin('a.person','p')
Run Code Online (Sandbox Code Playgroud)
我希望我的结果集只包含选定的表和关联.
任何帮助将不胜感激.
Dav*_*Lin 11
在最新版本的JMSSerializer中,您应该关注的地方是
JMS\Serializer\EventDispatcher\Subscriber\DoctrineProxySubscriber
Run Code Online (Sandbox Code Playgroud)
代替
Serializer\Handler\DoctrineProxyHandler
Run Code Online (Sandbox Code Playgroud)
要覆盖默认的延迟加载行为,应该定义自己的事件订阅者.
在你的app/config.yml添加中:
parameters:
...
jms_serializer.doctrine_proxy_subscriber.class: Your\Bundle\Event\DoctrineProxySubscriber
Run Code Online (Sandbox Code Playgroud)
你可以将类从JMS\Serializer\EventDispatcher\Subscriber\DoctrineProxySubscriber复制到你的\ Bundle\Event\DoctrineProxySubscriber并注释掉$ object - > __ load(); 线
public function onPreSerialize(PreSerializeEvent $event)
{
$object = $event->getObject();
$type = $event->getType();
// If the set type name is not an actual class, but a faked type for which a custom handler exists, we do not
// modify it with this subscriber. Also, we forgo autoloading here as an instance of this type is already created,
// so it must be loaded if its a real class.
$virtualType = ! class_exists($type['name'], false);
if ($object instanceof PersistentCollection) {
if ( ! $virtualType) {
$event->setType('ArrayCollection');
}
return;
}
if ( ! $object instanceof Proxy && ! $object instanceof ORMProxy) {
return;
}
//$object->__load(); Just comment this out
if ( ! $virtualType) {
$event->setType(get_parent_class($object));
}
}
Run Code Online (Sandbox Code Playgroud)
在Doctrine中寻找答案后,我的团队发现JMS Serializer是"问题".它自动触发了Doctrine Proxies的使用.我们编写了一个Patch for JMS Serializer以避免延迟加载.
我们实现了自己的DoctrineProxyHandler,它不会触发Doctrines延迟加载机制并在我们的SerializationHandlers数组中注册它.
class DoctrineProxyHandler implements SerializationHandlerInterface {
public function serialize(VisitorInterface $visitor, $data, $type, &$handled)
{
if (($data instanceof Proxy || $data instanceof ORMProxy) && (!$data->__isInitialized__ || get_class($data) === $type)) {
$handled = true;
if (!$data->__isInitialized__) {
//don't trigger doctrine lazy loading
//$data->__load();
return null;
}
$navigator = $visitor->getNavigator();
$navigator->detachObject($data);
// pass the parent class not to load the metadata for the proxy class
return $navigator->accept($data, get_parent_class($data), $visitor);
}
return null;
}
Run Code Online (Sandbox Code Playgroud)
现在我可以简单地选择我的表,加入我需要的关联 - 我的JSON将只包含我选择的数据而不是无限深度关联和递归:)
$qb= $this->_em->createQueryBuilder()
->from("\Project\Entity\Personappointment", 'pa')
->select('pa', 't', 'c', 'a')
->leftjoin('pa.table', 't')
->leftjoin('pa.company', 'c')
->leftjoin('pa.appointment', 'a')
Run Code Online (Sandbox Code Playgroud)
JSON将只包含
{
Personappointment: { table {fields}, company {fields}, appointment {fields}}
Personappointment: { table {fields}, company {fields}, appointment {fields}}
Personappointment: { table {fields}, company {fields}, appointment {fields}}
.
.
}
Run Code Online (Sandbox Code Playgroud)