我想创建表单,用于添加,编辑(以及在url字段为空时删除)菜单项。问题是行/项的计数是可变的。 (正如你在第一张照片上看到的那样)
问题:
1)如何编写具有可变字段数的表单。
2)如何将数据解析为此表单中的字段。
class GalleryType extends AbstractType {
public function buildForm(FormBuilderInterface $builder, array $options) {
$builder->add(
//...some textType, fileType fields,...etc
);
}
public function configureOptions(OptionsResolver $resolver) {
$resolver->setDefaults([
//...
//some data/data_class option that parse data into the field
]);
}
额外信息:
我正在使用Symfony 3框架开发自己的简单内容管理系统。我想允许用户添加菜单项,其中包含以下信息:URL,标题,例如FA图标,背景图片等等。
- 总是有一个空行用于添加项目,其余字段用现有数据(菜单项/ s)来实现。确认表单后,此行将添加到表单中(以及空行)。
- 有几种不同类型的菜单:主菜单,滑块,侧面菜单,具有不同类型的字段。 (你可以在第二张图片上看到它)
- 主菜单有:标题,网址和某些项目可以有子项目(作为子菜单)
-Slider有:标题,网址,标题颜色,背景图片
-Side菜单包含:title,url和Font Awesome Icon
我已经完成了导航菜单(页脚)的表单,其中只有2个字段(标题和链接),但我觉得这不是属性方式如何编程...为了说明目的,这里是我'做了导航 控制器:
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use AppBundle\Entity\SMBundle\Navigation;
use AppBundle\Entity\Sett;
use Symfony\Component\Serializer\Serializer;
use Symfony\Component\Serializer\Encoder\JsonEncoder;
use Symfony\Component\Serializer\Normalizer\GetSetMethodNormalizer;
use Symfony\Component\Form\Extension\Core\Type\TextType;
class SettingsController extends Controller {
//....
/**
* @Route("/admin/menu/navigation", name="navigation")
*/
public function navigationAction(Request $request) {
$set = $this->getDoctrine()->getRepository('AppBundle:Sett')->findOneByName('navigation');
$navigation = $this->deserializeFromStringToObject('navigation');
if (!$navigation) {
$set = new Sett();
$navigation = new Navigation();
}
$form = $this->createFormFromArray($navigation->getLinksArray());
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$set->setEditedAt(new \DateTime());
$set->setName('navigation');
$this->brutalHack($navigation, $form);
$set->setContent($this->serializeFromObjectToString($navigation));
// Save
$this->save($set);
return $this->redirect($this->generateUrl('navigation'));
}
return $this->render("viewSM/menu/navigation.html.twig", array('form' => $form->createView()));
}
private function deserializeFromStringToObject($name) {
$object = $this->getDoctrine()->getRepository('AppBundle:Sett')->findOneByName($name);
if (!$object) {
return null;
}
$serializer = new Serializer(array(new GetSetMethodNormalizer()), array('json' => new JsonEncoder()));
return $serializer->deserialize($object->getContent(), 'AppBundle\\Entity\\SMBundle\\' . ucfirst($name), 'json');
}
private function serializeFromObjectToString($object) {
$serializer = new Serializer(array(new GetSetMethodNormalizer()), array('json' => new JsonEncoder()));
return $serializer->serialize($object, 'json');
}
private function createFormFromArray(array $collection) {
$i = 0;
$formBuilder = $this->createFormBuilder();
foreach ($collection as $key => $value) {
$formBuilder
->add('url' . $i, TextType::class, ['label' => 'URL ', 'data' => '' . $key, 'attr' => ['class' => 'form-control']])
->add('name' . $i, TextType::class, ['label' => 'Titulek ', 'data' => '' . $value, 'attr' => ['class' => 'form-control']]);
$i++;
}
$formBuilder
->add('url' . $i, TextType::class, ['label' => 'URL ', 'attr' => ['class' => 'form-control']])
->add('name' . $i, TextType::class, ['label' => 'Titulek ', 'attr' => ['class' => 'form-control']])
->add('submit', \Symfony\Component\Form\Extension\Core\Type\SubmitType::class, ['label' => 'Uložit', 'attr' => ['class' => 'btn btn-primary']]);
$form = $formBuilder->getForm();
return $form;
}
private function save($set) {
$em = $this->getDoctrine()->getManager();
$em->persist($set);
$em->flush();
}
private function brutalHack($navigation, $form) {
$nav = array();
if (count($navigation->getLinksArray()) == 0) {
$nav[$form['url0']->getData()] = $form['name0']->getData();
}
for ($i = 0; $i < count($navigation->getLinksArray()); $i++) {
$key = $form['url' . $i]->getData();
$value = $form['name' . $i]->getData();
if ($key != NULL && $value != NULL) {
$nav[$key] = $value;
}
}
$key = $form['url' . $i]->getData();
$value = $form['name' . $i]->getData();
if ($key != NULL && $value != NULL) {
$nav[$key] = $value;
}
$navigation->setLinksArray($nav);
}
//...
}
实体:
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity
* @ORM\Table(name="sett")
* @ORM\HasLifecycleCallbacks
*/
class Sett
{
/**
* @ORM\Id
* @ORM\Column(type="integer")
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @ORM\Column(name="name", length=255)
*/
private $name;
/**
* @ORM\Column(name="content", type="json_array")
*/
private $content;
/**
* @ORM\Column(name="edited_at", type="datetime")
*/
private $editedAt;
/**
* @ORM\Column(name="created_at", type="datetime")
*/
private $createdAt;
/**
* @ORM\PrePersist
*/
public function onPrePersist()
{
$this->createdAt = new \DateTime();
}
/**
* Get id
*
* @return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set name
*
* @param string $name
*
* @return Set
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name
*
* @return string
*/
public function getName()
{
return $this->name;
}
/**
* Set content
*
* @param array $content
*
* @return Set
*/
public function setContent($content)
{
$this->content = $content;
return $this;
}
/**
* Get content
*
* @return array
*/
public function getContent()
{
return $this->content;
}
/**
* Set editedAt
*
* @param \DateTime $editedAt
*
* @return Set
*/
public function setEditedAt($editedAt)
{
$this->editedAt = $editedAt;
return $this;
}
/**
* Get editedAt
*
* @return \DateTime
*/
public function getEditedAt()
{
return $this->editedAt;
}
/**
* Set createdAt
*
* @param \DateTime $createdAt
*
* @return Set
*/
public function setCreatedAt($createdAt)
{
$this->createdAt = $createdAt;
return $this;
}
/**
* Get createdAt
*
* @return \DateTime
*/
public function getCreatedAt()
{
return $this->createdAt;
}
}
数据类:
class Navigation
{
private $linksArray;
public function __construct() {
$this->linksArray=array();
}
function getLinksArray() {
return $this->linksArray;
}
function setLinksArray($linksArray) {
$this->linksArray = $linksArray;
}
function add($key,$value){
$this->linksArray[$key]=$value;
}
}
答案 0 :(得分:1)
我不确定这是否有效,但你应该试一试。
2)如何将数据解析为具有可变字段数的表单。
您可以使用$ options格式发送数据。
控制器中的
$oForm = $this->createForm(YourFormType::class,
$FormObject, [
'your_options' => [
'Checkbox' => 'FieldName1',
'TextArea' => 'FieldName2'
]);
在您的表单中
public function buildForm(FormBuilderInterface $builder, array $options)
{
foreach($options['your_options'] as $key, $option) { //you can name $option as $filedName or whatever you find convenient
$builder->add($option, $key.Type::class);
}
...}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'your_options' => null
])
}