Логика запроса формы обработки Symfony

Извините, если этот вопрос слишком запутан, но есть ли общий способ обработки запроса формы в Symfony? (Я использую SF 4).

На данный момент у меня в контроллере есть логика:

$formBooking = $this->createForm(BookingType::class);

    $formBooking->handleRequest($request);

    if ($formBooking->isSubmitted() && $formBooking->isValid()) {
        // perform actions ...

У меня есть несколько форм на одной странице, поэтому мой контроллер становится все больше и больше.

Я хотел создать новую папку, например Действие, и поместить сюда логическую.

И сделайте в моем контроллере:

 $formBooking = $this->createForm(BookingType::class);

 // $bookingAction = new App\Action\BookingAction
 $bookingAction->handleRequest($formBooking, $request);

Я просто хочу знать, есть ли для этого «официальный» способ?

У вас есть два способа разделить код: сначала создайте множество контроллеров на основе вашей бизнес-логики. во-вторых, перейти к обслуживанию вашей бизнес-логики, чтобы сохранить уровень верхнего уровня вашего контроллера.

Yanis-git 19.06.2018 09:48

Да, я перейду к действию, я не хочу смешивать с сервисами, поскольку действие предназначено только для обработки форм. Для меня более логично оставить контроллеры на верхнем уровне.

Vincent Decaux 19.06.2018 10:11

Тщательно продумайте первый комментарий. Ограничение одного действия на контроллер решит проблему выхода контроллеров из-под контроля. И устраните предлагаемое вами довольно неудобное разделение BookingAction.

Cerad 19.06.2018 13:42

К сведению, почему это разделение неудобно? SymfonyDoc говорит, что лучше отправлять запрос формы в том же методе / контроллере. Лучше создать новый контроллер и установить действие формы на этот контроллер? Спасибо.

Vincent Decaux 19.06.2018 14:08

Ваш первый код - это «стандартный» способ обработки форм. Раздел, который вы пометили «// выполнить действия», - это то, что вы могли бы подумать о переходе на другую службу. Предполагая, что это сложнее, чем просто сохранить объект бронирования и перенаправить. Служба не должна знать форму или запрос. Но опять же, если ваша основная цель - сократить код контроллера, то одно действие на контроллер - это легкая отправная точка.

Cerad 19.06.2018 15:02
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Symfony Station Communiqué - 17 февраля 2023 г
Symfony Station Communiqué - 17 февраля 2023 г
Это коммюнике первоначально появилось на Symfony Station , вашем источнике передовых новостей Symfony, PHP и кибербезопасности.
Управление ответами api для исключений на Symfony с помощью KernelEvents
Управление ответами api для исключений на Symfony с помощью KernelEvents
Много раз при создании api нам нужно возвращать клиентам разные ответы в зависимости от возникшего исключения.
0
5
97
1

Ответы 1

Вы можете создать абстрактный «BaseController» и унаследовать свой другой контроллер. Я не думаю, что это «официальный» способ, но он кажется правильным.

В моем примере я установил диспетчер сущностей, фабрику форм и маршрутизацию как службы. Кроме того, он называется BaseManager, так как вся моя логика находится в файле менеджера, в то время как у моего контроллера нет кода (это просто вызов моего менеджера, за исключением особых случаев)

Для этого просто обратитесь к своему сервису, и пусть ваш контроллер будет главным, но простым и понятным.

## Controller##
<?php
namespace AppBundle\Controller;
use AppBundle\Entity\Category;
use AppBundle\Form\CategoryType;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\HttpFoundation\Request;
/**
 * @Route("/admin/category")
 */
class CategoryController extends Controller
{
    /**
     * @Template()
     * @Route("/", name = "category_index")
     * @return array
     */
    public function indexAction()
    {
        $categories = $this->get('app.category.manager')->find();
        return array('categories' => $categories);
    }
    /**
     * @Template()
     * @Route("/", name = "category_menu")
     * @return array
     */
    public function menuAction()
    {
        $categories = $this->getDoctrine()->getRepository('AppBundle:Category')->findAllOrdered("ASC");
        return array('categories' => $categories);
    }
    /**
     * @Template()
     * @Route("/icones/glyficones", name = "category_icones_glyficones")
     * @return array
     */
    public function fontawesomeAction()
    {
        return array();
    }
    /**
     * @Template()
     * @Route("/icones/fontawesome", name = "category_icones_fontawesome")
     * @return array
     */
    public function glyficoneAction()
    {
        return array();
    }
    /**
     * @Template()
     * @Route("/new", name = "category_create")
     * @param Request $request
     * @return array
     */
    public function newAction(Request $request)
    {
        return $this->get('app.category.manager')->save($request);
    }
    /**
     * @Template()
     * @Route("/{id}/edit", name = "category_edit")
     * @param Request $request
     * @param $id
     * @return array
     */
    public function editAction(Request $request, $id)
    {
        return $this->get('app.category.manager')->edit($request, $id);
    }
    /**
     * @Template()
     * @Route("/{id}/delete", name = "category_delete")
     * @param Request $request
     * @param $id
     * @return array
     */
    public function deleteAction(Request $request, $id)
    {
        return $this->get('app.category.manager')->delete($request, $id);
    }
}

Базовый менеджер

<?php
namespace AppBundle\Manager;
use AppBundle\Form\CategoryType;
use Symfony\Bundle\FrameworkBundle\Routing\Router;
use Symfony\Component\Form\Form;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RedirectResponse;
abstract class BaseManager
{
    protected $em;
    protected $formFactory;
    protected $router;
    /**
     * CategoryManager constructor.
     * @param $em
     * @param $formFactory
     * @param Router $router
     */
    public function __construct($em, $formFactory, Router $router)
    {
        $this->em = $em;
        $this->formFactory = $formFactory;
        $this->router = $router;
    }
    /**
     * @param $entity
     */
    protected function persistAndFlush($entity)
    {
        $this->em->persist($entity);
        $this->em->flush();
    }
    /**
     * @param $entity
     */
    protected function removeAndFlush($entity)
    {
        $this->em->remove($entity);
        $this->em->flush();
    }
    /**
     * @param Request $request
     * @param Form $form
     * @param $entity
     * @param $path
     * @return array|RedirectResponse
     */
    protected function handleBaseForm(Request $request, Form $form, $entity, $path)
    {
        $form->handleRequest($request);
        if ($form->isSubmitted() && $form->isValid()) {
            $this->persistAndFlush($entity);
            return new RedirectResponse($this->router->generate($path));
        }
        return array('form' => $form->createView());
    }
    /**
     * @param $route
     * @return RedirectResponse
     */
    protected function redirect($route)
    {
        return new RedirectResponse($this->router->generate($route));
    }
}

А вот пример, простой примитив из сущности "Категория".

Менеджер по конкретному объекту

<?php
namespace AppBundle\Manager;
use AppBundle\Entity\Category;
use AppBundle\Form\CategoryType;
use Symfony\Bundle\FrameworkBundle\Routing\Router;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RedirectResponse;
/**
 * Class CategoryManager
 * @package AppBundle\Manager
 */
class CategoryManager extends BaseManager
{
    /**
     * CategoryManager constructor.
     * @param $em
     * @param $formFactory
     * @param Router $router
     */
    public function __construct($em, $formFactory, Router $router)
    {
        parent::__construct($em, $formFactory, $router);
    }
    /**
     * @return mixed
     */
    public function find()
    {
        return $this->em->getRepository('AppBundle:Category')->findAll();
    }
    /**
     * @param Request $request
     * @return array
     */
    public function save(Request $request)
    {
        $category = new Category();
        return $this->handleForm($request, $category);
    }
    /**
     * @param Request $request
     * @param $id
     * @return array|RedirectResponse
     */
    public function edit(Request $request, $id)
    {
        $category = $this->em->getRepository('AppBundle:Category')->find($id);
        return $this->handleForm($request, $category);
    }
    /**
     * @param Request $request
     * @param $id
     * @return RedirectResponse
     */
    public function delete(Request $request, $id)
    {
        $category = $this->em->getRepository('AppBundle:Category')->find($id);
        $this->persistAndFlush($category);
        return $this->redirect('category_index');
    }
    /**
     * @param Request $request
     * @param Category $category
     * @return array|RedirectResponse
     */
    public function handleForm(Request $request, $category)
    {
        $form = $this->formFactory->create(CategoryType::class, $category);
        return $this->handleBaseForm($request, $form, $category, "category_index");
    }
}

На всякий случай вот мой файл services.yaml

services:
  app.category.manager:
    class: AppBundle\Manager\CategoryManager
    arguments: [ '@doctrine.orm.entity_manager', '@form.factory', '@router' ]

  fos_user.doctrine_registry:
      alias: doctrine

Надеюсь, это поможет решить вашу проблему и получить более чистый код. Обратите внимание, что это личное решение, и, вероятно, есть решения получше. Но этот рабочий, который мне кажется чище, чем просто позволить контроллеру иметь всю логику.

Другие вопросы по теме