Php 具有额外字段的N:M关系的表单版本不起作用
我正在处理一个表单,该表单使用一个额外的参数(额外的字段/列)处理N:m关系。这就是我到目前为止所做的: 在Php 具有额外字段的N:M关系的表单版本不起作用,php,symfony,doctrine-orm,symfony-forms,symfony-2.5,Php,Symfony,Doctrine Orm,Symfony Forms,Symfony 2.5,我正在处理一个表单,该表单使用一个额外的参数(额外的字段/列)处理N:m关系。这就是我到目前为止所做的: 在ordersype.php表单中: class OrdersType extends AbstractType { public function buildForm(FormBuilderInterface $builder, array $options) { // $builder fields // $builder fields
ordersype.php
表单中:
class OrdersType extends AbstractType {
public function buildForm(FormBuilderInterface $builder, array $options)
{
// $builder fields
// $builder fields only need on edit form not in create
if ($options['curr_action'] !== NULL)
{
$builder
// other $builder fields
->add("orderProducts", "collection", array(
'type' => new OrdersHasProductType(),
'allow_add' => true,
'allow_delete' => true,
'by_reference' => false
));
}
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'Tanane\FrontendBundle\Entity\Orders',
'render_fieldset' => FALSE,
'show_legend' => FALSE,
'intention' => 'orders_form',
'curr_action' => NULL
));
}
public function getName()
{
return 'orders';
}
}
在OrderHasProductType.php
中:
class OrdersHasProductType extends AbstractType {
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('product', 'text', array(
'required' => FALSE,
'label' => FALSE
))
->add('amount', 'text', array(
'required' => TRUE,
'label' => FALSE
));
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'Tanane\FrontendBundle\Entity\OrderHasProduct',
'intention' => 'order_has_product'
));
}
public function getName()
{
return 'order_has_product';
}
}
最后是Orders.php
和OrdersHasProduct.php
实体:
class Orders {
use IdentifiedAutogeneratedEntityTrait;
// rest of fields for the entity
/**
* @ORM\OneToMany(targetEntity="OrderHasProduct", mappedBy="order", cascade={"all"})
*/
protected $orderProducts;
protected $products;
/**
* @ORM\Column(name="deletedAt", type="datetime", nullable=true)
*/
protected $deletedAt;
public function __construct()
{
$this->orderProducts = new ArrayCollection();
$this->products = new ArrayCollection();
}
public function getOrderProducts()
{
return $this->orderProducts;
}
public function getDeletedAt()
{
return $this->deletedAt;
}
public function setDeletedAt($deletedAt)
{
$this->deletedAt = $deletedAt;
}
public function getProduct()
{
$products = new ArrayCollection();
foreach ($this->orderProducts as $op)
{
$products[] = $op->getProduct();
}
return $products;
}
public function setProduct($products)
{
foreach ($products as $p)
{
$ohp = new OrderHasProduct();
$ohp->setOrder($this);
$ohp->setProduct($p);
$this->addPo($ohp);
}
}
public function getOrder()
{
return $this;
}
public function addPo($ProductOrder)
{
$this->orderProducts[] = $ProductOrder;
}
public function removePo($ProductOrder)
{
return $this->orderProducts->removeElement($ProductOrder);
}
}
/**
* @ORM\Entity
* @ORM\Table(name="order_has_product")
* @Gedmo\SoftDeleteable(fieldName="deletedAt")
* @UniqueEntity(fields={"order", "product"})
*/
class OrderHasProduct {
use IdentifiedAutogeneratedEntityTrait;
/**
* Hook timestampable behavior
* updates createdAt, updatedAt fields
*/
use TimestampableEntity;
/**
* @ORM\ManyToOne(targetEntity="\Tanane\FrontendBundle\Entity\Orders", inversedBy="orderProducts")
* @ORM\JoinColumn(name="general_orders_id", referencedColumnName="id")
*/
protected $order;
/**
* @ORM\ManyToOne(targetEntity="\Tanane\ProductBundle\Entity\Product", inversedBy="orderProducts")
* @ORM\JoinColumn(name="product_id", referencedColumnName="id")
*/
protected $product;
/**
* @ORM\Column(type="integer", nullable=false)
*/
protected $amount;
/**
* @ORM\Column(name="deletedAt", type="datetime", nullable=true)
*/
protected $deletedAt;
public function setOrder(\Tanane\FrontendBundle\Entity\Orders $order)
{
$this->order = $order;
}
public function getOrder()
{
return $this->order;
}
public function setProduct(\Tanane\ProductBundle\Entity\Product $product)
{
$this->product = $product;
}
public function getProduct()
{
return $this->product;
}
public function setAmount($amount)
{
$this->amount = $amount;
}
public function getAmount()
{
return $this->amount;
}
public function getDeletedAt()
{
return $this->deletedAt;
}
public function setDeletedAt($deletedAt)
{
$this->deletedAt = $deletedAt;
}
}
但当我尝试在控制器中使用以下代码编辑订单时:
public function editAction(Request $request, $id)
{
$em = $this->getDoctrine()->getManager();
$order = $em->getRepository('FrontendBundle:Orders')->find($id);
$type = $order->getPerson()->getPersonType() === 1 ? "natural" : "legal";
$params = explode('::', $request->attributes->get('_controller'));
$actionName = substr($params[1], 0, -6);
$orderForm = $this->createForm(new OrdersType(), $order, array('action' => '#', 'method' => 'POST', 'register_type' => $type, 'curr_action' => $actionName));
return array(
"form" => $orderForm->createView(),
'id' => $id,
'entity' => $order
);
}
我得到这个错误:
表单的视图数据应为标量、数组或
\ArrayAccess的实例,但是类的实例
代理\uuuu CG\uuuu\Tanane\ProductBundle\Entity\Product。你可以避免这种情况
将“data_class”选项设置为时出错
“代理\uuuu CG\uuuu\Tanane\ProductBundle\Entity\Product”或通过添加
视图转换器,用于转换类的实例
代理\uuuu CG\uuuu\Tanane\ProductBundle\Entity\Product到标量、数组或
\ArrayAccess的实例
我找不到或不知道如何修复它,有人能给我一些帮助吗?我想这是因为代码
class OrdersHasProductType extends AbstractType {
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('product', 'text', array(
'required' => FALSE,
'label' => FALSE
))
));
}
//...
}
这意味着Symfony希望“product”是“text”类型的字段,但当它在OrderHasProduct上调用getProduct()
时,它会得到一个产品对象(或一个产品的原则代理,因为此时尚未加载)。Symfony字段继承自Form/AbstractType,因此它们本质上是表单本身,只有一个字段,因此会出现错误消息
解决方案是将该字段设置为“entity”类型,或者创建一个只给出产品名称的不同方法,例如OrderHasProduct上的
getProductName()
,然后将其用作字段后面的数据。Hi@frumious,感谢您在这里留下的所有回复(这一个和您回答的另外两个)。我之所以使用text
而不是entity
是因为我使用的是Select2组件,它通过AJAX调用从DB获取产品,如果我使用entity
类型,我不希望Symfony呈现典型的select组件,如果你知道这方面的任何解决方案,那么是的,我可以使用实体
,没有问题。你能用它来获得你想要的输出吗?嗯,我不确定属性是否有帮助,你对此有什么想法吗?可能没有。。。您需要传递给Select2的具体内容是什么?你能给出一个呈现HTML的例子吗?它是在线的,看看这个字符串“Ofertas realizadas a facturar”,在那里你会看到我在说什么(很抱歉是西班牙语翻译),如果你有任何疑问,请再次告诉我我在这里