php – Symfony2表单和集合 – Order,OrderItem实现
|
因此,我今天花了大约5或6个小时与Symfony2表格进行斗争,并且我希望得到社区其他成员的一些建议.我已经尝试了3种不同的方法来实现我所追求的并且没有成功.我已经阅读了文档,谷歌搜索了所有内容,问了其他人,而且比起初时我只有一点点好转. 我的用例 我正在建立一个可以订购门票的系统.但核心问题是如何设计系统的订单部分. >票证有一个名称,以及它可用的开始和结束日期(其他东西也是如此,但让我们保持示例简单. 在阅读并尝试不同的事情后,我收集了代表订单的票和数量,我需要另一个实体OrderTicket对应于https://github.com/beberlei/AcmePizzaBundle的OrderItem,而Pizza是我的票. > OrderTicket有票和数量. 在我创建订单的订单页面上,我想要以下内容: >客户详细信息表 – 姓名,电子邮件,地址.这部分工作正常. 我的后端 Order / OrderTicket / Ticket设计主要基于https://github.com/beberlei/AcmePizzaBundle 票 /**
* @ORMEntity(repositoryClass="FooBackendBundleEntityTicketsRepository")
* @ORMHasLifecycleCallbacks
* @ORMTable(name="tickets")
*/
class Tickets
{
// id fields and others
/**
* @AssertNotBlank
* @ORMColumn(type="string",nullable=true)
*/
protected $name;
/**
* @ORMColumn(type="date",name="available_from",nullable=true)
*/
protected $availableFrom;
/**
* @ORMColumn(type="date",name="available_to",nullable=true)
*/
protected $availableTo;
}
OrderTicket /**
* @ORMTable()
* @ORMEntity
*/
class OrderTicket
{
// id field
/**
* @ORMColumn(name="quantity",type="integer")
*/
private $quantity;
/**
* @ORMManyToOne(targetEntity="Tickets")
*/
protected $ticket;
/**
* @ORMManyToOne(targetEntity="Orders",inversedBy="tickets")
*/
protected $order;
// getters and setters for quantity,ticket and order
}
订购 /**
* @ORMEntity
* @ORMHasLifecycleCallbacks
* @ORMTable(name="orders")
*/
class Orders
{
// id field and other stuff
/**
* @ORMOneToMany(targetEntity="OrderTicket",mappedBy="order",cascade={"persist"})
**/
protected $tickets;
/**
* @ORMManyToOne(targetEntity="Customer",cascade={"persist"})
*/
protected $customer;
public function __construct()
{
$this->tickets = new DoctrineCommonCollectionsArrayCollection();
}
// getters,setters,add for Tickets and Customer
}
顾客 /**
* @ORMTable()
* @ORMEntity
*/
class Customer
{
// id,name,email,address fields
}
这会创建一个类似的模式(表命名差异来自自动生成): CREATE TABLE `tickets` ( `id` int(11) NOT NULL AUTO_INCREMENT,`name` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,`available_from` date DEFAULT NULL,`available_to` date DEFAULT NULL,PRIMARY KEY (`id`) ); CREATE TABLE `Customer` ( `id` int(11) NOT NULL AUTO_INCREMENT,`email` varchar(255) COLLATE utf8_unicode_ci NOT NULL,`name` varchar(255) COLLATE utf8_unicode_ci NOT NULL,`address` longtext COLLATE utf8_unicode_ci NOT NULL,PRIMARY KEY (`id`) ); CREATE TABLE `OrderTicket` ( `id` int(11) NOT NULL AUTO_INCREMENT,`ticket_id` int(11) DEFAULT NULL,`order_id` int(11) DEFAULT NULL,`quantity` int(11) NOT NULL,PRIMARY KEY (`id`) ); CREATE TABLE `orders` ( `id` int(11) NOT NULL AUTO_INCREMENT,`customer_id` int(11) DEFAULT NULL,PRIMARY KEY (`id`) ); 形式 class CustomerType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder,array $options)
{
$builder
->add('email')
->add('name')
->add('address')
;
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'FooBackendBundleEntityCustomer'
));
}
public function getName()
{
return 'foo_backendbundle_customertype';
}
}
class OrderTicketType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder,array $options)
{
$builder
->add('quantity','integer')
->add('ticket')
;
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'FooBackendBundleEntityOrderTicket'
));
}
public function getName()
{
return 'foo_backendbundle_ordertickettype';
}
}
class OrdersType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder,array $options)
{
$builder
->add('customer',new CustomerType())
->add('tickets','collection',array(
'type' => new OrderTicketType(),'allow_add' => true,'allow_delete' => true,'prototype' => true,))
;
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'FooBackendBundleEntityOrders',));
}
public function getName()
{
return 'foo_backendbundle_orderstype';
}
}
表格 <form action="{{ path('index') }}" method="post" {{ form_enctype(form) }}>
<h3>Tickets</h3>
{{ form_errors(form) }}
<table>
<thead>
<tr>
<td>Ticket</td>
<td>Quantity</td>
</thead>
<tbody>
{% for ticketrow in form.tickets %}
<tr>
<td>{{ form_widget(ticketrow.ticket) }}</td>
<td>{{ form_widget(ticketrow.quantity) }}</td>
</tr>
{% endfor %}
</tbody>
</table>
<h3>Customer</h3>
{% for customer in form.customer %}
{{ form_row(customer) }}
{% endfor %}
</form>
最后是控制器 class DefaultController extends Controller
{
/**
* @Route("/",name="index")
* @Template()
*/
public function indexAction(Request $request)
{
$em = $this->getDoctrine()->getManager();
// IMPORTANT - the Tickets are prefiltered for active Tickets,these have to be injected into the Order atm. In other places I use this method on the query builder
$tickets = $em->getRepository('FooBackendBundle:Tickets')->findActive();
// check no tickets
$order = new Orders();
// To prepopulate the order with the available tickets,we have to do it like this,due to it being a collection,// rather than using the forms query_builder like everywhere else
foreach($tickets as $ticket) {
$ot = new OrderTicket();
$ot->setTicket($ticket);
$ot->setQuantity(0);
$ot->setOrder($order);
$order->addTicket($ot);
}
$form = $this->createForm(new OrdersType(),$order);
if ($request->isMethod('POST')) {
$form->bind($request);
// IMPORTANT here I have to remove the previously added Tickets where the quantity is 0 - as they're not wanted in the Order. Is there a better way to do this?
// if the quantity of Ticket is 0,do not add to order
// note we use the validation callback in Order to check total quantity of OrderTickets is > 0
$order->removeTicketsWithNoQuantity();
if ($form->isValid()) {
$em->persist($order);
$em->flush();
return $this->redirect($this->generateUrl('order_show',array('id' => $order->getId())));
}
}
return array('form' => $form->createView());
}
}
摘要 这可以正常保存订单,但我不确定这是正确的方式来做我想要的,它不会显示我想要的. 您可以在下面的图像中看到它的外观和顺序如何通过.值得注意的是,在每张Ticket下拉列表中,其余的门票都是活跃的. 订单页面: 保存后的订单摘要页面: 显示的3个门票是已过滤的门票,我只想在窗体上使用这些门票.我只想看到门票名称,而不是可编辑的下降. (编辑:安卓应用网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
