Вложенные поля коллекции в Sonata Admin (2.3)

У меня возникают проблемы с созданием формы для создания курса. Это часть моей схемы базы данных, для которой я пытаюсь создать форму:

введите описание изображения здесь

Поэтому я пытаюсь создать курс, где я могу создавать сеансы и даты (момент), прикрепленные к этому сеансу. Он должен выглядеть примерно так:

введите описание изображения здесь

В моем классе CourseAdmin у меня есть:

protected function configureFormFields(FormMapper $formMapper) { $formMapper ->add('name', 'text', array('label' => 'Naam')) ->add('description', 'textarea', array('label' => 'Beschrijving')) ->add('materials', 'textarea', array('label' => 'Benodigde materialen')) ->add('numberOfParticipants', 'number', array('label' => 'Aantal deelnembers')) ->add('numberOfDays', 'number', array('label' => 'Aantal dagen')) ->add('price', 'number', array('label' => 'Prijs')) ->add('priceKmo', 'number', array('label' => 'KMO-portefeuille Prijs')) ->add('location', 'sonata_type_model', array('expanded' => true, 'by_reference' => false, 'multiple' => true, 'btn_add' => false)) ->add('session', 'sonata_type_collection', array( 'by_reference' => false, 'type_options' => array( // Prevents the "Delete" option from being displayed 'delete' => false, 'delete_options' => array( // You may otherwise choose to put the field but hide it 'type' => 'hidden', // In that case, you need to fill in the options as well 'type_options' => array( 'mapped' => false, 'required' => false, ) ) ) ), array( 'edit' => 'inline', 'inline' => 'table', 'sortable' => 'position' )) ; } 

В моем классе SessionAdmin у меня есть:

 protected function configureFormFields(FormMapper $formMapper) { $formMapper ->add('type', 'text', array('label' => 'Type opleiding (Dag / Avond)')) ->add('moment', 'sonata_type_collection', array( 'by_reference' => false, 'type_options' => array( // Prevents the "Delete" option from being displayed 'delete' => false, 'delete_options' => array( // You may otherwise choose to put the field but hide it 'type' => 'hidden', // In that case, you need to fill in the options as well 'type_options' => array( 'mapped' => false, 'required' => false, ) ) ) ), array( 'edit' => 'inline', 'inline' => 'table', 'sortable' => 'position' )) ; } 

И в моем классе MomentAdmin у меня есть:

 protected function configureFormFields(FormMapper $formMapper) { $formMapper ->add('time', 'date', array('label' => 'Datum')) ; } 

Проблема в моей форме – когда я пытаюсь добавить момент (дату) в свою сессию, я получаю следующую ошибку:

FatalErrorException: Ошибка: вызов функции-члена getName () в нуле в строке /myproject/app/cache/dev/classes.php 9772

Таким образом, я могу добавить сеанс, но когда я пытаюсь добавить момент на мой сеанс, я получаю ошибку ….

Когда я смотрю в файле classes.php в правиле 9771 и 9772, есть:

 $childFormBuilder = $this->getChildFormBuilder($formBuilder, $elementId); $fieldDescription = $admin->getFormFieldDescription($childFormBuilder->getName()); 

$childFormBuilder имеет значение null .

Когда я смотрю на эту функцию, я получаю следующее:

 public function getChildFormBuilder(FormBuilder $formBuilder, $elementId) { foreach (new FormBuilderIterator($formBuilder) as $name => $formBuilder) { if ($name == $elementId) { return $formBuilder; } } return; } 

Когда я делаю var_dump $ name и $ elementId следующим образом:

 public function getChildFormBuilder(FormBuilder $formBuilder, $elementId) { foreach (new FormBuilderIterator($formBuilder) as $name => $formBuilder) { var_dump("name: " . $name); var_dump("elementId: " . $elementId); if ($name == $elementId) { return $formBuilder; } } die; return; } 

И нажмите на кнопку «Добавить новую», как показано на следующем рисунке:

введите описание изображения здесь

Затем я получаю этот вывод:

 name: s56cda71d2daa0_name elementId: s56cda71d2daa0_session_0_moment name: s56cda71d2daa0_description elementId: s56cda71d2daa0_session_0_moment name: s56cda71d2daa0_materials elementId: s56cda71d2daa0_session_0_moment name: s56cda71d2daa0_numberOfParticipants elementId: s56cda71d2daa0_session_0_moment name: s56cda71d2daa0_numberOfDays elementId: s56cda71d2daa0_session_0_moment name: s56cda71d2daa0_price elementId: s56cda71d2daa0_session_0_moment name: s56cda71d2daa0_priceKmo elementId: s56cda71d2daa0_session_0_moment name: s56cda71d2daa0_location elementId: s56cda71d2daa0_session_0_moment name: s56cda71d2daa0_session elementId: s56cda71d2daa0_session_0_moment 

Во всех моих сущностях у меня есть функция __toString. Пример моего объекта курса:

 public function __toString() { if(!is_null($this->name)) { return $this->name; } else{ return ""; } } 

Что может быть проблемой здесь? Я действительно застрял в этом. Я также опубликовал вопрос о реестре github для Sonata Admin, но нет ответов …

Мои сущности :

Суть курса :

 <?php namespace Studyx\EnrolmentBundle\Entity; use Doctrine\ORM\Mapping as ORM; /** * Course * * @ORM\Table(name="course") * @ORM\Entity */ class Course { /** * @var string * * @ORM\Column(name="name", type="string", length=255, nullable=false) */ private $name; /** * @var string * * @ORM\Column(name="description", type="text", nullable=false) */ private $description; /** * @var string * * @ORM\Column(name="materials", type="text", nullable=true) */ private $materials; /** * @var integer * * @ORM\Column(name="number_of_participants", type="integer", nullable=true) */ private $numberOfParticipants; /** * @var integer * * @ORM\Column(name="number_of_days", type="integer", nullable=true) */ private $numberOfDays; /** * @var string * * @ORM\Column(name="price", type="decimal", nullable=true) */ private $price; /** * @var string * * @ORM\Column(name="price_kmo", type="decimal", nullable=true) */ private $priceKmo; /** * @var integer * * @ORM\Column(name="ID", type="integer") * @ORM\Id * @ORM\GeneratedValue(strategy="IDENTITY") */ private $id; /** * @var \Doctrine\Common\Collections\Collection * * @ORM\ManyToMany(targetEntity="Studyx\EnrolmentBundle\Entity\Location", inversedBy="course") * @ORM\JoinTable(name="course_has_location", * joinColumns={ * @ORM\JoinColumn(name="course_ID", referencedColumnName="ID") * }, * inverseJoinColumns={ * @ORM\JoinColumn(name="location_ID", referencedColumnName="ID") * } * ) */ private $location; /** * @var \Doctrine\Common\Collections\Collection * * @ORM\OneToMany(targetEntity="Studyx\EnrolmentBundle\Entity\Session", mappedBy="course") */ private $session; /** * Add session * * @param \Studyx\EnrolmentBundle\Entity\Session $session * @return Session */ public function addSession(\Studyx\EnrolmentBundle\Entity\Session $session) { $this->session[] = $session; return $this; } /** * Remove session * * @param \Studyx\EnrolmentBundle\Entity\Session $session */ public function removeSession(\Studyx\EnrolmentBundle\Entity\Session $session) { $this->session->removeElement($session); } /** * Get session * * @return \Doctrine\Common\Collections\Collection */ public function getSession() { return $this->session; } /** * Constructor */ public function __construct() { $this->location = new \Doctrine\Common\Collections\ArrayCollection(); } public function __toString() { if(!is_null($this->name)) { return $this->name; } else{ return ""; } } /** * Set name * * @param string $name * @return Course */ public function setName($name) { $this->name = $name; return $this; } /** * Get name * * @return string */ public function getName() { return $this->name; } /** * Set description * * @param string $description * @return Course */ public function setDescription($description) { $this->description = $description; return $this; } /** * Get description * * @return string */ public function getDescription() { return $this->description; } /** * Set materials * * @param string $materials * @return Course */ public function setMaterials($materials) { $this->materials = $materials; return $this; } /** * Get materials * * @return string */ public function getMaterials() { return $this->materials; } /** * Set numberOfParticipants * * @param integer $numberOfParticipants * @return Course */ public function setNumberOfParticipants($numberOfParticipants) { $this->numberOfParticipants = $numberOfParticipants; return $this; } /** * Get numberOfParticipants * * @return integer */ public function getNumberOfParticipants() { return $this->numberOfParticipants; } /** * Set numberOfDays * * @param integer $numberOfDays * @return Course */ public function setNumberOfDays($numberOfDays) { $this->numberOfDays = $numberOfDays; return $this; } /** * Get numberOfDays * * @return integer */ public function getNumberOfDays() { return $this->numberOfDays; } /** * Set price * * @param string $price * @return Course */ public function setPrice($price) { $this->price = $price; return $this; } /** * Get price * * @return string */ public function getPrice() { return $this->price; } /** * Set priceKmo * * @param string $priceKmo * @return Course */ public function setPriceKmo($priceKmo) { $this->priceKmo = $priceKmo; return $this; } /** * Get priceKmo * * @return string */ public function getPriceKmo() { return $this->priceKmo; } /** * Get id * * @return integer */ public function getId() { return $this->id; } /** * Add location * * @param \Studyx\EnrolmentBundle\Entity\Location $location * @return Course */ public function addLocation(\Studyx\EnrolmentBundle\Entity\Location $location) { $this->location[] = $location; return $this; } /** * Remove location * * @param \Studyx\EnrolmentBundle\Entity\Location $location */ public function removeLocation(\Studyx\EnrolmentBundle\Entity\Location $location) { $this->location->removeElement($location); } /** * Get location * * @return \Doctrine\Common\Collections\Collection */ public function getLocation() { return $this->location; } } 

Объект сеанса :

  <?php namespace Studyx\EnrolmentBundle\Entity; use Doctrine\ORM\Mapping as ORM; /** * Session * * @ORM\Table(name="session") * @ORM\Entity */ class Session { /** * @var string * * @ORM\Column(name="type", type="string", length=45, nullable=false) */ private $type; /** * @var integer * * @ORM\Column(name="ID", type="integer") * @ORM\Id * @ORM\GeneratedValue(strategy="IDENTITY") */ private $id; /** * @var \Studyx\EnrolmentBundle\Entity\Course * * @ORM\ManyToOne(targetEntity="Studyx\EnrolmentBundle\Entity\Course", inversedBy="session") * @ORM\JoinColumns({ * @ORM\JoinColumn(name="course_ID", referencedColumnName="ID") * }) */ private $course; /** * @var \Doctrine\Common\Collections\Collection * * @ORM\OneToMany(targetEntity="Studyx\EnrolmentBundle\Entity\Moment", mappedBy="session") */ private $moment; /** * Add moment * * @param \Studyx\EnrolmentBundle\Entity\Moment $moment * @return Moment */ public function addMoment(\Studyx\EnrolmentBundle\Entity\Moment $moment) { $this->moment[] = $moment; return $this; } /** * Remove moment * * @param \Studyx\EnrolmentBundle\Entity\Moment $moment */ public function removeMoment(\Studyx\EnrolmentBundle\Entity\Moment $moment) { $this->moment->removeElement($moment); } /** * Get moment * * @return \Doctrine\Common\Collections\Collection */ public function getMoment() { return $this->moment; } public function __toString() { if(!is_null($this->type)) { return $this->type; } else{ return ""; } } /** * Set type * * @param string $type * @return Session */ public function setType($type) { $this->type = $type; return $this; } /** * Get type * * @return string */ public function getType() { return $this->type; } /** * Get id * * @return integer */ public function getId() { return $this->id; } /** * Set course * * @param \Studyx\EnrolmentBundle\Entity\Course $course * @return Session */ public function setCourse(\Studyx\EnrolmentBundle\Entity\Course $course = null) { $this->course = $course; return $this; } /** * Get course * * @return \Studyx\EnrolmentBundle\Entity\Course */ public function getCourse() { return $this->course; } } -  <?php namespace Studyx\EnrolmentBundle\Entity; use Doctrine\ORM\Mapping as ORM; /** * Session * * @ORM\Table(name="session") * @ORM\Entity */ class Session { /** * @var string * * @ORM\Column(name="type", type="string", length=45, nullable=false) */ private $type; /** * @var integer * * @ORM\Column(name="ID", type="integer") * @ORM\Id * @ORM\GeneratedValue(strategy="IDENTITY") */ private $id; /** * @var \Studyx\EnrolmentBundle\Entity\Course * * @ORM\ManyToOne(targetEntity="Studyx\EnrolmentBundle\Entity\Course", inversedBy="session") * @ORM\JoinColumns({ * @ORM\JoinColumn(name="course_ID", referencedColumnName="ID") * }) */ private $course; /** * @var \Doctrine\Common\Collections\Collection * * @ORM\OneToMany(targetEntity="Studyx\EnrolmentBundle\Entity\Moment", mappedBy="session") */ private $moment; /** * Add moment * * @param \Studyx\EnrolmentBundle\Entity\Moment $moment * @return Moment */ public function addMoment(\Studyx\EnrolmentBundle\Entity\Moment $moment) { $this->moment[] = $moment; return $this; } /** * Remove moment * * @param \Studyx\EnrolmentBundle\Entity\Moment $moment */ public function removeMoment(\Studyx\EnrolmentBundle\Entity\Moment $moment) { $this->moment->removeElement($moment); } /** * Get moment * * @return \Doctrine\Common\Collections\Collection */ public function getMoment() { return $this->moment; } public function __toString() { if(!is_null($this->type)) { return $this->type; } else{ return ""; } } /** * Set type * * @param string $type * @return Session */ public function setType($type) { $this->type = $type; return $this; } /** * Get type * * @return string */ public function getType() { return $this->type; } /** * Get id * * @return integer */ public function getId() { return $this->id; } /** * Set course * * @param \Studyx\EnrolmentBundle\Entity\Course $course * @return Session */ public function setCourse(\Studyx\EnrolmentBundle\Entity\Course $course = null) { $this->course = $course; return $this; } /** * Get course * * @return \Studyx\EnrolmentBundle\Entity\Course */ public function getCourse() { return $this->course; } } 

Moment Entity :

 <?php namespace Studyx\EnrolmentBundle\Entity; use Doctrine\ORM\Mapping as ORM; /** * Moment * * @ORM\Table(name="moment") * @ORM\Entity */ class Moment { /** * @var \DateTime * * @ORM\Column(name="time", type="datetime", nullable=false) */ private $time; /** * @var integer * * @ORM\Column(name="ID", type="integer") * @ORM\Id * @ORM\GeneratedValue(strategy="IDENTITY") */ private $id; /** * @var \Studyx\EnrolmentBundle\Entity\Session * * @ORM\ManyToOne(targetEntity="Studyx\EnrolmentBundle\Entity\Session") * @ORM\JoinColumns({ * @ORM\JoinColumn(name="session_ID", referencedColumnName="ID") * }) */ private $session; public function __toString() { if(!is_null($this->time)) { return $this->time; } else{ return ""; } } /** * Set time * * @param \DateTime $time * @return Moment */ public function setTime($time) { $this->time = $time; return $this; } /** * Get time * * @return \DateTime */ public function getTime() { return $this->time; } /** * Get id * * @return integer */ public function getId() { return $this->id; } /** * Set session * * @param \Studyx\EnrolmentBundle\Entity\Session $session * @return Moment */ public function setSession(\Studyx\EnrolmentBundle\Entity\Session $session = null) { $this->session = $session; return $this; } /** * Get session * * @return \Studyx\EnrolmentBundle\Entity\Session */ public function getSession() { return $this->session; } } 

ОБНОВИТЬ:

Я добавил несколько var_dumps к моей функции getChildFormBuilder следующим образом:

 public function getChildFormBuilder(FormBuilder $formBuilder, $elementId) { foreach (new FormBuilderIterator($formBuilder) as $name => $formBuilder) { if ($name == $elementId) { return $formBuilder; } } var_dump(__METHOD__); var_dump($elementId); var_dump(debug_backtrace()); return; } 

В результате получается следующее:

 string 'Sonata\AdminBundle\Admin\AdminHelper::getChildFormBuilder' (length=57) string 's56cdfa72c4dea_session_0_moment' (length=31) array (size=8) 0 => array (size=7) 'file' => string '/Applications/MAMP/htdocs/studyx_enrolments/app/cache/dev/classes.php' (length=69) 'line' => int 9774 'function' => string 'getChildFormBuilder' (length=19) 'class' => string 'Sonata\AdminBundle\Admin\AdminHelper' (length=36) 'object' => object(Sonata\AdminBundle\Admin\AdminHelper)[339] protected 'pool' => object(Sonata\AdminBundle\Admin\Pool)[104] ... 'type' => string '->' (length=2) 'args' => array (size=2) 0 => object(Symfony\Component\Form\FormBuilder)[436] ... 1 => &string 's56cdfa72c4dea_session_0_moment' (length=31) 1 => array (size=7) 'file' => string '/Applications/MAMP/htdocs/studyx_enrolments/vendor/sonata-project/admin-bundle/Controller/HelperController.php' (length=110) 'line' => int 95 'function' => string 'appendFormFieldElement' (length=22) 'class' => string 'Sonata\AdminBundle\Admin\AdminHelper' (length=36) 'object' => object(Sonata\AdminBundle\Admin\AdminHelper)[339] protected 'pool' => object(Sonata\AdminBundle\Admin\Pool)[104] ... 'type' => string '->' (length=2) 'args' => array (size=3) 0 => object(Studyx\EnrolmentBundle\Admin\CourseAdmin)[370] ... 1 => object(Studyx\EnrolmentBundle\Entity\Course)[415] ... 2 => &string 's56cdfa72c4dea_session_0_moment' (length=31) 2 => array (size=5) 'function' => string 'appendFormFieldElementAction' (length=28) 'class' => string 'Sonata\AdminBundle\Controller\HelperController' (length=46) 'object' => object(Sonata\AdminBundle\Controller\HelperController)[244] protected 'twig' => object(Twig_Environment)[220] ... protected 'helper' => object(Sonata\AdminBundle\Admin\AdminHelper)[339] ... protected 'pool' => object(Sonata\AdminBundle\Admin\Pool)[104] ... protected 'validator' => object(Symfony\Component\Validator\Validator)[340] ... 'type' => string '->' (length=2) 'args' => array (size=1) 0 => object(Symfony\Component\HttpFoundation\Request)[6] ... 3 => array (size=4) 'file' => string '/Applications/MAMP/htdocs/studyx_enrolments/app/bootstrap.php.cache' (length=67) 'line' => int 2957 'function' => string 'call_user_func_array' (length=20) 'args' => array (size=2) 0 => & array (size=2) ... 1 => & array (size=1) ... 4 => array (size=7) 'file' => string '/Applications/MAMP/htdocs/studyx_enrolments/app/bootstrap.php.cache' (length=67) 'line' => int 2931 'function' => string 'handleRaw' (length=9) 'class' => string 'Symfony\Component\HttpKernel\HttpKernel' (length=39) 'object' => object(Symfony\Component\HttpKernel\DependencyInjection\ContainerAwareHttpKernel)[300] protected 'container' => object(appDevDebugProjectContainer)[304] ... protected 'dispatcher' => object(Symfony\Component\HttpKernel\Debug\TraceableEventDispatcher)[299] ... protected 'resolver' => object(Symfony\Component\HttpKernel\Controller\TraceableControllerResolver)[249] ... 'type' => string '->' (length=2) 'args' => array (size=2) 0 => object(Symfony\Component\HttpFoundation\Request)[6] ... 1 => &int 1 5 => array (size=7) 'file' => string '/Applications/MAMP/htdocs/studyx_enrolments/app/bootstrap.php.cache' (length=67) 'line' => int 3060 'function' => string 'handle' (length=6) 'class' => string 'Symfony\Component\HttpKernel\HttpKernel' (length=39) 'object' => object(Symfony\Component\HttpKernel\DependencyInjection\ContainerAwareHttpKernel)[300] protected 'container' => object(appDevDebugProjectContainer)[304] ... protected 'dispatcher' => object(Symfony\Component\HttpKernel\Debug\TraceableEventDispatcher)[299] ... protected 'resolver' => object(Symfony\Component\HttpKernel\Controller\TraceableControllerResolver)[249] ... 'type' => string '->' (length=2) 'args' => array (size=3) 0 => object(Symfony\Component\HttpFoundation\Request)[6] ... 1 => &int 1 2 => &boolean true 6 => array (size=7) 'file' => string '/Applications/MAMP/htdocs/studyx_enrolments/app/bootstrap.php.cache' (length=67) 'line' => int 2333 'function' => string 'handle' (length=6) 'class' => string 'Symfony\Component\HttpKernel\DependencyInjection\ContainerAwareHttpKernel' (length=73) 'object' => object(Symfony\Component\HttpKernel\DependencyInjection\ContainerAwareHttpKernel)[300] protected 'container' => object(appDevDebugProjectContainer)[304] ... protected 'dispatcher' => object(Symfony\Component\HttpKernel\Debug\TraceableEventDispatcher)[299] ... protected 'resolver' => object(Symfony\Component\HttpKernel\Controller\TraceableControllerResolver)[249] ... 'type' => string '->' (length=2) 'args' => array (size=3) 0 => object(Symfony\Component\HttpFoundation\Request)[6] ... 1 => &int 1 2 => &boolean true 7 => array (size=7) 'file' => string '/Applications/MAMP/htdocs/studyx_enrolments/web/app_dev.php' (length=59) 'line' => int 29 'function' => string 'handle' (length=6) 'class' => string 'Symfony\Component\HttpKernel\Kernel' (length=35) 'object' => object(AppKernel)[5] protected 'bundles' => array (size=22) ... protected 'bundleMap' => array (size=22) ... protected 'container' => object(appDevDebugProjectContainer)[304] ... protected 'rootDir' => string '/Applications/MAMP/htdocs/studyx_enrolments/app' (length=47) protected 'environment' => string 'dev' (length=3) protected 'debug' => boolean true protected 'booted' => boolean true protected 'name' => string 'app' (length=3) protected 'startTime' => float 1456339594.61 protected 'loadClassCache' => array (size=2) ... 'type' => string '->' (length=2) 'args' => array (size=1) 0 => object(Symfony\Component\HttpFoundation\Request)[6] ... 

ОБНОВЛЕНИЕ 2:

Я изменил требование в моем composer.json на «sonata-project / admin-bundle»: «^2.4@dev» и обновил композитор. Но теперь я получаю эту ошибку:

ContextErrorException: предупреждение: недопустимое смещение строки «admin» в строке приложения / cache / dev / classes.php 10482

Ошибка в этой функции:

 public function getDashboardGroups() { $groups = $this->adminGroups; foreach ($this->adminGroups as $name => $adminGroup) { if (isset($adminGroup['items'])) { foreach ($adminGroup['items'] as $key => $item) { if (''!= $item['admin']) { $admin = $this->getInstance($item['admin']); if ($admin->showIn(Admin::CONTEXT_DASHBOARD)) { $groups[$name]['items'][$key] = $admin; } else { unset($groups[$name]['items'][$key]); } } else { unset($groups[$name]['items'][$key]); } } } if (empty($groups[$name]['items'])) { unset($groups[$name]); } } return $groups; } эта public function getDashboardGroups() { $groups = $this->adminGroups; foreach ($this->adminGroups as $name => $adminGroup) { if (isset($adminGroup['items'])) { foreach ($adminGroup['items'] as $key => $item) { if (''!= $item['admin']) { $admin = $this->getInstance($item['admin']); if ($admin->showIn(Admin::CONTEXT_DASHBOARD)) { $groups[$name]['items'][$key] = $admin; } else { unset($groups[$name]['items'][$key]); } } else { unset($groups[$name]['items'][$key]); } } } if (empty($groups[$name]['items'])) { unset($groups[$name]); } } return $groups; } не public function getDashboardGroups() { $groups = $this->adminGroups; foreach ($this->adminGroups as $name => $adminGroup) { if (isset($adminGroup['items'])) { foreach ($adminGroup['items'] as $key => $item) { if (''!= $item['admin']) { $admin = $this->getInstance($item['admin']); if ($admin->showIn(Admin::CONTEXT_DASHBOARD)) { $groups[$name]['items'][$key] = $admin; } else { unset($groups[$name]['items'][$key]); } } else { unset($groups[$name]['items'][$key]); } } } if (empty($groups[$name]['items'])) { unset($groups[$name]); } } return $groups; } эта public function getDashboardGroups() { $groups = $this->adminGroups; foreach ($this->adminGroups as $name => $adminGroup) { if (isset($adminGroup['items'])) { foreach ($adminGroup['items'] as $key => $item) { if (''!= $item['admin']) { $admin = $this->getInstance($item['admin']); if ($admin->showIn(Admin::CONTEXT_DASHBOARD)) { $groups[$name]['items'][$key] = $admin; } else { unset($groups[$name]['items'][$key]); } } else { unset($groups[$name]['items'][$key]); } } } if (empty($groups[$name]['items'])) { unset($groups[$name]); } } return $groups; } не public function getDashboardGroups() { $groups = $this->adminGroups; foreach ($this->adminGroups as $name => $adminGroup) { if (isset($adminGroup['items'])) { foreach ($adminGroup['items'] as $key => $item) { if (''!= $item['admin']) { $admin = $this->getInstance($item['admin']); if ($admin->showIn(Admin::CONTEXT_DASHBOARD)) { $groups[$name]['items'][$key] = $admin; } else { unset($groups[$name]['items'][$key]); } } else { unset($groups[$name]['items'][$key]); } } } if (empty($groups[$name]['items'])) { unset($groups[$name]); } } return $groups; } эта public function getDashboardGroups() { $groups = $this->adminGroups; foreach ($this->adminGroups as $name => $adminGroup) { if (isset($adminGroup['items'])) { foreach ($adminGroup['items'] as $key => $item) { if (''!= $item['admin']) { $admin = $this->getInstance($item['admin']); if ($admin->showIn(Admin::CONTEXT_DASHBOARD)) { $groups[$name]['items'][$key] = $admin; } else { unset($groups[$name]['items'][$key]); } } else { unset($groups[$name]['items'][$key]); } } } if (empty($groups[$name]['items'])) { unset($groups[$name]); } } return $groups; } не public function getDashboardGroups() { $groups = $this->adminGroups; foreach ($this->adminGroups as $name => $adminGroup) { if (isset($adminGroup['items'])) { foreach ($adminGroup['items'] as $key => $item) { if (''!= $item['admin']) { $admin = $this->getInstance($item['admin']); if ($admin->showIn(Admin::CONTEXT_DASHBOARD)) { $groups[$name]['items'][$key] = $admin; } else { unset($groups[$name]['items'][$key]); } } else { unset($groups[$name]['items'][$key]); } } } if (empty($groups[$name]['items'])) { unset($groups[$name]); } } return $groups; } 

Ошибки в строке: if (''!= $item['admin']) { .

В моем config.yml у меня есть:

 sonata_admin: title: Studyx title_logo: bundles/studyxenrolment/images/logo.png templates: layout: StudyxEnrolmentBundle:Admin:standard_layout.html.twig edit: StudyxEnrolmentBundle:CRUD:edit.html.twig user_block: StudyxEnrolmentBundle:Admin:user_block.html.twig # search: SonataAdminBundle:Core:search.html.twig # search_result_block: SonataAdminBundle:Block:block_search_result.html.twig dashboard: groups: studyx.admin.group.inschrijvingen: label: Inschrijvingen items: ~ item_adds: - sonata.admin.enrolment studyx.admin.group.algemeen: label: Algemeen items: ~ item_adds: - sonata.admin.course - sonata.admin.student studyx.admin.group.extra: label: Extra items: ~ item_adds: - sonata.admin.location blocks: - position: top class: col-md-12 type: sonata.admin.block.admin_list 

Поэтому я думаю, что там называется функция getDashboardGroups .

ОБНОВЛЕНИЕ 3:

В моем композиторе.json у меня есть следующее:

 "sonata-project/block-bundle": "~2.3", "sonata-project/admin-bundle": "^2.4@dev", "sonata-project/doctrine-orm-admin-bundle": "2.3.*", "sonata-project/formatter-bundle": "^2.3" 

Должен ли я обновить их все до ^ ^2.4@dev ?

Эта ошибка возникает из-за того, что у вас имеется более двух уровней вложенных форм коллекции, и в настоящее время она еще не поддерживается в любой версии sonata-admin.

От @rande (владелец) и сопровождающих сонаты по вопросам № 262 , № 1228 , № 1327 и № 1971 :

Это пока не поддерживается.

Вы также можете посмотреть этот старый PR # 1971, который должен решить проблему только для некоторых случаев использования.

Решение, которое я предлагаю вам, – это реализовать исправление, предоставленное последним открытым PR # 2985 .
Поскольку PR не сливается, вам нужно сказать, что композитор загружает его, а не текущую (нерабочую, как ожидалось) версию. (см. композитор и VCS ).

Надеюсь, что PR будет объединен в ближайшее время.
Пока это не будет, вы можете исправить свою проблему на данный момент, используя ее напрямую, как это делают некоторые люди.

ОБНОВИТЬ

Запрос Pull # 3553 был недавно объединен и исправил проблему вложенных коллекций на> 2 уровнях (вложенных в вложенные).

Чтобы получить фиксированный выпуск, вы должны использовать тег dev-master пакета (по крайней мере, из commit 926f159, представляющего слияние PR).

Я попробовал, и он хорошо работает со следующим требованием:

 // composer.json "require": { "sonata-project/admin-bundle": "^2.4@dev", ... }, 

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

Update2

По-видимому, ваш композитор не принимает последние изменения в ветке.
Исправление, предоставленное PR # 2739 , было объединено 6 дней назад.

Чтобы исправить это последнее (надеюсь), вам нужно изменить очень короткий блок кода в AddDepencyCallsCompilerPass расположенный в AddDepencyCallsCompilerPass vendor/sonata-project/admin-bundle/DependencyInjection/Compiler/AddDependencyCallsCompilerPass .

На строке 95 замените эту строку:

 $groupDefaults[$resolvedGroupName]['items'][] = $id; 

Тем:

 $groupDefaults[$resolvedGroupName]['items'][] = array( 'admin' => $id, 'label' => !empty($attributes['label']) ? $attributes['label'] : '', 'route' => '', 'route_params' => array(), ); 

Как это сделано PR (это единственное необходимое изменение, чтобы заставить его работать).

Я сделал бы исправление вручную, потому что он очень новый, и через несколько дней / недель выполните следующие команды:

composer clear-cache и composer update sonata-project/admin-bundle

Вы должны попробовать это сейчас, прежде чем добавлять исправление вручную, возможно, изменения будут добавлены.

Кроме того, вы можете использовать ссылку о композиторе и VCS, которые я дал в начале моего ответа, и требуем исправления напрямую. Это на ваше усмотрение, потому что это решение на данный момент.

И, наконец, будьте терпеливы, исправления вскоре будут объединены в стабильные релизы.

 public function getChildFormBuilder(FormBuilder $formBuilder, $elementId) { foreach (new FormBuilderIterator($formBuilder) as $name => $formBuilder) { if ($name == $elementId) { return $formBuilder; } } return; } 

Сбрасывание имени и элемента в цикле ничего не выполнит. Ваше приложение, очевидно, сработает, когда нет ничего, чтобы повторить его, затем он проходит цикл, выходит и переходит к последней строке, где возвращается NULL .

Я предлагаю вам сбросить идентификатор элемента сразу после цикла, как показано ниже. Использование debug_backtrace также может помочь:

 public function getChildFormBuilder(FormBuilder $formBuilder, $elementId) { foreach (new FormBuilderIterator($formBuilder) as $name => $formBuilder) { if ($name == $elementId) { return $formBuilder; } } var_dump(__METHOD__); var_dump($elementId); var_dump(debug_backtrace()); return; }