I installed this free plugin and now the whole website crashed! It can´t take that long to add this simple feature! Why is our website so slow?! Can we add a new language to the site by tomorrow? Sulu CMS Batteries included! Thanks to Symfony.
I'm Thomas Schedler @chirimoya | https://github.com/chirimoya ... head of development and technical consultant. Young father trying to master Heston Blumenthal recipes.
Sulu routing summarized – CMF ChainRouter replaces the default routing system – and works by accepting a set of prioritized Routers – The Symfony default Router is registered with the highest priority
Sulu routing summarized – CMF ChainRouter replaces the default routing system – and works by accepting a set of prioritized Routers – The Symfony default Router is registered with the highest priority – DynamicRouters handle all the dynamically defined routes (pages, redirects, …)
Reverse Proxy Caches – A HTTP Cache is a full page cache – It bypasses your application entirely, if the cache entry is valid – HTTP cache headers are used to mark a response cacheable and for how long
Reverse Proxy Caches – A HTTP Cache is a full page cache – It bypasses your application entirely, if the cache entry is valid – HTTP cache headers are used to mark a response cacheable and for how long – Symfony comes with a reverse proxy written in PHP
Reverse Proxy Caches – A HTTP Cache is a full page cache – It bypasses your application entirely, if the cache entry is valid – HTTP cache headers are used to mark a response cacheable and for how long – Symfony comes with a reverse proxy written in PHP – Switch to something more robust like Varnish without any problem
Reverse Proxy Caches – A HTTP Cache is a full page cache – It bypasses your application entirely, if the cache entry is valid – HTTP cache headers are used to mark a response cacheable and for how long – Symfony comes with a reverse proxy written in PHP – Switch to something more robust like Varnish without any problem https://tomayko.com/blog/2008/things-caches-do
Reverse Proxy Caches – A HTTP Cache is a full page cache – It bypasses your application entirely, if the cache entry is valid – HTTP cache headers are used to mark a response cacheable and for how long – Symfony comes with a reverse proxy written in PHP – Switch to something more robust like Varnish without any problem https://tomayko.com/blog/2008/things-caches-do
ESI - Edge Side Includes – The ESI specification describes tags to communicate with the gateway cache – In Symfony the is implemented – If the response contains ESI tags, the cache either requests the page fragment from the backend or embeds the fresh cache entry
Customizing Models – Doctrine doesn't support model customization – Inheritance leads to multiple tables for the same data structure – Sulu’s PersistenceBundle allows to replace models via configuration
Customizing Models – Doctrine doesn't support model customization – Inheritance leads to multiple tables for the same data structure – Sulu’s PersistenceBundle allows to replace models via configuration – Inspired by Sylius ResourceBundle
// src/AppBundle/EntityTag.php namespace AppBundle\Entity; use Sulu\Bundle\TagBundle\Entity\Tag as SuluTag; class Tag extends SuluTag { public $description; }
// src/AppBundle/EntityTag.php namespace AppBundle\Entity; use Sulu\Bundle\TagBundle\Entity\Tag as SuluTag; class Tag extends SuluTag { public $description; } // src/AppBundle/Resources/config/doctrine/Tag.orm.xml
// src/AppBundle/EntityTag.php namespace AppBundle\Entity; use Sulu\Bundle\TagBundle\Entity\Tag as SuluTag; class Tag extends SuluTag { public $description; } // src/AppBundle/Resources/config/doctrine/Tag.orm.xml
use Sulu\Component\DocumentManager\Event\PublishEvent; use Sulu\Component\DocumentManager\Events; use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class MailSubscriber implements EventSubscriberInterface { ...
/** * {@inheritdoc} */ public static function getSubscribedEvents() { return [ Events::PUBLISH => ['sendNotification', -1000], ]; }
public function sendNotification(PublishEvent $event) { $message = new \Swift_Message('Page Published', 'URL: ' . $event->getDocument()->getResourceSegment());
use Sulu\Component\DocumentManager\Event\PublishEvent; use Sulu\Component\DocumentManager\Events; use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class MailSubscriber implements EventSubscriberInterface { ...
/** * {@inheritdoc} */ public static function getSubscribedEvents() { return [ Events::PUBLISH => ['sendNotification', -1000], ]; }
public function sendNotification(PublishEvent $event) { $message = new \Swift_Message('Page Published', 'URL: ' . $event->getDocument()->getResourceSegment());
Service Container – Foundation for extensibility & customizability – Sulu heavily uses service definitions – Add new functionality (Modulnavigation, Content-Type, ...)
Service Container – Foundation for extensibility & customizability – Sulu heavily uses service definitions – Add new functionality (Modulnavigation, Content-Type, ...) – Extend existing (Smart-Content, Teaser, ...)
Service Container – Foundation for extensibility & customizability – Sulu heavily uses service definitions – Add new functionality (Modulnavigation, Content-Type, ...) – Extend existing (Smart-Content, Teaser, ...) – Overwrite services
use Sulu\Bundle\AdminBundle\Admin\Admin; use Sulu\Bundle\AdminBundle\Navigation\Navigation; use Sulu\Bundle\AdminBundle\Navigation\NavigationItem;
class AppAdmin extends Admin { public function __construct($title) { $rootNavigationItem = new NavigationItem($title); $section = new NavigationItem('navigation.modules');
$myModule = new NavigationItem('app.my_module'); $myModule->setIcon('custom');
$item = new NavigationItem('app.my_module.title'); $item->setAction('my_module/custom'); $myModule->addChild($item);
use Sulu\Bundle\AdminBundle\Admin\Admin; use Sulu\Bundle\AdminBundle\Navigation\Navigation; use Sulu\Bundle\AdminBundle\Navigation\NavigationItem;
class AppAdmin extends Admin { public function __construct($title) { $rootNavigationItem = new NavigationItem($title); $section = new NavigationItem('navigation.modules');
$myModule = new NavigationItem('app.my_module'); $myModule->setIcon('custom');
$item = new NavigationItem('app.my_module.title'); $item->setAction('my_module/custom'); $myModule->addChild($item);
use AppBundle\Contact\CustomContactManager; use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Reference;
class AppCompilerPass implements CompilerPassInterface { public function process(ContainerBuilder $container) { $definition = $container->getDefinition('sulu_contact.contact_manager'); $definition->setClass(CustomContactManager::class); $definition->addArgument(new Reference('app.my_custom_service')); } }
use AppBundle\Contact\CustomContactManager; use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Reference;
class AppCompilerPass implements CompilerPassInterface { public function process(ContainerBuilder $container) { $definition = $container->getDefinition('sulu_contact.contact_manager'); $definition->setClass(CustomContactManager::class); $definition->addArgument(new Reference('app.my_custom_service')); } } // src/AppBundle/AppBundle.php namespace AppBundle; use AppBundle\DependencyInjection\AppCompilerPass; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\HttpKernel\Bundle\Bundle; class AppBundle extends Bundle { public function build(ContainerBuilder $container) { $container->addCompilerPass(new AppCompilerPass()); } }