我需要有人来帮助我完成我的工作,这对许多人来说可能很简单但对我来说很复杂因为我还在学习symfony。我想在品牌和汽车之间建立一对一的关系,这样一个品牌在逻辑上可以有很多车。
我有一个表单可以插入新的brand
,但是我还有另一个表单可以从选择框中选择car
插入brand
,这是我正在努力的地方。我可以使用db中的当前brands
填充选择框。当持久化car
时,我得到一个错误(期望一个对象不是字符串),并且不知道如何解决它。
我需要你的帮助来修改下面的代码,以便我可以坚持使用。
提前致谢
/var/www/html/local/sym/src/Car/BrandBundle/Resources/config/routing.yml
home:
pattern: /
defaults: { _controller: CarBrandBundle:Home:index }
methods: [GET]
brand:
pattern: /brand
defaults: { _controller: CarBrandBundle:Brand:index }
methods: [GET]
brandCreate:
pattern: /brand/create
defaults: { _controller: CarBrandBundle:Brand:create }
methods: [POST]
car:
pattern: /car
defaults: { _controller: CarBrandBundle:Car:index }
methods: [GET]
carCreate:
pattern: /car/create
defaults: { _controller: CarBrandBundle:Car:create }
methods: [POST]
BrandEntity.php
namespace Car\BrandBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
use Doctrine\Common\Collections\ArrayCollection;
/**
* Class BrandEntity
*
* @ORM\Entity
* @ORM\Table(name = "brands")
* @UniqueEntity(fields = "name", message = "The Brand already exist in database.")
* @package Car\BrandBundle\Entity
*/
class BrandEntity
{
/**
* @ORM\Id
* @ORM\Column(type = "smallint")
* @ORM\GeneratedValue(strategy = "AUTO")
* @var int $id
*/
protected $id;
/**
* @Assert\NotBlank(message = "The Name field should not be blank")
* @Assert\Length(max = 20, maxMessage = "The Name field cannot be longer than {{ limit }} characters length.")
* @ORM\Column(type = "string", length = 20)
* @var string $name
*/
protected $name;
/**
* @ORM\OneToMany(targetEntity = "CarEntity", mappedBy = "brand")
* @var object $car
*/
protected $car;
/**
* Constructor.
*/
public function __construct()
{
$this->car = new ArrayCollection();
}
/**
* Get id
*
* @return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set name
*
* @param string $name
* @return BrandEntity
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name
*
* @return string
*/
public function getName()
{
return $this->name;
}
/**
* Add car
*
* @param \Car\BrandBundle\Entity\CarEntity $car
* @return BrandEntity
*/
public function addCar(\Car\BrandBundle\Entity\CarEntity $car)
{
$this->car[] = $car;
return $this;
}
/**
* Remove car
*
* @param \Car\BrandBundle\Entity\CarEntity $car
*/
public function removeCar(\Car\BrandBundle\Entity\CarEntity $car)
{
$this->car->removeElement($car);
}
/**
* Get car
*
* @return \Doctrine\Common\Collections\Collection
*/
public function getCar()
{
return $this->car;
}
}
BrandType.php
namespace Car\BrandBundle\Form\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
/**
* Class BrandType
* @package Car\BrandBundle\Form\Type
*/
class BrandType extends AbstractType
{
/**
* Returns the db mapped form object.
* @param FormBuilderInterface $builder
* @param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->setAction($options['action'])
->setMethod('POST')
->add('name', 'text', array('label' => 'Name'))
->add('button', 'submit', array('label' => 'Add'))
;
}
/**
* Returns relevant data class to the form.
* @param OptionsResolverInterface $resolver
*/
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array('data_class' => 'Car\BrandBundle\Entity\BrandEntity'));
}
/**
* Returns the name of the form.
* @return string
*/
public function getName()
{
return 'brand';
}
}
BrandController.php
namespace Car\BrandBundle\Controller;
use Car\BrandBundle\Entity\BrandEntity;
use Car\BrandBundle\Form\Type\BrandType;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
/**
* Class BrandController.
* Handles brand.
* @package Car\BrandBundle\Controller
*/
class BrandController extends Controller
{
/**
* Generates landing web page.
* @return Response
*/
public function indexAction()
{
$form = $this->getFrom();
return $this->render('CarBrandBundle:Default:brand.html.twig',
array('page' => 'Brand', 'form' => $form->createView(), 'brands' => $this->getBrands()));
}
/**
* Handles form submission.
* @param Request $request
* @return Response
*/
public function createAction(Request $request)
{
if ($request->getMethod() != 'POST')
{
return new Response('Only POST method is allowed');
}
$form = $this->getFrom();
$form->handleRequest($request);
if ($form->isValid())
{
$submission = $form->getData();
$em = $this->getDoctrine()->getManager();
$brand = new BrandEntity();
$brand->setName($submission->getName());
$em->persist($brand);
$em->flush();
$this->redirect($this->generateUrl('brand'));
}
return $this->render('CarBrandBundle:Default:brand.html.twig',
array('page' => 'Brand', 'form' => $form->createView(), 'brands' => $this->getBrands()));
}
/**
* Returns web form.
* @return \Symfony\Component\Form\Form
*/
private function getFrom()
{
return $this->createForm(new BrandType(), new BrandEntity(),
array('action' => $this->generateUrl('brandCreate')));
}
/**
* Return brands from db.
* @return array
*/
private function getBrands()
{
$repo = $this->getDoctrine()->getRepository('CarBrandBundle:BrandEntity');
$brands = $repo->findAll();
return $brands;
}
}
brand.html.twig
{% extends '::base.html.twig' %}
{% block body %}
{{ form_start(form, { attr: {novalidate: 'novalidate'} }) }}
{% if not form.vars.valid %}
<div class="global_form_errors">
Form has errors!
</div><br />
{% endif %}
<div>
{{ form_label(form.name) }}
{% if form.name.vars.errors|length != '' %}
{{ form_widget(form.name, { attr: {'class': 'individual_form_error'} }) }}
{% else %}
{{ form_widget(form.name) }}
{% endif %}
{{ form_errors(form.name) }}
</div>
<div>
{{ form_widget(form.button) }}
</div>
{{ form_end(form) }}
<hr />
Total Brands: {{ brands|length }}
<br />
{% if brands|length != 0 %}
{% set i = 1 %}
{% for brand in brands %}
{{ '(' ~ i ~ ') - ' ~ brand.id ~ ' - ' ~ brand.name }}<br />
{% set i = i+1 %}
{% endfor %}
{% endif %}
{% endblock %}
CarEntity.php
namespace Car\BrandBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
/**
* Class CarEntity.
* @ORM\Entity
* @ORM\Table(name = "cars", uniqueConstraints={@ORM\UniqueConstraint(columns={"model", "brand_id"})})
* @package Car\BrandBundle\Entity
*/
class CarEntity
{
/**
* @ORM\Id
* @ORM\Column(type = "smallint")
* @ORM\GeneratedValue(strategy = "AUTO")
* @var int $id
*/
protected $id;
/**
* @Assert\NotBlank(message = "The Model should not be blank.")
* @Assert\Length(max = 20, maxMessage = "The Brand field cannot be longer than {{ limit }} characters length.")
* @ORM\Column(type = "string", length = 20)
* @var string $model
*/
protected $model;
/**
* @Assert\NotBlank(message = "The Brand should not be blank.")
* @ORM\ManyToOne(targetEntity="BrandEntity", inversedBy="car")
* @ORM\JoinColumn(name="brand_id", referencedColumnName="id", nullable=false)
* @var object $brand
*/
protected $brand;
/**
* Get id
*
* @return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set model
*
* @param string $model
* @return CarEntity
*/
public function setModel($model)
{
$this->model = $model;
return $this;
}
/**
* Get model
*
* @return string
*/
public function getModel()
{
return $this->model;
}
/**
* Set brand
*
* @param \Car\BrandBundle\Entity\BrandEntity $brand
* @return CarEntity
*/
public function setBrand(\Car\BrandBundle\Entity\BrandEntity $brand = null)
{
$this->brand = $brand;
return $this;
}
/**
* Get brand
*
* @return \Car\BrandBundle\Entity\BrandEntity
*/
public function getBrand()
{
return $this->brand;
}
}
CarType.php
namespace Car\BrandBundle\Form\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
/**
* Class CarType
* @package Car\BrandBundle\Form\Type
*/
class CarType extends AbstractType
{
/**
* @var array $brands
*/
private $brands;
/**
* Constructor.
* @param array $brands
*/
public function __construct(array $brands)
{
$this->brands = $brands;
}
/**
* Returns web form object.
* @param FormBuilderInterface $builder
* @param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->setAction($options['action'])
->setMethod('POST')
->add('brand', 'choice', array('label' => 'Brand', 'choices' => $this->getBrands()))
->add('model', 'text', array('label' => 'Model'))
->add('button', 'submit', array('label' => 'Add'))
;
}
/**
* Returns relevant data class to the form.
* @param OptionsResolverInterface $resolver
*/
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array('data_class' => 'Car\BrandBundle\Entity\CarEntity'));
}
/**
* Returns name of the web form.
* @return string
*/
public function getName()
{
return 'car';
}
/**
* Returns choices for select box
* @return array
*/
public function getBrands()
{
$choices = array('' => '');
foreach ($this->brands as $brand)
{
$choices[$brand->getId()] = $brand->getName();
}
return $choices;
}
}
CarController.php
namespace Car\BrandBundle\Controller;
use Car\BrandBundle\Entity\CarEntity;
use Car\BrandBundle\Form\Type\CarType;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
/**
* Class CarController
* @package Car\BrandBundle\Controller
*/
class CarController extends Controller
{
/**
* Generates landing web page.
* @return Response
*/
public function indexAction()
{
$form = $this->getForm();
return $this->render('CarBrandBundle:Default:car.html.twig',
array('page' => 'Car', 'form' => $form->createView(), 'cars' => $this->getCars()));
}
public function createAction(Request $request)
{
if ($request->getMethod() != 'POST')
{
return new Response('Only POST method is allowed');
}
$form = $this->getForm();
$form->handleRequest($request);
if ($form->isValid())
{
$submission = $form->getData();
echo '<pre>'; print_r($submission); exit;
//$brand = new BrandEntity();
}
return $this->render('CarBrandBundle:Default:car.html.twig',
array('page' => 'Car', 'form' => $form->createView(), 'cars' => $this->getCars()));
}
/**
* Returns web form.
* @return \Symfony\Component\Form\Form
*/
private function getForm()
{
return $this->createForm(new CarType($this->getBrands()), new CarEntity(),
array('action' => $this->generateUrl('carCreate')));
}
/**
* Return cars from db.
* @return array
*/
private function getCars()
{
$repo = $this->getDoctrine()->getRepository('CarBrandBundle:CarEntity');
$cars = $repo->findAll();
return $cars;
}
/**
* Return brands from db.
* @return array
*/
private function getBrands()
{
$repo = $this->getDoctrine()->getRepository('CarBrandBundle:BrandEntity');
$brands = $repo->findAll();
return $brands;
}
}
car.html.twig
{% extends '::base.html.twig' %}
{% block body %}
{{ form_start(form, { attr: {novalidate: 'novalidate'} }) }}
{% if not form.vars.valid %}
<div class="global_form_errors">
Form has errors!
</div><br />
{% endif %}
<div>
{{ form_label(form.brand) }}
{% if form.brand.vars.errors|length != '' %}
{{ form_widget(form.brand, { attr: {'class': 'individual_form_error'} }) }}
{% else %}
{{ form_widget(form.brand) }}
{% endif %}
{{ form_errors(form.brand) }}
</div>
<div>
{{ form_label(form.model) }}
{% if form.model.vars.errors|length != '' %}
{{ form_widget(form.model, { attr: {'class': 'individual_form_error'} }) }}
{% else %}
{{ form_widget(form.model) }}
{% endif %}
{{ form_errors(form.model) }}
</div>
<div>
{{ form_widget(form.button) }}
</div>
{{ form_end(form) }}
<hr />
Total Cars: {{ cars|length }}
<br />
{% if cars|length != 0 %}
{% set i = 1 %}
{% for car in cars %}
{{ '(' ~ i ~ ') - ' ~ car.id ~ ' - ' ~ car.model }}<br />
{% set i = i+1 %}
{% endfor %}
{% endif %}
{% endblock %}
答案 0 :(得分:2)
您应该将品牌选择从简单的选择框更改为实体选择,如此......
/**
* Returns web form object.
* @param FormBuilderInterface $builder
* @param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->setAction($options['action'])
->setMethod('POST')
->add('users', 'entity', array(
// Entity class
'class' => 'CarBrandBundle:BrandEntity',
// Field displayed in select
'property' => 'name',
// Closure with repository query
'query_builder' => function(EntityRepository $repo) {
return $repo->createQueryBuilder('b')
->orderBy('b.name', 'ASC');
},
'multiple' => false,
'expanded' => false,
))
->add('model', 'text', array('label' => 'Model'))
->add('button', 'submit', array('label' => 'Add'))
;
}
这会将您的表单填充为与实际品牌对象相关的选择框,而不是您当前生成的数组键。