Create Page Listener
February 2016 · 2 minute read
1. Add the following two lines into the page class in PageBundle/Entity/Page.php to to call the EntityListener:
- @ORM\HasLifecycleCallbacks
- @ORM\EntityListeners({“SelenaSmall\Bundle\PageBundle\Entity\PageListener”})
/**
* Page Entity
*
* @ORM\Entity(repositoryClass="SelenaSmall\Bundle\PageBundle\Entity\PageRepository")
* @ORM\HasLifecycleCallbacks
* @ORM\EntityListeners({"SelenaSmall\Bundle\PageBundle\Entity\PageListener"})
* @ORM\Table(name="page")
* @UniqueEntity(fields={"parent", "slug"})
*/
2. Create PageBundle/Entity/EntityListener.php to listen to the entity.
namespace SelenaSmall\Bundle\PageBundle\Entity;
use Doctrine\ORM\Event\LifecycleEventArgs;
use Doctrine\ORM\Event\PreUpdateEventArgs;
class PageListener {
# region Properties
private $container;
private $isUrlChanged;
private $oldUrl;
# endregion Properties
# region Construst
public function __construct($container) {
$this->container = $container;
$this->isUrlChanged = false;
}
# endregion Construct
# region Protected
/**
* Update the full URL
*
* @param Page $page
* @param LifecycleEventArgs $event
*/
protected function updateUrl(Page $page, LifecycleEventArgs $event) {
//Store the old URL for conditionally updating children after persist
$this->oldUrl = $page->getUrl();
$parentUrl = ";
if ($page->getParent()) {
$parentUrl = $page->getParent()->getUrl();
}
$page->setUrlByParent($parentUrl);
if ((!$event instanceof PreUpdateEventArgs) || $event->hasChangedField('url')) {
$this->isUrlChanged = true;
}
}
/**
* Update the children
*
* @param Page $page
* @param LifecycleEventArgs $event
*/
protected function updateChildUrls(Page $page, LifecycleEventArgs $event) {
// If the URl updated, then update any child page
$pageUrl = $page->getUrl();
if ($this->isUrlChanged) {
return;
}
if (!$page->getChildren()->count()) {
return;
}
$em = $event->getEntityManager();
foreach ($page->getChildren() as $child) {
$child->setUrlByParent($pageUrl);
$query
= 'UPDATE ' . get_class($page) . ' p ' . 'SET p.url = CONCAT(:parentUrl, :slash, p.slug) ' . ' p.parent = :parentId';
// Define parameters
$parameters = array();
$parameters['parentUrl'] = $page->getUrl();
$parameters['slash'] = '/';
$parameters['parentId'] = $page->getId();
// Execute query to update all the children
$em
->createQuery($query)
->setParameters($parameters)
->execute();
$this->updateChildUrls($child, $event);
}
}
# endregion Protected
# region Events
# region Persist
/**
* Page entity prePersist event
*
* @param Page $page
* @param LifecycleEventArgs $event
*/
public function prePersist(Page $page, LifecycleEventArgs $event) {
$this->updateUrl($page, $event);
}
# endregion Persist
# region Update
/**
* Page entity preUpdate event
* @param Page $page
* @param PreUpdateEventArgs $event
*/
public function preUpdate(Page $page, PreUpdateEventArgs $event) {
$this->updateUrl($page, $event);
}
/**
* Page entity postUpdate event
*
* @param Page $page
* @param LifecycleEventArgs $event
*/
public function postUpdate(Page $page, LifecycleEventArgs $event) {
$this->updateChildUrls($page, $event);
}
# endregion Update
# endregion Events
}
3. Add page.entitylistener into the Resources/config/services.yml file in the PageBundle
page.entitylistener:
class: SelenaSmall\Bundle\PageBundle\Entity\PageListener
arguments: ['@service_container']
tags:
- { name: doctrine.orm.entity_listener, connection: default }