2014-06-16 119 views
0

我需要有人來幫助我完成我的工作,這可能是很多,但複雜的對我來說很簡單因爲我還在學習的symfony。我想有1到n的關係品牌汽車所以1品牌之間可以有很多車在邏輯。未能完成1到n的關係

我有一個表格中插入新的brand其工作正常,我有另一種形式,從選擇框中這是我掙扎插入car針對選定brand。我可以用db中的當前brands填充選擇框。當涉及到堅持car我得到一個錯誤(期待一個對象不是字符串),並不知道如何解決它。

我需要你的幫助來修改我的代碼,以便我可以堅持汽車。

在此先感謝

enter image description here

/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 %} 

回答

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

這將填充表單的選擇框,涉及到實際的品牌對象,而不是您正在生成的數組鍵。

+0

我無法解釋多少要感謝你。我現在學到了很多東西。非常非常感謝你。有沒有什麼方法可以清除(填充)''query_builder'部分,因爲我看起來有點難以閱讀。 +100 – BentCoder

+0

如果您不擔心訂單,那麼您可以完全省略query_builder部分。不知道它是如何很難閱讀,據我所知,這是非常標準的(https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide。 MD),但如果你只是想它是「漂亮」,那麼我想這很像你喜歡它。 – qooplmao

+0

再次感謝您。 – BentCoder