提问者:小点点

如何在symfony中为sonata block服务添加转发器(克隆)字段


我正在使用CMS选项进行symfony(4.2)项目。所以我决定使用索纳塔束来实现类似WP的CMS。我已经安装并使用了SonataAdminBundle、SonataDiabundle、SonataLockBundle。。。等等。我还为页面块创建了带有基本表单字段的定制服务,它对我来说很好。现在我想创建一个具有重复字段的表单,如克隆系统

我创建了一个名为CloneType的新表单类型,并自定义了表单模板。还在块服务文件中添加了CloneType字段,现在表单如下图所示

https://i.stack.imgur.com/WmYFg.png

在浏览器中检查时,我的输入如下所示

 <input type="text" id="s9fdc9db89c_settings_cxi_different_title" name="s9fdc9db89c[settings][cxi_different][title_1]" class=" form-control" value="test">
 <input type="text" id="s9fdc9db89c_settings_cxi_different_title" name="s9fdc9db89c[settings][cxi_different][title_2]" class=" form-control" value="test">

src/Form/Type/CloneType。php

<?php
namespace App\Form\Type;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\Extension\Core\Type\FormType;
use Symfony\Component\OptionsResolver\OptionsResolver;

class CloneType extends AbstractType
{
    public function getParent()
    {
        return FormType::class;
    }
}

模板/sonataadmin/forms/clone。细枝html

{% block clone_widget %}
  {% spaceless %}        
    <div class="clone-wrapper">
        <div id="clonedInput1" class="clonedInput">
            {{- form_widget(form) -}}
            {{- form_errors(form) -}}
            <div class="actions">
                <a class="btn btn-info clone">Clone</a> 
                <a class="btn btn-warning remove">Remove</a>
            </div>
        </div>
    </div>      
 {% endspaceless %}
 {% block javascripts %}
    <script type="text/javascript"> 
        var regex = /^(.+?)(\d+)$/i;
        var cloneIndex = $(".clonedInput").length;

        function clone(){
            $(this).parents(".clonedInput").clone()
                .appendTo("clone-wrapper")
                .attr("id", "clonedInput" +  cloneIndex)
                .find("*")
                .each(function() {
                    var id = this.id || "";
                    var match = id.match(regex) || [];
                    if (match.length == 3) {
                        this.id = match[1] + (cloneIndex);
                    }
                })
                .on('click', 'a.clone', clone)
                .on('click', 'a.remove', remove);
            cloneIndex++;
        }
        function remove(){
            $(this).parents(".clonedInput").remove();
        }
        $("a.clone").on("click", clone);

        $("a.remove").on("click", remove);         
    </script>
 {% endblock %}        
{% endblock %}

SRC/Application/Sonata/BlockBundle/Block/Cxi差分块ervice.php

<?php 
namespace App\Application\Sonata\BlockBundle\Block;

use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\Extension\Core\Type\FormType;
use Sonata\Form\Type\ImmutableArrayType;
use Sonata\Form\Validator\ErrorElement;
use Sonata\AdminBundle\Form\FormMapper;
use Sonata\BlockBundle\Meta\Metadata;
use Sonata\BlockBundle\Block\BlockContextInterface;
use Sonata\BlockBundle\Model\BlockInterface;
use Sonata\BlockBundle\Block\Service\AbstractBlockService;
use App\Application\Sonata\PageBundle\Entity\Block;
use App\Form\Type\CloneType;
use Sonata\AdminBundle\Admin\AdminInterface;
class CxiDifferentBlockService extends AbstractBlockService
{
 public function buildEditForm(FormMapper $formMapper, BlockInterface $block)
 {
    $formMapper
        ->add('settings', ImmutableArrayType::class, [
            'keys' => [
                ['title', TextType::class, [
                    'label' => 'Title (H2)',
                    'required' => false,
                ]],
                [$this->getCloneBuilder($formMapper), null, []],                   
            ],
        ])
    ;        
  }
  protected function getCloneBuilder(FormMapper $formMapper)
  {
     return $formMapper->create('cxi_different', CloneType::class, ['required' => false,'by_reference' => false,'allow_extra_fields'=>true])
         ->add('title', TextType::class,['required' => false, 'allow_extra_fields'=>true, 'by_reference' => false])
    ;
  }
}

我想更新数据库中克隆的字段值。但它不起作用。我在提交表格时检查了数据。sonata表单不会添加到post数组中的克隆字段中。post数组看起来低于实际结果

实际结果:

Array(
 [title] => test
 [cxi_different] => Array
    (
        [title_1] => test
    )
)

预期结果:

Array(
 [title] => test
 [cxi_different] => Array
    (
        [title_1] => test
        [title_2] => test
    )
) 

提前谢谢!


共1个答案

匿名用户

我已经使用CollectionType实现了这一点,并按照以下步骤实现了这一点

步骤1:我在src/Form/CloneFormT中添加了新的FormTypeype.php

<?php

namespace App\Form\Type;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Sonata\AdminBundle\Form\Type\CollectionType;

final class CloneFormType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options): void
    {
        $builder
            ->add('title_1', TextType::class)
            ->add('title_2', TextType::class)
            ;
    }
}

第二步:现在BlockService应该是这样的

<?php 
namespace App\Application\Sonata\BlockBundle\Block;

use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\Extension\Core\Type\FormType;
use Sonata\Form\Type\ImmutableArrayType;
use Sonata\Form\Validator\ErrorElement;
use Sonata\AdminBundle\Form\FormMapper;
use Sonata\BlockBundle\Meta\Metadata;
use Sonata\BlockBundle\Block\BlockContextInterface;
use Sonata\BlockBundle\Model\BlockInterface;
use Sonata\BlockBundle\Block\Service\AbstractBlockService;
use App\Application\Sonata\PageBundle\Entity\Block;
use App\Form\CloneFormType;
use Sonata\AdminBundle\Admin\AdminInterface;
class CxiDifferentBlockService extends AbstractBlockService
{
 public function buildEditForm(FormMapper $formMapper, BlockInterface $block)
 {
    $formMapper
        ->add('settings', ImmutableArrayType::class, [
            'keys' => [
                ['title', TextType::class, [
                    'label' => 'Title (H2)',
                    'required' => false,
                ]],
                ['cxi_different', CollectionType::class, [
                    'required' => false,
                    'allow_add' => true,
                    'allow_delete' => true,
                    'prototype' => true,
                    'by_reference' => false,
                    'allow_extra_fields' => true,
                    'entry_type' => CloneFormType::class,
                ]],                  
            ],
        ])
    ;        
  }
}

步骤3:您可以删除以下文件。使用此CollectionType时不需要它

  1. src/Form/Type/CloneType。php