草庐IT

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

coder 2023-06-13 原文

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

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

在我的CourseAdmin 类(class)中我有:

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 类(class)中,我有:

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

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

FatalErrorException: Error: Call to a member function getName() on null in /myproject/app/cache/dev/classes.php line 9772

所以,我可以添加一个 session ,但是当我尝试向我的 session 添加一个时刻时,我收到了错误...。

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

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

$childFormBuildernull

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

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 函数。我的类(class)实体中的示例:

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

这可能是什么问题?我真的坚持这个。我还在 Sonata Admin 的 github repo 上发布了一个 issue 但没有答案......

我的实体:

类(class)实体:

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

session 实体:

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

更新:

我在函数 getChildFormBuilder 中添加了一些 var_dump,如下所示:

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: Warning: Illegal string offset 'admin' in app/cache/dev/classes.php line 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']) { .

在我的 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:

在我的 composer.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 :

This is still not supported for now ....

你也可以看看这个老 PR #1971这应该只解决某些用例的问题。

我建议您的解决方案是实现上次打开的 PR #2985 提供的修复程序.
因为 PR 没有合并,您需要告诉 composer 加载它而不是当前(未按预期工作)版本。 (见 composer and VCS)。

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

更新

Pull Request #3553最近被合并并修复了> 2层嵌套集合的问题(嵌套在嵌套中)。

要获得固定版本,您必须使用 bundle 的 dev-master 标记(至少来自 commit 926f159 表示 PR 的合并)。

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

// composer.json

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

我希望您可以轻松升级 bundle 以获得修复。

更新2

显然,您的 Composer 没有接受分支的最后更改。
PR 提供的修复 #2739已于 6 天前合并。

要修复最后一个(希望),您需要更改位于 vendor/sonata-project/admin-bundle/DependencyInjection/Compiler/的 AddDepencyCallsCompilerPass 中的一个非常短的代码块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-cachecomposer update sonata-project/admin-bundle

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

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

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

关于php - Sonata Admin (2.3) 中的嵌套集合字段,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35258776/

有关php - Sonata Admin (2.3) 中的嵌套集合字段的更多相关文章

  1. ruby - 如何从 ruby​​ 中的字符串运行任意对象方法? - 2

    总的来说,我对ruby​​还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用

  2. ruby - 其他文件中的 Rake 任务 - 2

    我试图在一个项目中使用rake,如果我把所有东西都放到Rakefile中,它会很大并且很难读取/找到东西,所以我试着将每个命名空间放在lib/rake中它自己的文件中,我添加了这个到我的rake文件的顶部:Dir['#{File.dirname(__FILE__)}/lib/rake/*.rake'].map{|f|requiref}它加载文件没问题,但没有任务。我现在只有一个.rake文件作为测试,名为“servers.rake”,它看起来像这样:namespace:serverdotask:testdoputs"test"endend所以当我运行rakeserver:testid时

  3. ruby-on-rails - Ruby net/ldap 模块中的内存泄漏 - 2

    作为我的Rails应用程序的一部分,我编写了一个小导入程序,它从我们的LDAP系统中吸取数据并将其塞入一个用户表中。不幸的是,与LDAP相关的代码在遍历我们的32K用户时泄漏了大量内存,我一直无法弄清楚如何解决这个问题。这个问题似乎在某种程度上与LDAP库有关,因为当我删除对LDAP内容的调用时,内存使用情况会很好地稳定下来。此外,不断增加的对象是Net::BER::BerIdentifiedString和Net::BER::BerIdentifiedArray,它们都是LDAP库的一部分。当我运行导入时,内存使用量最终达到超过1GB的峰值。如果问题存在,我需要找到一些方法来更正我的代

  4. ruby-on-rails - Rails 3 中的多个路由文件 - 2

    Rails2.3可以选择随时使用RouteSet#add_configuration_file添加更多路由。是否可以在Rails3项目中做同样的事情? 最佳答案 在config/application.rb中:config.paths.config.routes在Rails3.2(也可能是Rails3.1)中,使用:config.paths["config/routes"] 关于ruby-on-rails-Rails3中的多个路由文件,我们在StackOverflow上找到一个类似的问题

  5. ruby-on-rails - Rails 编辑表单不显示嵌套项 - 2

    我得到了一个包含嵌套链接的表单。编辑时链接字段为空的问题。这是我的表格:Editingkategori{:action=>'update',:id=>@konkurrancer.id})do|f|%>'Trackingurl',:style=>'width:500;'%>'Editkonkurrence'%>|我的konkurrencer模型:has_one:link我的链接模型:classLink我的konkurrancer编辑操作:defedit@konkurrancer=Konkurrancer.find(params[:id])@konkurrancer.link_attrib

  6. ruby-on-rails - Rails - 一个 View 中的多个模型 - 2

    我需要从一个View访问多个模型。以前,我的links_controller仅用于提供以不同方式排序的链接资源。现在我想包括一个部分(我假设)显示按分数排序的顶级用户(@users=User.all.sort_by(&:score))我知道我可以将此代码插入每个链接操作并从View访问它,但这似乎不是“ruby方式”,我将需要在不久的将来访问更多模型。这可能会变得很脏,是否有针对这种情况的任何技术?注意事项:我认为我的应用程序正朝着单一格式和动态页面内容的方向发展,本质上是一个典型的网络应用程序。我知道before_filter但考虑到我希望应用程序进入的方向,这似乎很麻烦。最终从任何

  7. ruby - 将散列转换为嵌套散列 - 2

    这道题是thisquestion的逆题.给定一个散列,每个键都有一个数组,例如{[:a,:b,:c]=>1,[:a,:b,:d]=>2,[:a,:e]=>3,[:f]=>4,}将其转换为嵌套哈希的最佳方法是什么{:a=>{:b=>{:c=>1,:d=>2},:e=>3,},:f=>4,} 最佳答案 这是一个迭代的解决方案,递归的解决方案留给读者作为练习:defconvert(h={})ret={}h.eachdo|k,v|node=retk[0..-2].each{|x|node[x]||={};node=node[x]}node[

  8. ruby-on-rails - Rails 3.2.1 中 ActionMailer 中的未定义方法 'default_content_type=' - 2

    我在我的项目中添加了一个系统来重置用户密码并通过电子邮件将密码发送给他,以防他忘记密码。昨天它运行良好(当我实现它时)。当我今天尝试启动服务器时,出现以下错误。=>BootingWEBrick=>Rails3.2.1applicationstartingindevelopmentonhttp://0.0.0.0:3000=>Callwith-dtodetach=>Ctrl-CtoshutdownserverExiting/Users/vinayshenoy/.rvm/gems/ruby-1.9.3-p0/gems/actionmailer-3.2.1/lib/action_mailer

  9. ruby-on-rails - Rails 应用程序中的 Rails : How are you using application_controller. rb 是新手吗? - 2

    刚入门rails,开始慢慢理解。有人可以解释或给我一些关于在application_controller中编码的好处或时间和原因的想法吗?有哪些用例。您如何为Rails应用程序使用应用程序Controller?我不想在那里放太多代码,因为据我了解,每个请求都会调用此Controller。这是真的? 最佳答案 ApplicationController实际上是您应用程序中的每个其他Controller都将从中继承的类(尽管这不是强制性的)。我同意不要用太多代码弄乱它并保持干净整洁的态度,尽管在某些情况下ApplicationContr

  10. ruby-on-rails - 如何验证非模型(甚至非对象)字段 - 2

    我有一个表单,其中有很多字段取自数组(而不是模型或对象)。我如何验证这些字段的存在?solve_problem_pathdo|f|%>... 最佳答案 创建一个简单的类来包装请求参数并使用ActiveModel::Validations。#definedsomewhere,atthesimplest:require'ostruct'classSolvetrue#youcouldevencheckthesolutionwithavalidatorvalidatedoerrors.add(:base,"WRONG!!!")unlesss

随机推荐