Skip to content

Instantly share code, notes, and snippets.

@ArchTaqi
Last active July 8, 2019 13:55
Show Gist options
  • Save ArchTaqi/293ac5d771aced9398aac970070cbd52 to your computer and use it in GitHub Desktop.
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
<?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);
}
}
<?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;
}
}
<?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;
}
}
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