免责声明:我是Symfony的新手。真的很难收集字段类型和简单的OnetoOne关系设置。
场景:我有一个Product实体类和一个Category实体类。我在产品上使用收集字段来创建类别项。我正在想象一个单独的类别表,其中包含名称列和相关的product_id列。我知道它通常不实用。为了论证,类别也可能是功能或其他东西,因为我只是想建立关系作为扩展的场景。最终,类别将成为一个图像字段,允许我将相关图像拉入视图。
问题:我一遍又一遍地跟着食谱文章(http://symfony.com/doc/current/cookbook/form/form_collections.html),但只是碰到了砖墙。我已经遵守了原则,但感觉我错过了一些重要的东西。我已经从javascript生成了一个protoype表单字段,并且我成功地持久保存了新产品(完整版)和新类别(仅部分版本)。相关产品ID未写入连接列。
我确定这是一个没有得到正确照顾的吸气剂/安装者的情况。我'依靠学说自动生成它们。或者问题可能是某些未指定的要求将id设置为控制器中的Category。
要遵循的代码。非常感谢,因为这已经打了好几天而且无处可去。真的很沮丧,因为很快就掌握了所有其他原则,并且在symfony中建立第一个项目真的很不错。
产品实体
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Component\HttpFoundation\File\File;
use Vich\UploaderBundle\Mapping\Annotation as Vich;
use Doctrine\Common\Collections\ArrayCollection;
use AppBundle\Entity\Category;
/**
* Page
*
* @ORM\Table(name="product")
* @ORM\Entity
* @Vich\Uploadable
*/
class Product
{
/**
* @var integer
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @var string
*
* @ORM\Column(name="Title", type="string", length=255)
* @Assert\NotBlank()
*/
private $title;
/**
* Get id
*
* @return integer
*/
public function getId()
{
return $this->id;
}
/**
* @ORM\OnetoOne(targetEntity="Category", cascade={"persist"})
*/
protected $categorys;
public function __construct()
{
$this->categorys = new ArrayCollection();
}
}
类别实体
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use AppBundle\Entity\Product;
/**
* Category
*
* @ORM\Table(name="category")
* @ORM\Entity
*/
class Category
{
/**
* @var integer
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @var string
*
* @ORM\Column(name="name", type="string", length=255)
*/
private $name;
/**
* @ORM\OneToOne(targetEntity="Product", cascade={"persist"})
*/
protected $product;
/**
* Get id
*
* @return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set name
*
* @param string $name
* @return Category
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name
*
* @return string
*/
public function getName()
{
return $this->name;
}
/**
* Set product
*
* @param \AppBundle\Entity\Product $product
* @return Category
*/
public function setProduct(\AppBundle\Entity\Product $product = null)
{
$this->product = $product;
return $this;
}
/**
* Get product
*
* @return \AppBundle\Entity\Product
*/
public function getProduct()
{
return $this->product;
}
}
产品类型
<?php
namespace AppBundle\Form\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use AppBundle\Entity\Product;
use AppBundle\Entity\Category;
class ProductType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('title', 'text')
->add('categorys', 'collection', array(
'type' => new CategoryType(),
'allow_add' => true,
'by_reference' => false,
))
->add('save', 'submit', array(
'attr' => array('class' => 'btn btn-default'),
))
;
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'AppBundle\Entity\Product',
));
}
public function getName()
{
return 'product';
}
}
类别类型
<?php
namespace AppBundle\Form\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use AppBundle\Entity\Category;
class CategoryType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('name', 'text');
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'AppBundle\Entity\Category',
));
}
public function getName()
{
return 'category';
}
}
产品控制器:新产品
/**
* @Route("admin/product/new", name="product_add")
* @Security("has_role('ROLE_ADMIN')")
*/
public function newAction(Request $request)
{
$product = new Product();
$form = $this->createForm(new ProductType(), $product);
$category = new Category();
$form->handleRequest($request);
if ($form->isValid()) {
$category->getProduct($this);
$em = $this->getDoctrine()->getManager();
$em->persist($product);
$em->flush();
return $this->redirectToRoute('products_admin');
}
return $this->render('Product/productAdd.html.twig', array(
'form' => $form->createView(),
));
}
答案 0 :(得分:0)
我认为在你的情况下你也不需要收藏类型。您可以为entity type更改此设置。就像我解释的那样,制作实体ManyToOne。
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Product
*
* @ORM\Table()
* @ORM\Entity
*/
class Product
{
/**
* @var integer
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @var string
*
* @ORM\Column(name="description", type="string", length=64)
*/
private $description;
/**
* @var float
*
* @ORM\Column(name="price", type="float")
*/
private $price;
/**
* @ORM\ManyToOne(targetEntity="Category")
* @ORM\JoinColumn(name="category_id", referencedColumnName="id")
**/
private $category;
}
和类别:
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Category
*
* @ORM\Table()
* @ORM\Entity
*/
class Category
{
/**
* @var integer
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @var string
*
* @ORM\Column(name="name", type="string", length=64)
*/
private $name;
public function __toString() {
return $this->name;
}
}
现在使用控制台运行一些命令:
app/console doctrine:generate:entities AppBundle
app/console doctrine:schema:update --force
app/console doctrine:generate:crud AppBundle:Product
app/console doctrine:generate:crud AppBundle:Category
如果询问您是否要生成写入操作
,请选择“是”将__toString()方法添加到Category实体:
public function __toString() {
return $this->name;
}
现在看看你的新控制器和路线并尝试它们。
查看所有路线:
app/console router:debug
您必须在app / config / routing.yml中使用此功能:
app:
resource: "@AppBundle/Controller/"
type: annotation
最后你会得到:
- two new entities
- two new controllers
- two new form types
- eight new views
您可以从创建的代码中学到很多东西,并根据需要更改所有内容。 祝你好运
答案 1 :(得分:0)
我知道这是一个老问题,但是:
/**
* @Route("admin/product/new", name="product_add")
* @Security("has_role('ROLE_ADMIN')")
*/
public function newAction(Request $request)
{
$product = new Product();
$form = $this->createForm(new ProductType(), $product);
$category = new Category();
$form->handleRequest($request);
if ($form->isValid()) {
#################################
##$category->getProduct($this);##
#################################
$category->setProduct($this);
$em = $this->getDoctrine()->getManager();
$em->persist($product);
$em->flush();
return $this->redirectToRoute('products_admin');
}
return $this->render('Product/productAdd.html.twig', array(
'form' => $form->createView(),
));
}
您调用getProduct($ this)而不是setProduct($ this)