Symfony

(For Drupal Developers)

Presented by Larry Garfield (@Crell)

@Crell

Larry implements Huggable
  • Senior Architect, Palantir.net
  • Drupal 8 Web Services Lead
  • Drupal Representative, PHP-FIG
  • Advisor, Drupal Association
  • implements Huggable
Let's learn about Symfony

Symfony 2

  • Tier-1 PHP framework
  • Loosely coupled
  • Helped inspire PHP 5.3-era revolution
  • Incubator for Composer

You

  • Know Drupal 7
  • Kind of know Drupal 8
  • Want to move down-stack

Do I need to learn Symfony to use Drupal 8?

No!

Symfony fullstack

The Symfony architecture

Drupal 8

Drupal 8 architecture

Read the docs!

http://symfony.com/doc/

Here's what to watch out for...

Who is it for?

Drupal
  • Content strategists
  • Site Administrators
  • Content editors
  • "Build stuff without writing code"
Symfony
  • Professional developers
  • Bespoke applications
  • "Make writing code easier"

Configuration

  • No UI
  • Multiple config files (usually YAML)
  • Compiled config/container

Bundles

  • Enable extensions by hacking code
  • "Bundles" have configuration... files
  • "Admin" bundles, eg Sonata Admin Bundle

Sonata Admin Dashboard

The Sonata Admin dashboard

Sonata Admin Posts

The Sonata Admin posts list

Sonata Admin Posts

The Sonata Admin edit screen

Sonata Admin Users

The Sonata Admin users list

Organic Groups?

Panels?

Not a thing

FOSUserBundle

Developing

  • Most dev tools are CLI
  • Code scaffolding (Where did you think Drupal Console got it?)
  • Dev/Prod toggle, by code
  • Prod needs force rebuild

Architecture

functions?

Nope!

Services

  • All meaningful logic in services
  • Services are stateless objects

(Drupal 8 is like that, too)

Unopinionated configuration

PHP, XML, YAML, Annotations

Please pick one!

"The Drupal Way" is stricter than "The Symfony Way"

Drupal is metaprogramming via the UI

Symfony is metaprogramming via YAML

Theming

There is only one template per request

No, really!

Twig inheritance

index.html.twig


{% extends 'base.html.twig' %}

{% block body %}
  

Welcome to Symfony {{ constant('Symfony\\Component\\HttpKernel\\Kernel::VERSION') }}

Your application is ready to start working on it at: {{ base_dir }}/

What's next?

Read Symfony documentation to learn How to create your first page in Symfony

{% endblock %} {% block stylesheets %} {% endblock %}

base.html.twig


<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8" />
        <title>{% block title %}Welcome!{% endblock %}
        {% block stylesheets %}{% endblock %}
        
    </head>
    <body>
        {% block body %}{% endblock %}
        {% block javascripts %}{% endblock %}
    </body>
</html>
            

Extending

You're supposed to hack core

Wait, WHAT?

app/AppKernel.php


class AppKernel extends Kernel
{
    /**
     * {@inheritDoc}
     */
    public function __construct($environment, $debug)
    {
        // Set the default timezone to UTC.
        date_default_timezone_set('UTC');

        parent::__construct($environment, $debug);
    }

    public function registerBundles()
    {
        $bundles = array(
            new Symfony\Bundle\FrameworkBundle\FrameworkBundle(),
            new Symfony\Bundle\SecurityBundle\SecurityBundle(),
            new Symfony\Bundle\TwigBundle\TwigBundle(),
        );

        if (in_array($this->getEnvironment(), array('dev', 'test'))) {
            $bundles[] = new Symfony\Bundle\WebProfilerBundle\WebProfilerBundle();
            $bundles[] = new Sensio\Bundle\DistributionBundle\SensioDistributionBundle();
        }

        return $bundles;
    }

    // ...
}
            

Symfony project structure

The root directory

Symfony project structure

The web directory

Symfony project structure

The vendor directory

Symfony project structure

The app directory

Symfony project structure

The src directory

Development workflow

Drupal
  • Push buttons
  • Write code
  • Click "clear cache"
  • git commit
  • Profit!
Symfony
  • Write code
  • Run in dev mode
  • Clear prod cache (several cmds)
  • Build deploy snapshot
  • Profit!

Same kernel, different patterns

Drupal always uses View event

Symfony discourages it

Example Symfony controller


namespace AppBundle\Controller;

use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;

class DefaultController extends Controller
{
    /**
     * @Route("/", name="homepage")
     */
    public function indexAction(Request $request)
    {
        // replace this example code with whatever you need
        return $this->render('default/index.html.twig', array(
            'base_dir' => realpath($this->container->getParameter('kernel.root_dir').'/..'),
        ));
    }
}
            

Drupal always wants a render array

Paths and routing

Drupal
  • $module.routing.yml, or event
  • No path nesting
  • Fixed paths with aliasing
Symfony
  • routing.[yml|xml|php], or annotation
  • Path nesting
  • Slugs

Storing data

Drupal
  • Entities
  • State API
  • Configuration API
  • Key/Value
Symfony
  • Doctrine
  • Or whatever you want to use

Doctrine

  • Stand-alone PHP project
  • Simple objects only
  • 1:1 field->property
  • MongoDB requires ODM add-on

Drupal Entities vs Doctrine

Drupal
  • Configuration-driven
  • Fields
  • Multi-value
  • Rich data types
Doctrine
  • All custom classes
  • Simple properties
  • No multi-value
  • Simple data types

Doctrine gotchas

  • Primitive data only
  • SQL and Mongo are different APIs
  • Different event listeners from Symfony
  • Very primitive file handling

But still many similarities!

(In Drupal 8)

Services

  • All meaningful logic in services
  • Services are stateless objects
  • Event listeners are just glue code

Still the same kernel

Hooks ~ Listeners

But also tagged services

Twig

Twig the Templating engine

(modulo template inheritance)

Go forth and make music!

Symfony
Assumption: You know Drupal (version?) Want to learn Symfony Read the docs! Gotchas that are different, so you know not to trip Audience - No expectation of UI config; all config is direct YAML. -- parameters.yml compiled into container -- other config is compiled out to separate PHP file from container, but one big file. - Single dev/prod toggle. - Enable module by editing code. - Code scaffolding from CLI is a big thing. (Will be in D8, too.) - Most dev tools are CLI commands. - Sonata Admin bundle? Still not the same. - Organic Groups: It's Not a Thing Architecture - No functions! (capes) - Theme whole page at once, with one Twig template/inheritance. - Services, shallow access. - Always 4 ways of doing everything: YAML, XML, Annotation, PHP (at least) -- "Drupal way" is much stricter than "Symfony way". -- May even vary by 3rd party bundle within a single project. Stick to one for your own code. - Metaprogramming via YAML/Annotations rather than user config. Both metaprogramming. Extending *- "You're supposed to hack core". (Or at least anything outside vendor.) *- Bundles vs modules: Not huge difference. *- AppBundle ~ custom module - Listeners vs. Hooks -- See KNP videos "Journey to the center of Symfony" -- Symfony limits use of view listener; Drupal uses it heavily. *- Composer all the things. -- Deployment changes, need to produce prod artifact or similar. -- Need to manually regen more (assetic, etc.). Doctrine migrations, run yourself. -- Drupal has more tools to help here (auto-detect out of sync DB, clear cache from UI, etc.) - Nested routes in Symfony, not in Drupal. - No URL aliases. Use lookup slugs instead, manually. Similarities: - Container and services, yo! - HttpKernel, Request/response, kernel listeners - Twig, although used a bit differently (nesting templates) - Hook ~ Listener - Data - Doctrine -- All entities in code -- All fields single-value; need separate Entity for multi-value. -- Many differences between SQL and Mongo, mostly in service names. -- Different event listeners from core. :-( - File handling is even more primitive than Drupal (if you believe that...) - Something about forms? Need to use Symfony forms first...
Security - Authentication/authorization is totally weird, hard, different. -- Security bundle is odd, easy to get wrong. -- See alternative: https://packagist.org/packages/knpuniversity/guard -- security.yml: regex on path to determine needed role. -- Recently added expressions on route def -- Annotations on controller method (http://symfony.com/doc/current/bundles/SensioFrameworkExtraBundle/annotations/security.html)

Larry Garfield

Palantir.net

Making the Web a Better Place

Keep tabs on our work at @Palantir