我尝试生成表单类型,尤其是" ProductLanguageType"。
我想生成ProductLanguageType,与Language表中现有语言的当前数量一样多。
例如,如果我在语言表中有(英语,法语,俄语,中文),它将在同一页面上生成4个ProductLanguageType表单。
我想知道如何查询语言表并在同一页面上生成相同类型的多个表单,表单构建器是否能够执行此操作还是有另一种解决方法?一段时间以来遇到了一些麻烦,很乐意为此找到一个好的解决方案。
ProductLanguageType:
class ProductLanguageType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options){
$builder->add('id_language', 'entity', array(
'class' => 'AdminBundle:Language',
'data_class' => 'Main\AdminBundle\Entity\Language',
'property' => 'language'
)
)
->add('name', 'text')
->add('description', 'ckeditor', array(
'config_name' => 'admin',
'config' => array(
'filebrowser_image_browse_url' => array(
'route' => 'elfinder',
'route_parameters' => array('instance' => 'default'),
),
)
))
->add('short_description', 'text');
}
public function getName(){
return 'productLanguage';
}
}
ProductType(此处嵌入了ProductLanguageType):
class ProductType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options){
$builder->addEventListener(FormEvents::PRE_SET_DATA, array($this, 'onPreSetData'));
$builder->add('productLanguage', new ProductLanguageType())
->add('id_seller','text')
->add('price','text')
->add('cost_price','text')
->add('retail_price','text')
->add('hot', 'checkbox')
->add('featured', 'checkbox')
->add('new', 'checkbox')
->add('free_shipping', 'checkbox')
->add('status','text') //active or inactive, to be decided if hidden or visible
->add('Add', 'submit');
}
}
答案 0 :(得分:5)
希望这会对某人有所帮助。
正确的方法是使用Symfony的form.factory服务来创建命名构建器,然后从中创建一个表单。我建议为表单创建过程创建一个函数(据我所知,如果我错误,请纠正我),每个FormBuilder实例必须不同才能创建不同的表单。
正如对代码目的的解释: 我需要在帮助系统中显示一个打开的票证列表,能够根据票证的登录令牌分配一个人(未经登录授权)。这需要在单个页面上显示N个表单,这些表单是唯一的,但是从单个"模板"生成。或者输入你的意思。
此代码实现了没有任何黑客攻击。从控制器AFAIK创建具有特定ID(名称)的表格,没有简便的方法。
离。
public function generateFormForTicketAssignment(Ticket $ticket) {
$ticketAssignType = new TicketAssignInvokeType();
$ticketAssignType->setNameSuffix($ticket->getId());
/**
* @var Symfony\Component\Form\FormBuilderInterface
*/
$builder = $this->get('form.factory')->createNamedBuilder($ticketAssignType->getName(), $ticketAssignType );
$builder->setAutoinitialize(true);
$formTicket = $builder->getForm();
$formTicket->get('ticket')->setData($ticket);
return $formTicket;
}
AND(这是重要的部分)ticketAssignInvokeType如下所示:
class TicketAssignInvokeType extends AbstractType {
private $nameSuffix = null;
private $name = 'ticket_assign_invoke';
public function __constructor(string $suffix = null) {
//parent::__construct();
$this->nameSuffix = $this->generateNameSuffix();
}
private function generateNameSuffix() {
if ($this->nameSuffix == null || $this->nameSuffix == '') {
$generator = new SecureRandom();
//change data to alphanumeric string
return bin2hex($generator->nextBytes(10));
}
return $this->nameSuffix;
}
/**
*
* @param string $suffix When set suffix added to form will use selected
* string (note it should be unique for all forms on a page).
*/
public function setNameSuffix($suffix){
$this->nameSuffix = $suffix;
}
public function buildForm(FormBuilderInterface $builder, array $options) {
$builder
->add('loginToken',new AuthenticateTokenType())
->add('ticket',new TicketIDType())
->add('save', 'submit', array('label' => 'form.button.assign'))
;
}
public function getName() {
if ($this->nameSuffix == null || $this->nameSuffix == "" ) {
$this->nameSuffix = $this->generateNameSuffix();
}
return $this->name .'_'. $this->nameSuffix;
}
public function configureOptions(OptionsResolver $resolver) {
// ...
}
}
这有点过于复杂的逻辑和测试名称后缀但在某些时候我无法弄清楚为什么我所有的都是没有后缀的表单名称因此复杂。
PS。我已经创建了表单作为服务,稍后将测试是否可以使用服务,这是我的第一个意图。
PS2。我还不确定setAutoinitialize
方法,但也会对它进行测试。
答案 1 :(得分:5)
现在在Symfony 3.0中,他们更改了createNamedBuilder,因此只需调用即可解决此问题:
use AppBundle\Form\ShippingTrackCodeReturnType;
$uniqueForm = $this->get('form.factory')->createNamedBuilder('ship_form_'.$orderRecord->getId(), ShippingTrackCodeReturnType::class, $orderRecord)->getForm();
所以,你只需要循环显示并保存它们:
foreach ($invoice->getOrderRecords() as $key => $orderRecord)
{
// creates the forms with different names
$returnShipTrackCodeForm = $this->get('form.factory')->createNamedBuilder('ship_form_'.$orderRecord->getId(), ShippingTrackCodeReturnType::class, $orderRecord)->getForm();
$returnShipTrackCodeForm->handleRequest($request);
if ($returnShipTrackCodeForm->isSubmitted() && $returnShipTrackCodeForm->isValid())
{
// flush object
}
$returnForms[$orderRecord->getId()] = $returnShipTrackCodeForm;
}