Last active
July 8, 2019 13:55
-
-
Save ArchTaqi/293ac5d771aced9398aac970070cbd52 to your computer and use it in GitHub Desktop.
Proof of Concept: An approach to Fat models, skinny controllers with Event Dispatcher in Symfony
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php declare(strict_types=1); | |
namespace App\Controller; | |
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; | |
use Symfony\Component\Validator\ConstraintViolationListInterface; | |
use Symfony\Component\HttpFoundation\Request; | |
use App\Event\RepositoryEvent; | |
/** | |
* Class OurAbstractController | |
* @package App\Controller | |
*/ | |
abstract class OurAbstractController extends AbstractController | |
{ | |
/** | |
* Get entity name for CRUD | |
* @return string | |
*/ | |
abstract public function getEntityName(); | |
/** | |
* Get entity service manager | |
* @return mixed | |
*/ | |
abstract protected function getServiceManager(); | |
/** | |
* Standard logic for creating resource | |
* @param Request $request | |
* @param object $entity | |
* @param array $validationGroups | |
* @return $entity | ConstraintViolationListInterface | |
*/ | |
public function createResource(Request $request, $entity, array $validationGroups = []) | |
{ | |
$event = new RepositoryEvent($entity, 'create'); | |
$this->get('event_dispatcher')->dispatch('okApp.pre_validate', $event); | |
$errors = $this->validate($entity, $validationGroups); | |
if (count($errors) > 0) { | |
return $errors; // TODO: use error validation formatter instead! | |
} | |
// TODO: add permissions check | |
$this->getDoctrine()->getManager()->persist($entity); | |
$this->get('event_dispatcher')->dispatch('okApp.pre_flush', $event); | |
$this->getDoctrine()->getManager()->flush(); // save changes to already attached entity | |
$this->get('event_dispatcher')->dispatch('okApp.post_flush', $event); | |
return $entity; | |
} | |
/** | |
* Standard logic for updating resource | |
* | |
* @param Request $request | |
* @param $entity | |
* @param array $validationGroups | |
* @return mixed | |
*/ | |
public function updateResource(Request $request, $entity, array $validationGroups = []) | |
{ | |
$event = new RepositoryEvent($entity, 'update'); | |
$this->get('event_dispatcher')->dispatch('okApp.pre_validate', $event); | |
$errors = $this->validate($entity, $validationGroups); | |
if (count($errors) > 0) { | |
return $errors; // TODO: use error validation formatter instead! | |
} | |
$this->getDoctrine()->getManager()->persist($entity); | |
// TODO: add support of request passing as variable to check _opt status, add $context to $event for more custom handling | |
$this->get('event_dispatcher')->dispatch('okApp.pre_flush', $event); | |
// TODO: add validation, permissions check | |
$this->getDoctrine()->getManager()->flush(); // save changes to already attached entity | |
$this->get('event_dispatcher')->dispatch('okApp.post_flush', $event); | |
return $entity; | |
} | |
/** | |
* Standard logic for deletion resource | |
* | |
* @param $entity | |
* @return mixed | |
*/ | |
public function deleteResource($entity) | |
{ | |
$this->getDoctrine()->getManager()->remove($entity); | |
$event = new RepositoryEvent($entity, 'delete'); | |
$this->get('event_dispatcher')->dispatch('okApp.pre_validate', $event); | |
$this->get('event_dispatcher')->dispatch('okApp.pre_flush', $event); | |
$this->getDoctrine()->getManager()->flush(); // save changes to already attached entity | |
$this->get('event_dispatcher')->dispatch('okApp.post_flush', $event); | |
return $entity; | |
} | |
/** | |
* @param $entity | |
* @param array $groups | |
* @return ConstraintViolationListInterface | |
*/ | |
protected function validate($entity, $groups = null) | |
{ | |
// $groups - empty array must be replaced with NULL. Otherwise none of the validation groups will be checked | |
return $this->get('validator')->validate($entity, empty($groups) ? null : $groups); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php declare(strict_types=1); | |
namespace App\EventListener; | |
use App\Event\RepositoryEvent; | |
use App\Entity\Post; | |
/** | |
* Class PostListener | |
* @package App\EventListener | |
*/ | |
class PostListener | |
{ | |
/** | |
* @var RepositoryEvent | |
*/ | |
protected $event; | |
/** | |
* @var \Psr\Log\LoggerInterface | |
*/ | |
private $logger; | |
/** | |
* BadWordListener constructor. | |
* @param \Psr\Log\LoggerInterface $logger | |
*/ | |
public function __construct(\Psr\Log\LoggerInterface $logger) | |
{ | |
$this->logger = $logger; | |
} | |
/** | |
* @param RepositoryEvent $event | |
*/ | |
public function preValidate(RepositoryEvent $event) | |
{ | |
if (!$event->getData() instanceof Post | |
|| $event->getAction() !== 'create' | |
) { | |
return ; | |
} | |
$this->logger->debug('Post Listner preValidate'); | |
$this->event = $event; | |
} | |
/** | |
* @param RepositoryEvent $event | |
*/ | |
public function onPreFlush(RepositoryEvent $event) | |
{ | |
if (!$event->getData() instanceof Post | |
|| $event->getAction() !== 'create' | |
) { | |
return ; | |
} | |
$this->logger->debug('Post Listner onPostFlush'); | |
$this->event = $event; | |
} | |
/** | |
* @param RepositoryEvent $event | |
*/ | |
public function onPostFlush(RepositoryEvent $event) | |
{ | |
if (!$event->getData() instanceof Post | |
|| $event->getAction() !== 'create' | |
) { | |
return ; | |
} | |
$this->logger->debug('Post Listner onPostFlush'); | |
$this->event = $event; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php declare(strict_types=1); | |
namespace App\Event; | |
use Symfony\Contracts\EventDispatcher\Event; | |
/** | |
* Class RepositoryEvent | |
* @package App\Event | |
*/ | |
class RepositoryEvent extends Event | |
{ | |
/** | |
* Collection of entities or single entity | |
* @var | |
*/ | |
protected $data; | |
/** | |
* @var null | |
*/ | |
protected $action; | |
/** | |
* RepositoryEvent constructor. | |
* @param object $data | |
* @param null $action | |
*/ | |
function __construct($data, $action = null) | |
{ | |
$this->data = $data; | |
$this->action = $action; | |
} | |
/** | |
* @return mixed | |
*/ | |
public function getData() | |
{ | |
return $this->data; | |
} | |
/** | |
* @param mixed $data | |
*/ | |
public function setData($data) | |
{ | |
$this->data = $data; | |
} | |
/** | |
* @return null | |
*/ | |
public function getAction() | |
{ | |
return $this->action; | |
} | |
/** | |
* @param null $action | |
*/ | |
public function setAction($action) | |
{ | |
$this->action = $action; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
app.event_listener.bad_word: | |
class: App\EventListener\PostListener | |
autowire: false | |
tags: | |
- { name: kernel.event_listener, event: okApp.pre_validate, method: preValidate } | |
- { name: kernel.event_listener, event: okApp.pre_flush, method: onPreFlush } | |
- { name: kernel.event_listener, event: okApp.post_flush, method: onPostFlush } | |
arguments: ['@logger'] |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment