Symfony2: тайм-аут с вложенным объектом JMS Serializer

Попытка сериализовать объект с 3 вложенными свойствами объекта приводит к

Ошибка: достигнут максимальный уровень вложенности функций "250"

Entity Volunteer имеет OneToOne с Person, OnetoMany с фокусами и OneToMany с навыками. Если ответ сериализован $volunteer->getPerson();, происходит ожидаемый ответ json. Однако $volunteer->getFocuses(); также вызывает ошибку максимального уровня вложенности.

Обновлять

Когда xdebug max увеличивается, это просто истекает через 30 секунд в среде разработки.

Фрагмент контроллера:

$em = $this->getDoctrine()->getManager();
$serializer = \JMS\Serializer\SerializerBuilder::create()->build();
$volunteer = $em->getRepository('HOTV2Bundle:Volunteer')->find($id);
$response = new JsonResponse($serializer->serialize($volunteer, 'json'));

person geoB    schedule 26.12.2013    source источник
comment
Если это поможет, stackoverflow.com/questions/13308047/   -  person M Khalid Junaid    schedule 27.12.2013
comment
@MKhalidJunaid: Спасибо, но я не вижу, как xdebug повлияет на сериализатор.   -  person geoB    schedule 27.12.2013
comment
я думаю, это потому, что вы включили xdebug, если это так, попробуйте увеличить лимит в php.ini   -  person M Khalid Junaid    schedule 27.12.2013
comment
@MKhalidJunaid: Ах, симптом, а не болезнь. Либо повышая максимальное значение, либо полностью удаляя ссылки xdebug из php.ini, время ожидания сценария истекает через 30 секунд в dev. Итак, теперь я вижу, как xdebug влияет на производительность, но исходная проблема сериализации объекта с вложенными объектами остается нерешенной.   -  person geoB    schedule 27.12.2013


Ответы (3)


Ваша проблема с максимальным уровнем вложенности указывает на то, что вы пытаетесь сериализовать гораздо больше, чем вам нужно.

Укажите поля, которые вы хотите сериализовать с конфигурацией сущности JMS (аннотации, xml или yml). Я использую аннотации. Я всегда начинаю с аннотирования своего объекта/документа с помощью @ExclusionPolicy("all "), а затем явно @представить свойства и отношения.

@Accessor и @VirtualProperty очень полезны для настройки вывода. Вместо того, чтобы сериализовать связанные фокусы как объекты, вы можете аннотировать метод getFocusTitles с помощью @VirtualProperty для сериализации простого массива заголовков, если это все, что вам нужно.

Конечно, вам нужно будет аннотировать связанные объекты, как указано выше.

person dylan oliver    schedule 29.07.2014
comment
Ваш вклад оценен и может пригодиться - он был вознагражден. С тех пор я сделал серьезный редизайн и больше не пытаюсь сериализовать этот объект. - person geoB; 30.07.2014

Это сообщение об ошибке xdebug. Это означает, что у вас есть рекурсивные функции, которые вызывают себя более 250 раз.

Вы должны увеличить уровень вложенности в вашем php.ini.

xdebug.max_nesting_level = 1000

в противном случае вы можете установить уровень вложенности в свой скрипт с помощью

ini_set('xdebug.max_nesting_level', 1000)
person René Höhle    schedule 26.12.2013
comment
Спасибо. Даже при значительно расширенном уровне вложенности xdebug кажется, что сериализатор не оценивает все отношения в моей модели, поэтому время ожидания истекает. С тех пор я создал функцию для создания массива, который имитирует структуру, которую я ищу. Затем массив идеально сериализуется. - person geoB; 27.12.2013
comment
Что происходит, когда вы отключаете xdebug в своем php.ini? А вы уверены, что уровень вложенности действительно выше 250? - person René Höhle; 27.12.2013
comment
Цитирую моего дружелюбного соседа phpinfo(); xdebug.max_nesting_level 1000 - person geoB; 27.12.2013

Предполагая, что существует бесконечная рекурсия, пытающаяся сериализовать объект, я построил следующий массив, который можно сериализовать. Функция принимает объект Volunteer в качестве параметра.

public function createVolunteerArray($vol) {
    $p = $vol->getPerson();
    $person = array(
        'id' => $p->getId(),
        'firstName' => $p->getFirstName(),
        'lastName' => $p->getLastName(),
        'email' => $p->getEmail(),
        'address' => $p->getAddress(),
        'city' => $p->getCity(),
        'state' => $p->getState(),
        'zip' => $p->getZip(),
    );
    $f = $vol->getFocuses();
    $focusArray = array();
    foreach ($f as $foc) {
        $focus['id'] = $foc->getId();
        $focus['focus'] = $foc->getFocus();
        $focusArray[] = $focus;
    }
    $s = $vol->getSkills();
    $skillArray = array();
    foreach ($s as $sk) {
        $skill['id'] = $sk->getId();
        $skill['skill'] = $sk->getSkill();
        $skillArray[] = $skill;
    }
    $volunteer = array(
        'person' => $person,
        'focuses' => $focusArray,
        'skills' => $skillArray,
    );
    return $volunteer;
}
person geoB    schedule 31.12.2013