I have a problem with my project :
Not called :
public function postRemove(LifecycleEventArgs $event)
{
$test = 1;
$test1 = 2;
}
Called :
public function preRemove(LifecycleEventArgs $event)
{
$test = 1;
$test1 = 2;
}
Strange that postRemove is not called. I confirm that the entity is deleted from database. Please give an idea.
public function getSubscribedEvents()
{
return array(
'postPersist',
'postUpdate',
'postRemove' // !!!
);
}
public function postUpdate(LifecycleEventArgs $args)
{
dump('Update');
}
public function postPersist(LifecycleEventArgs $args)
{
dump('Persist');
}
public function postRemove(LifecycleEventArgs $args)
{
dump('Remove');
}
Related
Goal : redirect a user depending on a status, on the whole website when the user is logged.
I need to force the user to be on one page until he has changed his profile
So i try to make a redirection with the event kernel but i've got an infinite loop. however I tried to avoid doing this redirection once the page wanted
So please find what i try to do
class TokenSubscriber implements EventSubscriberInterface {
private $user;
private $tokenStorage;
private $router;
protected $redirect;
public function __construct(TokenStorageInterface $tokenStorage, RouterInterface $router
) {
$this->tokenStorage = $tokenStorage;
$this->router = $router;
}
public function onKernelController(FilterControllerEvent $event) {
$controller = $event->getController();
if (!is_array($controller)) {
return;
}
$this->user = $this->tokenStorage->getToken()->getUser();
if ($this->user->getValider() == 3 && $controller[1] == 'indexUserAction' && $controller[0] instanceof DefaultUserController) {
$this->redirect = null;
} else {
$this->redirect = 'user_index';
}
}
public function onKernelResponse(FilterResponseEvent $event) {
if (null !== $this->redirect) {
$url = $this->router->generate($this->redirect);
$event->setResponse(new RedirectResponse($url));
}
}
public static function getSubscribedEvents() {
return array(
KernelEvents::CONTROLLER => 'onKernelController',
KernelEvents::RESPONSE => 'onKernelResponse',
);
}
}
Now the redirection works but when the page is loaded all my css et javascript are not loader , because the redirection i think.
I work just in the kernel response.
public function onKernelResponse(FilterResponseEvent $event){
if ($event->getRequest()->get('_route') != null && $event->getRequest()->get('_route') != 'user_index') {
$url = $this->router->generate('user_index');
$event->setResponse(new RedirectResponse($url));
}
}
You could try this, but using ->get('_route') should normally only be used for debugging. You should dump the Event and the Response to find out what else you can use.
public function onKernelRequest(GetResponseEvent $event)
if($event->getRequest()->get('_route') != 'user_index'){
$event->setResponse(new Response('[NOT_ALLOWED]'));
}
}
This should solve your issue
public function onKernelController(FilterControllerEvent $event) {
$controller = $event->getController();
if (!is_array($controller)) {
return;
}
$this->user = $this->tokenStorage->getToken()->getUser();
if ($this->user->getValider() == 3 && $controller[1] == 'indexUserAction' && $controller[0] instanceof DefaultUserController) {
$this->redirect = null;
} else {
$this->redirect = 'user_index';
}
// Add this to Empty redirect if on already same page
if($event->getRequest()->get('_route') == 'user_index'){
$this->redirect = null;
}
}
When I insert data into User entity, subscriber below gets fired for pre and post events so I get two records inserted into Dummy entity which is fine up to here. What I need to know is, how can I check which event was fired so that I can use it in setHow() method?
$dummy->setHow(......);
Expected result in Dummy table:
id createdOn how
1 2014-10-16 12:12:00 prePersist
2 2014-10-16 12:12:01 postPersist
Subscriber:
class UserPost implements EventSubscriber
{
public function getSubscribedEvents()
{
return array('prePersist', 'postPersist');
}
public function prePersist(LifecycleEventArgs $args)
{
$this->index($args);
}
public function postPersist(LifecycleEventArgs $args)
{
$this->index($args);
}
public function index(LifecycleEventArgs $args)
{
$em = $args->getEntityManager();
$entity = $args->getEntity();
if ($entity instanceof User) {
$dummy = new Dummy();
$dummy->setCreatedOn(new \DateTime('now'));
$dummy->setHow(.............);
$em->persist($dummy);
$em->flush();
}
}
}
Service:
Service:
entity.subscriber.user_post:
class: Site\MainBundle\EventSubscriber\Entity\UserPost
tags:
- { name: doctrine.event_subscriber }
You can just pass the name of the event in the method call like..
public function prePersist(LifecycleEventArgs $args)
{
$this->index($args, 'prePersist');
}
public function postPersist(LifecycleEventArgs $args)
{
$this->index($args, 'postPersist');
}
public function index(LifecycleEventArgs $args, $event)
{
...
if ($entity instanceof User) {
$dummy = new Dummy();
$dummy->setCreatedOn(new \DateTime('now'));
$dummy->setHow($event);
...
}
}
I have a defined listener watching the onKernelException in which errors could occur.
class SpecificExceptionListener
{
public function onKernelException(GetResponseForExceptionEvent $event)
{
$exception = $event->getException();
if ($exception instanceof SpecificExceptionToBeProcessed) {
// ...
if ($somethingWentWrong) {
// here, redirect to the default/overriden Symfony error page
}
// ...
}
}
}
How do you redirect to the standard/customized error page in case of an error?
For those who might be interested, here's how it can be done:
use Symfony\Bundle\TwigBundle\TwigEngine;
use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
use Symfony\Component\HttpFoundation\Response;
// ...
class SpecificExceptionListener
{
protected $templating;
public function __construct(TwigEngine $templating)
{
$this->templating = $templating;
}
public function onKernelException(GetResponseForExceptionEvent $event)
{
$exception = $event->getException();
if ($exception instanceof SpecificExceptionToBeProcessed) {
// ...
if ($somethingWentWrong) {
// build response to display Symfony default error page
// replace by your own template if needed
$response = new Response();
$response->setContent(
$this->templating->render('TwigBundle:Exception:error.html.twig')
);
$event->setResponse($response);
return;
}
// ...
}
}
}
I created a back-end system by using SonataAdminBundle in order to manage a User and Role entities which have Many-To-Many relation.
Everything goes well until I edited the role of the user.
The error showed up : FatalErrorException: Error: Call to a member function add() on a non-object in /Applications/XAMPP/xamppfiles/htdocs/projectName/vendor/sonata-project/doctrine-orm-admin-bundle/Sonata/DoctrineORMAdminBundle/Model/ModelManager.php line 560
I tried the following commands:
php app/console doctrine:generate:entities projectBundle
php app/console doctrine:schema:update --force
php app/console cache:clear
Notthing changes... :(
Entities
User
<?php
//.. Declare namespace and use
class User implements UserInterface, \Serializable
{
// ...
// Declare variables
public function __construct()
{
$this->roles = new \Doctrine\Common\Collections\ArrayCollection();
}
function getId()
{
return $this->id;
}
public function setName($name)
{
$this->name = $name;
return $this;
}
public function getName()
{
return $this->name;
}
public function setLastName($lastName)
{
$this->lastName = $lastName;
return $this;
}
public function getLastName()
{
return $this->lastName;
}
public function setEmail($email)
{
$this->email = $email;
return $this;
}
public function getEmail()
{
return $this->email;
}
public function setUsername($username)
{
$this->username = $username;
return $this;
}
public function getUsername()
{
return $this->username;
}
public function setPassword($password)
{
$this->password = $password;
return $this;
}
public function getPassword()
{
return $this->password;
}
public function setDateCreated($dateCreated)
{
$this->dateCreated = $dateCreated;
return $this;
}
public function getDateCreated()
{
return $this->dateCreated;
}
public function addRole(Role $role)
{
// Link each role with the user
$role->addUser($this);
$this->roles->add($role);
return $this;
}
public function removeRole(Role $role)
{
// Link each role with the user
$role->removeUser($this);
$this->roles->removeElement($role);
}
public function getRoles()
{
return $this->roles->toArray();
}
public function getSalt()
{
return null;
}
public function eraseCredentials()
{
}
public function equals(User $user)
{
return $user->getUsername() == $this->getUsername();
}
/**
* #ORM\PrePersist
*/
public function setDateCreatedValue()
{
$this->setDateCreated(new \DateTime());
}
function __toString()
{
return $this->getName();
}
public function serialize()
{
return serialize(array(
$this->id,
$this->username,
$this->password,
));
}
public function unserialize($serialized)
{
list (
$this->id,
$this->username,
$this->password,
) = unserialize($serialized);
}
}
Role
<?php
//.. Declare namespace and use
class Role implements RoleInterface
{
// .. Declare variables
public function __construct()
{
$this->users = new \Doctrine\Common\Collections\ArrayCollection();
}
public function getId()
{
return $this->id;
}
public function setName($name)
{
$this->name = $name;
return $this;
}
public function getName()
{
return $this->name;
}
public function setDescription($description)
{
$this->description = $description;
return $this;
}
public function getDescription()
{
return $this->description;
}
public function setDateCreated($dateCreated)
{
$this->dateCreated = $dateCreated;
return $this;
}
public function getDateCreated()
{
return $this->dateCreated;
}
public function addUser(User $user)
{
$user->addRole($this);
$this->users->add($user);
return $this;
}
public function removeUser(User $user)
{
$user->removeRole($this);
$this->users->removeElement($user);
}
public function getUsers()
{
return $this->users;
}
/**
* #ORM\PrePersist
*/
public function setDateCreatedValue()
{
$this->setDateCreated(new \DateTime());
}
function __toString()
{
return $this->getName();
}
public function getRole(){
return $this->getName();
}
}
SonataAdminClass
UserAdmin
<?php
//.. Declare namespace and use
class UserAdmin extends Admin
{
// Fields to be shown on create/edit forms
protected function configureFormFields(FormMapper $formMapper)
{
$formMapper
->add('name', 'text', array('label' => 'Name'))
->add('lastName', 'text', array('label' => 'Last name'))
->add('email') //if no type is specified, SonataAdminBundle tries to guess it
->add('username')
->add('password')
->add('roles','sonata_type_model',array(
'expanded' => true,
'compound' => true,
'multiple' => true,
'by_reference' => true
));
}
// Fields to be shown on filter forms
protected function configureDatagridFilters(DatagridMapper $datagridMapper)
{
$datagridMapper
->add('name')
->add('lastName')
->add('roles')
;
}
// Fields to be shown on lists
protected function configureListFields(ListMapper $listMapper)
{
$listMapper
->addIdentifier('name')
->add('lastName')
->add('email')
->add('roles','sonata_type_model')
;
}
}
RoleAdmin
<?php
//.. Declare namespace and use
class RoleAdmin extends Admin
{
// Fields to be shown on create/edit forms
protected function configureFormFields(FormMapper $formMapper)
{
$formMapper
->add('name', 'text', array('label' => 'Role name'))
->add('description', 'text', array('label' => 'Role description'))
;
}
// Fields to be shown on filter forms
protected function configureDatagridFilters(DatagridMapper $datagridMapper)
{
$datagridMapper
->add('name')
->add('description')
;
}
// Fields to be shown on lists
protected function configureListFields(ListMapper $listMapper)
{
$listMapper
->addIdentifier('name')
->add('description')
;
}
}
I have been trying for a whole day and still not be able to figure it out. Any help would be really appreciated!!
Try to change this
$this->roles->add($role);
to this
$this->roles[] = $role;
I have a postUpdate listener and I'd like to know what the values were prior to the update and what the values for the DB entry were after the update. Is there a way to do this in Symfony 2.1? I've looked at what's stored in getUnitOfWork() but it's empty since the update has already taken place.
You can use this ansfer Symfony2 - Doctrine - no changeset in post update
/**
* #param LifecycleEventArgs $args
*/
public function postUpdate(LifecycleEventArgs $args)
{
$changeArray = $args->getEntityManager()->getUnitOfWork()->getEntityChangeSet($args->getObject());
}
Found the solution here. What I needed was actually part of preUpdate(). I needed to call getEntityChangeSet() on the LifecycleEventArgs.
My code:
public function preUpdate(Event\LifecycleEventArgs $eventArgs)
{
$changeArray = $eventArgs->getEntityChangeSet();
//do stuff with the change array
}
Your Entitiy:
/**
* Order
*
* #ORM\Table(name="order")
* #ORM\Entity()
* #ORM\EntityListeners(
* {"\EventListeners\OrderListener"}
* )
*/
class Order
{
...
Your listener:
class OrderListener
{
protected $needsFlush = false;
protected $fields = false;
public function preUpdate($entity, LifecycleEventArgs $eventArgs)
{
if (!$this->isCorrectObject($entity)) {
return null;
}
return $this->setFields($entity, $eventArgs);
}
public function postUpdate($entity, LifecycleEventArgs $eventArgs)
{
if (!$this->isCorrectObject($entity)) {
return null;
}
foreach ($this->fields as $field => $detail) {
echo $field. ' was ' . $detail[0]
. ' and is now ' . $detail[1];
//this is where you would save something
}
$eventArgs->getEntityManager()->flush();
return true;
}
public function setFields($entity, LifecycleEventArgs $eventArgs)
{
$this->fields = array_diff_key(
$eventArgs->getEntityChangeSet(),
[ 'modified'=>0 ]
);
return true;
}
public function isCorrectObject($entity)
{
return $entity instanceof Order;
}
}
You can find example in doctrine documentation.
class NeverAliceOnlyBobListener
{
public function preUpdate(PreUpdateEventArgs $eventArgs)
{
if ($eventArgs->getEntity() instanceof User) {
if ($eventArgs->hasChangedField('name') && $eventArgs->getNewValue('name') == 'Alice') {
$eventArgs->setNewValue('name', 'Bob');
}
}
}
}