奏鸣曲管理中的嵌套集合字段 (2.3)
我在创建用于创建课程的表单时遇到问题。这是我的数据库方案的一部分,我正在尝试为其创建一个表单:
因此,我试图做的是创建一个课程,我可以在其中创建附加到该会话的会话和日期(时刻)。它应该看起来像这样:
在我的课程管理员课程中,我有:
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'
))
;
}
在我的会话管理员课程中,我有:
protected function configureFormFields(FormMapper $formMapper)
{
$formMapper
->add('type', 'text', array('label' => 'Type opleiding (Dag / Avond)'))
->add('moment', 'sonata_type_collection', array(
'by_reference' => false,
'type_options' => array(
// Prevents the "Delete" option from being displayed
'delete' => false,
'delete_options' => array(
// You may otherwise choose to put the field but hide it
'type' => 'hidden',
// In that case, you need to fill in the options as well
'type_options' => array(
'mapped' => false,
'required' => false,
)
)
)
), array(
'edit' => 'inline',
'inline' => 'table',
'sortable' => 'position'
))
;
}
在我的MomentAdmin课程中,我有:
protected function configureFormFields(FormMapper $formMapper)
{
$formMapper
->add('time', 'date', array('label' => 'Datum'))
;
}
我的表单中的问题是,当我尝试向会话添加时刻(日期)时,我收到以下错误:
FatalErrorException:错误:在 /myproject/app/cache/dev/classes 中调用成员函数 getName() .php行 9772 中的 null
因此,我可以添加一个会话,但是当我尝试向我的会话添加时刻时,我收到错误... .
当我在文件类中查找时.php规则9771和9772上有:
$childFormBuilder = $this->getChildFormBuilder($formBuilder, $elementId);
$fieldDescription = $admin->getFormFieldDescription($childFormBuilder->getName());
为空。$childFormBuilder
当我看到这个函数时,我得到这个:
public function getChildFormBuilder(FormBuilder $formBuilder, $elementId)
{
foreach (new FormBuilderIterator($formBuilder) as $name => $formBuilder) {
if ($name == $elementId) {
return $formBuilder;
}
}
return;
}
当我像这样var_dump$name和$elementId时:
public function getChildFormBuilder(FormBuilder $formBuilder, $elementId)
{
foreach (new FormBuilderIterator($formBuilder) as $name => $formBuilder) {
var_dump("name: " . $name);
var_dump("elementId: " . $elementId);
if ($name == $elementId) {
return $formBuilder;
}
}
die;
return;
}
然后按下“添加新”按钮,如下图所示:
然后我得到这个输出:
name: s56cda71d2daa0_name
elementId: s56cda71d2daa0_session_0_moment
name: s56cda71d2daa0_description
elementId: s56cda71d2daa0_session_0_moment
name: s56cda71d2daa0_materials
elementId: s56cda71d2daa0_session_0_moment
name: s56cda71d2daa0_numberOfParticipants
elementId: s56cda71d2daa0_session_0_moment
name: s56cda71d2daa0_numberOfDays
elementId: s56cda71d2daa0_session_0_moment
name: s56cda71d2daa0_price
elementId: s56cda71d2daa0_session_0_moment
name: s56cda71d2daa0_priceKmo
elementId: s56cda71d2daa0_session_0_moment
name: s56cda71d2daa0_location
elementId: s56cda71d2daa0_session_0_moment
name: s56cda71d2daa0_session
elementId: s56cda71d2daa0_session_0_moment
在我所有的实体中,我都有一个__toString函数。我的课程实体中的一个示例:
public function __toString()
{
if(!is_null($this->name))
{
return $this->name;
}
else{
return "";
}
}
这里可能有什么问题?我真的被这个困住了。我还在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;
}
}
更新:
我已经在我的函数getChildFormBuilder中添加了一些var_dumps,如下所示:
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”非法.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']) {
在我的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