Sonata Admin (2.3) 中的嵌套集合字段

2023-12-25

我在创建用于创建课程的表单时遇到问题。这是我的数据库方案的一部分,我正在尝试为其创建一个表单:

所以我想做的是创建一个课程,我可以在其中创建会话和附加到该会话的日期(时刻)。它应该看起来像这样:

In my 课程管理我有的课:

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'
        ))
    ;
}

In my 会话管理我有的课:

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'
        ))
        ;
}

而在我的时刻管理我有的课:

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

我的表单中的问题是,当我尝试在会话中添加时刻(日期)时,出现以下错误:

FatalErrorException:错误:在 /myproject/app/cache/dev/classes.php 第 9772 行中对 null 调用成员函数 getName()

因此,我可以添加一个会话,但是当我尝试在会话中添加一个时刻时,我收到错误...。

当我查看文件时类.php规则 9771 和 9772 中有:

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

The $childFormBuilder is null.

当我查看该函数时,我得到了这个:

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

当我像这样执行 $name 和 $elementId 的 var_dump 时:

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 "";
    }
}

这里可能有什么问题?我真的被这个问题困扰了。我还发布了一个issue http://github.com/sonata-project/SonataAdminBundle/issues/3583在 Sonata Admin 的 github 存储库上,但没有答案......

我的实体:

课程实体:

<?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;

/**
 * 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;
    }
}

UPDATE:

我在我的函数中添加了一些 var_dumps获取ChildFormBuilder像这样:

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”并使用composer进行更新。但现在我收到这个错误:

ContextErrorException:警告:非法字符串偏移“admin” app/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;
}

网上的错误:if (''!= $item['admin']) { .

In my 配置.yml I have:

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

所以我认为函数获取仪表板组在那里被称为。

更新3:

In my 作曲家.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 尚不支持它。

From @rande https://github.com/sonata-project/SonataAdminBundle/issues/262#issuecomment-2773237(所有者)和奏鸣曲维护者的问题#262 https://github.com/sonata-project/SonataAdminBundle/issues/262, #1228 https://github.com/sonata-project/SonataAdminBundle/issues/1228, #1327 https://github.com/sonata-project/SonataAdminBundle/issues/1327 and #1971 https://github.com/sonata-project/SonataAdminBundle/pull/1971 :

目前还不支持这个......

你也可以看看这个旧的 PR#1971 https://github.com/sonata-project/SonataAdminBundle/pull/1971这应该只能解决某些用例的问题。

我建议您的解决方案是实施上次打开的 PR 提供的修复#2985 https://github.com/sonata-project/SonataAdminBundle/pull/2985/commits.
由于 PR 未合并,因此您需要告诉 Composer 加载它而不是当前(未按预期工作)版本。 (看作曲家和 VCS https://getcomposer.org/doc/05-repositories.md#loading-a-package-from-a-vcs-repository).

希望PR尽快合并。
在此之前,请随时直接使用它来解决您的问题,就像很多人所做的那样。

UPDATE

The 请求请求#3553 https://github.com/sonata-project/SonataAdminBundle/pull/3553最近已合并并修复了 > 2 层嵌套集合的问题(嵌套在嵌套中)。

要获得固定版本,您必须使用dev-master捆绑包的标签(至少来自提交 926f159 https://github.com/sonata-project/SonataAdminBundle/commit/926f15924f612c75366472d99bedf8c6ca25ea68代表 PR 的合并)。

我尝试了一下,它可以很好地满足以下要求:

// composer.json

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

我希望您可以轻松升级捆绑包以获得修复。

Update2

显然,您的作曲家没有采用分支的最后更改。
PR 提供的修复#2739 https://github.com/sonata-project/SonataAdminBundle/pull/2739已于 6 天前合并。

要解决最后一个问题(希望),您需要更改中的一个非常短的代码块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 and composer update sonata-project/admin-bundle

您应该在手动添加修复之前尝试一下,也许会添加更改。

另外,您可以使用我在答案开头给出的有关 Composer 和 VCS 的链接,并直接要求修复。这是您自己的欣赏,因为它是目前的解决方案。

最后,请耐心等待,修复程序将很快合并到稳定版本中。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Sonata Admin (2.3) 中的嵌套集合字段 的相关文章

  • 搜索引擎如何找到相关内容? [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 Google 在解析网络时如何找到相关内容 例如 Google 使用 PHP 原生 DOM 库来解析内
  • 通过 Ajax 加载内容时,WORDPRESS 音频播放器未加载,MediaElement.js 未应用

    我正在创建一个 WordPress 主题 当我使用 ajax 加载内容时 它不会将 MediaElements js 应用于我的音频播放器 因此不会显示音频 我认为这是因为 MediaElement js 加载了 wp footer 并且此
  • 在 symfony2 中加载应用程序的自定义配置文件

    我正在开发一个symfony2应用程序 我试图包含我的自定义 yaml 配置位于 src AppBundle Resources Config general yml 我已按照此处提供的示例进行操作http symfony com doc
  • 删除PHP字符串中所有不匹配的字符?

    我有一个文本 我想从中删除所有不属于以下字符的字符 所需字符 0123456789 abcdefghijklmnopqrstuvwxyz n 最后一个是我确实想保留的 n 换行符 要匹配除列出的字符之外的所有字符 请使用反转字符集 http
  •  
    标记内删除

    我制作了简单的 BBCode 脚本 一切正常 但后来我使用了一个 javascript 库来美化我的代码 pre pre 现在我面临的唯一问题是 br 每行代码后面的标签 pre pre tags 所以问题是我怎样才能删除 br 标记哪些在
  • posts_search 中的自定义查询

    如何使用此查询作为我的自定义搜索查询 add filter posts search my search is perfect 20 2 function my search is perfect search wp query sWord
  • 从 smarty 访问 PHP 文件的变量(本地或全局)

    我有一个 php 文件 其中包含一些本地和全局变量 例如 foo 从此文件中调用 smarty 对象 如何在不更改 PHP 文件的情况下从 smarty 脚本访问 foo Thanks 如果你有一个名为 BASE 的常量变量 并且定义如下
  • 从 .phar 存档中提取文件

    对于 Phar 文件 我完全错过了一些东西 我正在安装一个需要 phpunit pdepend 和其他依赖项的项目 我将它们作为 phar 文件获取 但是 我无法使用命令行工具 php 命令 从中提取文件 我用谷歌搜索了这个问题 但没有发现
  • 使用 SSL 证书验证 Web 浏览器

    是否可以使用 ssl 证书对 Web 浏览器进行身份验证 假设我在应用程序中存储私钥 有什么方法可以从浏览器读取密钥并尝试基于该私钥进行身份验证 您可以使用 SSL TLS 客户端证书身份验证来对浏览器 用户进行身份验证 服务器必须请求客户
  • 在 PHP 中使用 phpseclib 时出现 RSA 问题

    我正在尝试在 phpseclib 中使用 RSA 实现 我认为在函数中执行一次代码并重新使用该函数会更容易 当我尝试向代码发送短信时 我收到一条错误消息 提示 解密错误 测试还让我意识到每次代码运行时密文都是不同的 所以我显然在那里做错了什
  • PHP 与 MySQL 查询性能( if 、 函数 )

    我只看到这个artice http www onextrapixel com 2010 06 23 mysql has functions part 5 php vs mysql performance 我需要知道在这种情况下什么是最好的表
  • PHP 中只保留数组的前 N ​​个元素? [复制]

    这个问题在这里已经有答案了 有没有办法只保留数组的前 N 个 例如 10 个 元素 我知道有array pop 但是有没有更好 更优雅的方法呢 您可以使用array slice http php net array slice or arr
  • php 错误 fopen(): 文件名不能为空

    发送带有附件代码的电子邮件工作正常 最近我们已将文件传输到另一个托管服务器 idk 发生了什么 它显示以下错误 警告 fopen 第 106 行 home hugerecruitmetnt public html validatecva p
  • 如何在 PHP 中从 IP 地址/国家/地区名称查找时区 ID?

    谁能告诉我 PHP 中是否有任何方法可以从 IP 地址或国家 地区名称获取时区区域 例如 亚洲 加尔各答 描述 我正在尝试根据他 她的国家 地区设置用户时区 我从他的 IP 地址获取用户所在国家 地区 但我需要该国家 地区的时区区域 例如
  • php,统计字符并删除超过140个字符的内容

    我需要一个 PHP 函数来计算短语的字符数 如果短语长度超过 140 个字符 则此函数应删除所有其他字符并在短语末尾添加三个点 例如我们有 message I am what I am and you are what you are et
  • 内部 while 循环不工作

    这是我项目网页上的代码片段 这里我想显示用户选择的类别 然后想显示属于该类别的主题 在那里 用户可以拥有多个类别 这没有问题 我可以在第一个 while 循环中打印所有这些类别 问题是当我尝试打印主题时 结果只显示一行 但每个类别中有更多主
  • ini_set 'session.gc_maxlifetime' 为 1 天

    If I do ini set session gc maxlifetime 86400 这是否意味着用户可以将浏览器留在同一页面 非活动状态 最多 1 天 而不必担心会话被垃圾收集并被注销 如果服务器配置不支持此功能会发生什么 它会给我一
  • 为什么 Composer 降级了我的包?

    php composer phar update这样做了 删除了 2 3 0 软件包并安装了整个 2 2 5 Zend Framework php composer phar update Loading composer reposito
  • 如何使用 PHPExcel 库从 Excel 获取日期

    我正在尝试使用 PHPExcel 从 Excel 获取日期 但我没有得到日期 我得到的字符串值不是 1970 以来的秒数 我尝试过的代码是 InvDate trim excel gt getActiveSheet gt getCell B
  • 对具有混合类型值的数组进行数字排序

    我有一个像这样的混合数组 fruits array lemon Lemon 20 banana apple 121 40 50 然后申请sort 其功能如下 sort fruits SORT NUMERIC foreach fruits a

随机推荐

  • NPM - 无许可证字段

    我尝试在 Visual Studio Code 的集成终端上使用以下命令 npm 安装 但是 已显示错误 它说 npm WARN package json Angular 电子邮件受保护 cdn cgi l email protection
  • 在数组中查找总和为 k 的两个元素[重复]

    这个问题在这里已经有答案了 可能的重复 给定两个数组 a 和 b 找到所有元素对 a1 b1 使得 a1 属于数组 A b1 属于数组 B 其总和 a1 b1 k https stackoverflow com questions 3815
  • 将 Crypto++ AES 加密移植到 PHP 的 mcrypt 时密钥大小不正确

    早些时候 我设法将一些 C CryptoPP Rijndael 128 CBC 代码移植到 MCrypt PHP 但现在我遇到了 CFB 模式的问题 C 和 PHP 结果不匹配 第一个字节匹配 但这可能是巧合 其他一切都不是 通过一些诊断
  • 从“popup.html”访问当前选项卡 DOM 对象?

    我正在开发 Google Chrome 浏览器的扩展程序 我无法弄清楚如何从 popup html 页面访问当前选项卡 DOM 对象 有什么建议么 默认情况下 在 popup js popup html 中 文档 对象仅指扩展的弹出窗口的文
  • 检测到要删除的 iOS 应用程序?

    For my iOS应用程序 当用户a要删除该应用程序时 会触发什么事件 没有这样的事 抱歉 你能做的最好的事情就是检查UIApplicationWillTerminateNotification通知 但更重要的是 当应用程序转换到后台时保
  • 在 C# 中,':this' 意味着什么[重复]

    这个问题在这里已经有答案了 我在这个链接中遇到了一些c http www asp net signalr overview getting started tutorial server broadcast with aspnet sign
  • 排除 SSRS 报告的“日期/时间”参数中的时间

    在我的 SSRS 报告中 我希望允许用户指定一个日期 用于过滤报告上的数据 当我这样做时 参数还包括时间 是否可以只允许用户选择日期而不显示时间 我还可以给它一个当前日期的默认值吗 我已经应用于报告参数的步骤 将参数设置为 日期 时间 数据
  • 使用 EPPlus 从 Excel 获取所有单元格值

    我想使用 EPPlus 库中的 ExcelWorksheet 对象并检索所有具有值及其位置的单元格 归根结底 我想要一本与此类似的词典 Dictionary
  • 我如何在 OS X 下覆盖 malloc()、calloc()、free() 等?

    假设使用最新的 XCode 和 GCC 覆盖内存分配函数的正确方法是什么 我猜也是 new delete 运算符 调试内存分配器对于游戏来说太慢了 我只需要一些基本的统计数据 我可以自己做 影响最小 由于钩子 我知道它在 Linux 中很容
  • 返回值时类型不兼容

    我想在地图上显示带有绘制线的图像 并为图像中的每个部分 几条连接线 制作单独的图像 我写了这段代码 public BufferedImage getLineImage BufferedImage lineImage null Buffere
  • 如果父进程退出,如何防止子进程不成为僵尸进程

    我的主进程生成一个子进程 如果主进程被杀死 子进程将被分配 ppid 为 1 当子进程退出时 它将成为僵尸进程 因为 init 尚未对该子进程调用 wait 有没有办法避免这种情况呢 init will call wait 在它继承的进程上
  • 如何在ubuntu下使用adb USB连接android设备[关闭]

    Closed 这个问题需要细节或清晰度 help closed questions 目前不接受答案 其他人可能在 ubuntu linux 下遇到了 adb 调试问题 症状是 USB 连接的 Android 设备的可用性 例如与日食 你可以
  • 组合框数据绑定错误 - 如果以编程方式失去焦点,则不会写入值

    我有一个空白表单 我在其中添加了默认值ComboBox TextBox 仅用于接收焦点 以及Label 组合框具有设置为表单上的私有属性的数据绑定 Setup Private Sub FormLoad sender As System Ob
  • @RequestBody 在发出 POST 请求时给出空 JsonObject

    我有以下方法 RequestMapping value app write method RequestMethod POST consumes application json produces application json publ
  • 如何添加用户脚本js文件作为Chrome扩展?

    我目前一直在为 Chrome 开发用户脚本 这些脚本可以在不使用 Tampermonkey 的情况下运行 今天我在 Chrome 扩展中添加了一个第三方扩展 userscript js UserScript name job changer
  • 如何让 python 程序运行而不是在记事本中打开?

    我在打开 py 文件时遇到一些问题 我有一个程序调用这个 py 文件 即路径名 example py file txt 但它不是运行 python 程序 而是在记事本中打开它 我如何让它运行 程序本身接收一个文件 并创建一个更可读的输出 编
  • 未找到框架 Protobuf

    I am facing an issue wherein I needed to use FirebaseRemoteConfig for my iOS app I included the following pod pod Fireba
  • 具有自己的文件偏移量的重复文件描述符

    如何从现有文件描述符创建新文件描述符 使得新描述符不共享文件表中相同的内部文件结构 条目 具体来说 诸如文件偏移量 最好是权限 共享和模式 之类的属性不应在新旧文件描述符之间共享 在 Windows 和 Linux 下 dup 将复制文件描
  • mingw 3.4.5 缺少 dlfcn.h?

    难道是我的mingw 3 4 5安装有问题 还是其他一些图书馆提供了这个 如果您想知道 dlfcn h 是定义 dlopen 和 dlclose 等内容的地方 所以它应该是相当标准的 dlfcn win32 http code google
  • Sonata Admin (2.3) 中的嵌套集合字段

    我在创建用于创建课程的表单时遇到问题 这是我的数据库方案的一部分 我正在尝试为其创建一个表单 所以我想做的是创建一个课程 我可以在其中创建会话和附加到该会话的日期 时刻 它应该看起来像这样 In my 课程管理我有的课 protected