Upgrade to Pro — share decks privately, control downloads, hide ads and more …

SymfonyCon Cluj 2017: Batteries included! Thanks to symfony.

SymfonyCon Cluj 2017: Batteries included! Thanks to symfony.

Wachter Johannes

November 17, 2017
Tweet

More Decks by Wachter Johannes

Other Decks in Programming

Transcript

  1. Tired of fixing your CMS 
 instead of creating awesome

    websites? Batteries included! Thanks to Symfony.
  2. I'm Johannes Wachter @wachterjohannes | https://asapo.at | https://github.com/wachterjohannes ... core

    developer and support genius. Never looses his smile, even on release days.
  3. Sulu – Content Management Platform – Full-Stack Symfony – Made

    for businesses – Simple UI – High Performance – Open Source
  4. Where we see us Bicycles Everyone can ride them, many

    can repair it
 (WordPress etc.) Cars Many can ride them, some can repair it
 (Typo3 etc.) Supertanker Need highly specialized staff, expensive and very complex
 (Hybris, OpenText etc.) – Trucks Need a special license, must be configured to your needs
 (EZpublisher, PimCore etc.)
  5. <webspace> <name>example.com</name> <key>example</key> <localizations> <localization language="en" default="true"/> <localization language="de" country="at"/>

    </localizations> <portals> <portal> <name>example.com</name> <key>example</key> <environments> <environment type="prod"> <urls> <url>example.com/{localization}</url> </urls> </environment> <environment type="dev"> <urls> <url>{host}/{localization}</url> </urls> </environment> </environments> </portal>
  6. Templates & Content Types – The structure of the page

    – How that structure is rendered – Each page template is defined by two files: – an XML file that contains the page structure – a Twig file that contains the HTML code – A page structure consists of properties, each of which has a content type
  7. <?xml version="1.0" ?> <template xmlns="http://schemas.sulu.io/template/template" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://schemas.sulu.io/template/template http://schemas.sulu.io/ template/template-1.0.xsd"> <key>default</key>

    <view>templates/default</view> <controller>SuluWebsiteBundle:Default:index</controller> <cacheLifetime>2400</cacheLifetime> <properties> <section name="highlight"> <properties> <property name="title" type="text_line" mandatory="true"> <tag name="sulu.rlp.part"/> </property> <property name="url" type="resource_locator" mandatory="true"> <tag name="sulu.rlp"/> </property> </properties> </section> <property name="article" type="text_editor"/> </properties> </template>
  8. {% extends "master.html.twig" %} {% block content %} <h1 property="title">{{

    content.title }}</h1> <div property="article"> {{ content.article|raw }} </div> {% endblock %}
  9. / /services /blog Request Response Kernel Controller Router Request URI

    Controller & Action Front Controller indexAction() servicesAction blogAction() Response Response Response Model View Services
  10. Router Chain Router / /services /blog Request Response Kernel Controller

    Request URI Controller & Action Front Controller indexAction() servicesAction blogAction() Response Response Response Model View Services Dynamic Router
  11. 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, …)
  12. // app/WebsiteKernel.php
 
 class WebsiteKernel extends AbstractKernel
 {
 /**
 *

    {@inheritdoc}
 */
 protected $name = 'website';
 
 /**
 * @param string $environment
 * @param bool $debug
 */
 public function __construct($environment, $debug)
 {
 parent::__construct($environment, $debug);
 $this->setContext(self::CONTEXT_WEBSITE);
 }
 
 /**
 * {@inheritdoc}
 */
 public function registerBundles()
 {
 $bundles = parent::registerBundles();
 $bundles[] = new Symfony\Cmf\Bundle\RoutingBundle\CmfRoutingBundle();
 return $bundles;
 }
 } $bundles[] = new AppBundle\AppBundle();
  13. // app/config/website/routing.yml app:
 resource: "@AppBundle/Controller/"
 type: annotation
 prefix: /app //

    src/AppBundle/Controller/DefaultController.php namespace AppBundle\Controller;
 
 use Symfony\Bundle\FrameworkBundle\Controller\Controller;
 use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
 
 class DefaultController extends Controller
 {
 /**
 * @Route("/")
 */
 public function indexAction()
 {
 return $this->render('AppBundle:Default:index.html.twig');
 }
 } // src/AppBundle/Resources/views/Default/index.html.twig Hallo World!
  14. Controller Chain Router Router / /services /blog Request Response Kernel

    Request URI Controller & Action Front Controller indexAction() servicesAction blogAction() Response Response Response Model View Services Dynamic Router Default Controller
  15. // app/Resources/templates/pages/default.xml <?xml version="1.0" ?>
 <template xmlns="http://schemas.sulu.io/template/template"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://schemas.sulu.io/template/template http://

    schemas.sulu.io/template/template-1.0.xsd">
 
 <key>default</key>
 
 <view>templates/default</view> 
 <cacheLifetime>2400</cacheLifetime>
 
 <meta>
 <title lang="en">Default</title>
 <title lang="de">Standard</title>
 </meta>
 
 ... </template>
 <controller>AppBundle:Custom:index</controller>
  16. // src/AppBundle/Controller/CustomController.php
 
 namespace AppBundle\Controller;
 
 use Sulu\Bundle\WebsiteBundle\Controller\WebsiteController;
 use Sulu\Component\Content\Compat\StructureInterface;


    
 class CustomController extends WebsiteController
 {
 /**
 * My custom controller action.
 *
 * @param StructureInterface $structure
 * @param bool $preview
 * @param bool $partial
 *
 * @return Response
 */
 public function indexAction(StructureInterface $structure, $preview = false, $partial = false)
 {
 $response = $this->renderStructure(
 $structure,
 [
 // here you can add some custom data for your template
 'myData' => $this->get('my_custom_service')->getMyData(),
 ],
 $preview,
 $partial
 );
 
 return $response;
 }
 }
  17. // app/Resources/templates/pages/default.xml <?xml version="1.0" ?>
 <template xmlns="http://schemas.sulu.io/template/template"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://schemas.sulu.io/template/template http://schemas.sulu.io/template/template-1.0.xsd">


    
 <key>default</key>
 
 <view>AppBundle:Custom:index</view>
 <controller>AppBundle:Custom:index</controller>
 <cacheLifetime>2400</cacheLifetime>
 
 ... </template> // src/AppBundle/Resources/views/Custom/index.html.twig
 
 {% extends "master.html.twig" %}
 
 {% block content %}
 <h1 property="title">{{ content.title }}</h1>
 
 <div property="article">
 {{ content.article|raw }}
 </div>
 {% endblock %} // src/AppBundle/Resources/views/Custom/index.json.twig {{ content|json_encode|raw }} .html.twig
  18. Symfony Events Kernel Events – kernel.request – kernel.response – kernel.controller

    – kernel.view – kernel.terminate … Doctrine Events Lifecycle Events – [pre|post]Remove – [pre|post]Persist – [pre|post]Update – [pre|on|post]Flush – onClear …
  19. Sulu Document Manager Events +----------------------+ | Events | +----------------------+ |

    persist | | hydrate | | remove | | refresh | | copy | | move | | create | | clear | | find | | reorder | | publish | | unpublish | | remove_draft | | flush | | query.create | | query.create_builder | | query.execute | | configure_options | | metadata_load | | restore | +----------------------+ bin/adminconsole sulu:document:subscriber:debug
  20. // src/AppBundle/Document/Subscriber/MailSubscriber.php
 
 namespace AppBundle\Document\Subscriber;
 
 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());
 
 $this->mailer->send($message);
 }
 } <service id="app.document_subscriber.email" class="AppBundle\Document\Subscriber\MailSubscriber"> <argument type="service" id="mailer" /> <tag name="sulu_document_manager.event_subscriber"/> </service>
  21. Service Container – Foundation for extensibility & customizability – Sulu

    heavily uses service definitions – Add new functionality (Modulnavigation, Content-Type, ...) – Extend existing (Smart-Content, Teaser, ...) – Overwrite services