Skip to content

Instantly share code, notes, and snippets.

@webdevilopers
Created February 26, 2015 11:03
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save webdevilopers/461ff76b45046137f968 to your computer and use it in GitHub Desktop.
Save webdevilopers/461ff76b45046137f968 to your computer and use it in GitHub Desktop.
Doctrine ORM custom Aware Filter and Event in Symfony
<?php
namespace Plusquam\Bundle\ContractBundle\Filter;
use Doctrine\ORM\Query\Filter\SQLFilter;
use Doctrine\ORM\Mapping\ClassMetadata;
use Doctrine\Common\Annotations\Reader;
class CompartmentFilter extends SQLFilter
{
protected $reader;
public function setAnnotationReader(Reader $reader)
{
$this->reader = $reader;
}
public function addFilterConstraint(ClassMetadata $targetEntity, $targetTableAlias)
{
if (empty($this->reader)) {
return '';
}
// The Doctrine filter is called for any query on any entity
// Check if the current entity is "compartment aware" (marked with an annotation)
$compartmentAware = $this->reader->getClassAnnotation(
$targetEntity->getReflectionClass(),
'Plusquam\\Bundle\\ContractBundle\\Annotation\\CompartmentAware'
);
if (!$compartmentAware) {
return '';
}
// @see http://stackoverflow.com/questions/12354285/how-can-i-implemented-a-doctrine2-filter-based-on-a-relation
return $targetTableAlias.'.compartment_id = ' . $this->getParameter('compartment_id'); // getParameter applies quoting automatically
}
}
<?php
namespace Plusquam\Bundle\CompartmentBundle\EventListener;
use Doctrine\ORM\Event\LifecycleEventArgs;
use Doctrine\Common\Annotations\Reader;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
class CompartmentPersister
{
private $tokenStorage;
public function __construct(Reader $reader, TokenStorageInterface $tokenStorage)
{
$this->reader = $reader;
$this->tokenStorage = $tokenStorage;
}
public function prePersist(LifecycleEventArgs $args)
{
$entity = $args->getEntity();
// The Doctrine filter is called for any query on any entity
// Check if the current entity is "compartment aware" (marked with an annotation)
$object = new \ReflectionClass($entity);
$compartmentAware = $this->reader->getClassAnnotation(
$object,
'Plusquam\\Bundle\\ContractBundle\\Annotation\\CompartmentAware'
);
if ($compartmentAware) {
$user = $this->tokenStorage->getToken()->getUser();
$compartment = $user->getCompartment();
$entity->setCompartment($compartment);
}
}
}
doctrine:
orm:
filters:
compartment_filter:
class: Plusquam\Bundle\ContractBundle\Filter\CompartmentFilter
enabled: true
<?php
namespace Plusquam\Bundle\ContractBundle\Entity;
use Plusquam\Bundle\ContractBundle\Annotation\CompartmentAware;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity
* @ORM\Table(name="contracts")
* CompartmentAware(compartmentFieldName="compartment_id")
* @CompartmentAware
*/
class Contract
{
/**
* @ORM\Id
* @ORM\Column(type="integer")
* @ORM\GeneratedValue(strategy="AUTO")
*
* @GRID\Column(field="id", visible=false)
*/
private $id;
}
services:
qis.listener.compartmentPersister:
class: Plusquam\Bundle\CompartmentBundle\EventListener\CompartmentPersister
arguments:
- "@annotation_reader"
- "@security.token_storage"
tags:
- { name: doctrine.event_listener, event: prePersist }
@michaelperrin
Copy link

Yep, it seems to come from the article I wrote about Doctrine filters and annotations and it works really fine (in production for a large application with several kind of "something aware" entities) 😃

@webdevilopers
Copy link
Author

Indeed your post was an inspiration for this @michaelperrin. I was looking for a solution that would not only filter the entities for a column but also persist it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment