Symfony / Sonata: Thêm chức năng nhân bản trong một CRUD

Để thêm tính năng nhân bản đối tượng vào danh sách CRUD, bạn cần sửa danh sách bằng cách thêm nút, cấu hình một tuyến đường, thực hiện mã nhân bản đối tượng, và cuối cùng, tham chiếu đến bộ điều khiển sẽ chứa chức năng của chúng ta trong giao diện của chúng ta, thông qua dịch vụ của nó. Thêm nút: Trong bộ điều khiển của bạn, thêm nút bằng cách tham chiếu đến mẫu nút. Ở đây chúng ta thiết lập đường dẫn 'Admin/list__action_clone.html.twig'. Hệ thống sẽ tìm kiếm tệp tại: /templates/Admin/list__action_clone.html.twig
   protected function configureListFields(ListMapper $listMapper)
    {

        $listMapper->addIdentifier('id', null, ['label' => 'id']);
        $listMapper->addIdentifier('label', null, ['label' => 'type']);  
        $listMapper->addIdentifier('description', null, ['label' => 'Label']);
        $listMapper->add('actif', null, ['editable' => true]);
        $listMapper->add('_action', null, [
				'actions' => [
					'clone' => [
						'template' => 'Admin/list__action_clone.html.twig'
					]
				]
			]);
        
    }
Nội dung của tệp twig của chúng ta rất đơn giản. Nó chỉ là hiển thị một biểu tượng.
<a  class="btn btn-sm btn-default" 
    href="{{ admin.generateObjectUrl('clone', object) }}" 
    title="{{ 'Clone'|trans({}, 'default') }}" 
    alt="{{ 'Clone'|trans({}, 'default') }}">
	<i class="fa fa-clone"></i>
</a>

Bước tiếp theo là tạo tuyến đường trong bộ điều khiển của chúng ta:
    protected function configureRoutes(RouteCollection $collection)
    {
        $collection->add('clone', $this->getRouterIdParameter().'/clone');
    }
Và bước cuối cùng, nhân bản đối tượng của chúng ta cùng với tất cả cấu hình của nó. Để làm điều này, chúng ta sẽ tạo một bộ điều khiển cụ thể dành riêng cho quản lý các chức năng bổ sung của chúng ta và thêm nó vào dịch vụ của chúng ta để nó trở nên có sẵn. Trong App/Admin, chúng ta sẽ tạo một tệp gọi là CustomAction.php sẽ chứa chức năng cloneAction() của chúng ta. Điều này phải được mở rộng bởi CRUDController và không phải AbstractAdmin như với giao diện của chúng ta. Đó là lý do tại sao chúng ta đặt chức năng của mình trong một tệp mới. Nhưng nó cũng cho phép chúng ta tái sử dụng chức năng này nếu cần. Trong src/Admin/CustomAction.php:
<?php
namespace App\Admin;

use Sonata\AdminBundle\Controller\CRUDController;
use Symfony\Component\HttpFoundation\RedirectResponse;

class CustomAction extends CRUDController
{
    
    
    /**
     * @param $id
     */
    public function cloneAction($id)
    {
        $object = $this->admin->getObject($id);
        $objectConf=$object->getWtypeWconf()->toArray();
    
    
        if (!$object) {
            throw new NotFoundHttpException(sprintf('unable to find the object with id: %s', $id));
        }
    
        $clonedObject = clone $object;
        $clonedObject->unsetId();
        $clonedObject->setLabel($object->getLabel().' clone('.uniqid().')');
        $this->admin->create($clonedObject);
        if(!empty($objectConf)){
            foreach($objectConf as $c){
                $clonedConf=clone $c;
                $clonedConf->setWconfTypcont($clonedObject);
                $this->admin->create($clonedConf);
            }
        }
        $this->addFlash('sonata_flash_success', 'L\'élément a correctement été dupliqué.');
        return new RedirectResponse($this->admin->generateUrl('list'));
    
        // if you have a filtered list and want to keep your filters after the redirect
        // return new RedirectResponse($this->admin->generateUrl('list', ['filter' => $this->admin->getFilterParameters()]));
    }
}
Như bạn có thể thấy, chức năng nhân bản của chúng ta chịu trách nhiệm nhân bản đối tượng của chúng ta cũng như tất cả các mối quan hệ OneToMany của nó. Dòng $clonedConf->setWconfTypcont($clonedObject); được sử dụng để đặt id của mối quan hệ cha trong trường của mối quan hệ con. Nếu không, tất cả các đối tượng sẽ giữ mối quan hệ của họ với đối tượng ban đầu. Bước cuối cùng, chúng ta cần tham chiếu bộ điều khiển mới của chúng ta trong dịch vụ của giao diện chúng ta. Trước:
admin.wtype:
    class: App\Admin\WtypeAdmin
    arguments: [~, App\Entity\Wtype, ~]
    calls:
        - [addChild, ["@admin.wconf"]] 
    tags:
        - { name: sonata.admin, manager_type: orm, label: "Types de contrats" }
    public: true
Sau:
    admin.wtype:
        class: App\Admin\WtypeAdmin
        arguments: [~, App\Entity\Wtype, App\Admin\CustomAction]
        calls:
            - [addChild, ["@admin.wconf"]] 
        tags:
            - { name: sonata.admin, manager_type: orm, label: "Types de contrats" }
        public: true