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) 中的嵌套集合字段 的相关文章

  • 如何将 javascript 倒计时器与服务器同步

    我有一个拍卖网站 有一个 JavaScript 计时器倒计时 由于某种原因 15 20 分钟后 该计时器比实际时间滞后 20 30 秒 在 1 小时的过程中 JavaScript 倒计时器可能会关闭至少 2 3 分钟 这让用户感到困惑 因为
  • 执行 mysqli->set_charset() 的永久方法?

    将我可以找到的字符集的所有配置文件和运行时选项设置为 utf 8 后 使用 php 建立的新 mysqli 连接的字符集仍然设置为 latin1 这实际上意味着我必须调用 mysqli gt set charset utf8 每次我连接 m
  • Composer 自动加载始终是第一位的

    我在一个遗留项目中使用作曲家 该项目有很多没有命名空间的类 重构不是一个选项 这是一个非常庞大的应用程序 但所有新模块都完全符合 psr 4 遗留代码有它自己的自动加载方法 使用类映射 非常有效 我的问题是 无论我以什么顺序添加自动加载器方
  • 无法在WordPress的functions.php中使用php fopen()函数

    我正在尝试简单地运行 fopen 函数 php 并且也尝试过test phpWordPress 模板文件 但这不起作用 如果我将 test php 文件和 csv 文件移动到主题文件夹之外的位置 那么它第一次可以工作 function cs
  • ruby 中可以做动态变量吗? [复制]

    这个问题在这里已经有答案了 我可以通过其他方式实现这种动态性质 但这引起了我的好奇 Ruby 中有类似的机制吗 varname hello varname world echo hello Output world 您可以使用以下方法实现类
  • PHP Google Drive API - 文件上传仅作为“无标题”-文件或只是没有内容

    我正在寻找一种解决方案 通过 PHP 将文件从我的根服务器直接上传到我的 Google Drive 帐户 授权工作正常 但当我尝试传输文件 例如 test jpg 时 它只是在 Google Drive 中创建一个名为 Untitled 的
  • 联系表 7 根据用户选择立即发送给多个联系人

    您好 我正在 WordPress 联系表单 7 中创建联系表单 如果用户选择 全部 我想立即向多个收件人发送电子邮件 我看过这个 但似乎没有记录您是否可以一次发送给多个收件人http contactform7 com selectable
  • 有没有办法清除所有会话中的一些会话数据?

    一般来说 我有以下场景 从数据库中获取产品及其相关数据 将获取的数据转换为 php product 对象 在会话中缓存产品对象 缓存是只读的 即客户在网站上查看产品 但也有类似的电话getProductIdsByCategory categ
  • ZF2:如何将参数传递给转发插件,然后我可以在转发它们的方法中获取这些参数?

    我有一个 Action 方法Foo需要参数的控制器 public function fooAction one two a one b two 我需要从某些方法的其他方法转发到该方法Boo控制器 这些参数之一必须是引用参数 唯一的例子就是手
  • PHP:数据库连接类构造方法

    我是面向对象编程的新手 最初 我是在类内部和构造函数外部定义变量并为其赋值 但是在今天的 Java OOP 课程之后 我被告知这是不好的风格 应该避免 这是我模拟的原始 PHP 数据库连接类 class DatabaseConnection
  • jqgrid嵌套子网格第四级子网格总是返回子网格的第一个rowid

    jqGrid v4 3 2 ie9荣获7家企业 我使用以下代码来生成子网格 http www trirand com blog jqgrid jqgrid html http www trirand com blog jqgrid jqgr
  • 关联数组与 SplObjectStorage

    我正在编写代码来管理一组独特的对象 该代码的第一个原型使用关联数组 基本上就像我一直这样做的方式一样 然而 我也热衷于利用 PHP 的更现代版本中添加的功能 例如 SplObjectStorage 1 这样做 部分是作为一种学习经验 部分是
  • Magento:查找包含产品的订单

    Magento 有没有办法找到包含给定产品的所有订单 如果可以通过管理面板来完成就更好了 报告 gt 产品 gt 订购的产品向我提供了产品销售的日期以及包含该产品的订单数量 但我需要知道哪些特定订单包含该产品 谢谢你 这个问题我在另一个问题
  • 设置基于 PHP 定时器的函数

    我有一个 php 文件test php 我想要echo or print5 秒后 即在浏览器调用 加载或打开 php 文件后不久 成功 顺便说一句 有时我可能想在特定的时间间隔后执行 初始化某些函数 如何使用 php 执行面向时间的任务 例
  • 来自外部文件的 PHP 变量?

    编辑 完成的解决方案 工作代码 所以 这是我的一个朋友帮我想出来的 这是我在 K2 items php 文件中使用的部分 div class fb comments div
  • PHP:分离业务逻辑和表示逻辑,值得吗? [复制]

    这个问题在这里已经有答案了 可能的重复 为什么要在 PHP 中使用模板系统 https stackoverflow com questions 436014 why should i use templating system in php
  • (mysql, php) 如何在插入数据之前获取auto_increment字段值?

    我正在将图像文件上传到存储服务器 在上传之前 我应该编写文件名 其中包含自动增量值 例如 12345 filename jpg 在插入数据库之前如何获取自动增量值 我只看到一种解决方案 插入空行 获取其自增值 删除这一行 使用 p 1 中的
  • 使用 jQuery 将值发送到 $_GET

    我正在使用一个 PHP 脚本 该脚本正在通过 GET 等待两个值 我正在尝试使用 jQuery 传递这两个值 而这正是我不太擅长的地方 这是我得到的代码 有人能指出我正确的方向吗 谢谢 function xrate id rating aj
  • 使用 foreach 进行复杂的多维关联数组处理

    我不得不再次问这个问题 抱歉 但我在尝试处理这个数组时遇到了问题 我尝试了几种不同的方法 但没有一个是正确的 这是数组 Array search gt Array response gt Array errors gt number of
  • 散列 hash_hmac 时,Convert.ToChar(0) 散列结果与 PHP 中的 chr(0) 不同的字符串

    我在 PHP 中有一个字符串 它被转换为字节数组并进行哈希处理 转换为字节数组的字符串如下所示 G 字符 0 便便 我需要 C 中的等效字节数组 这样我才能得到相同的哈希值 编辑 这是完整的问题 生成的哈希值不同 PHP api secre

随机推荐

  • 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