Build your apps, not your tools

 

The goal of the framework is to integrate many independent tools in order to provide a consistent experience for the developer.

Even the framework itself is a Symfony bundle (i.e. a plugin) that can be configured or replaced entirely.

 

What is Symfony?

 

The collection of over twenty independent libraries called the Symfony Components.

 

Http Foundation

Contains the Request and Response classes, as well as other classes for handling sessions and file uploads.

// the URI being requested (e.g. /about) minus any query parameters
$request->getPathInfo();

// retrieve GET and POST variables respectively
$request->query->get('foo');
$request->request->get('bar', 'default value if bar does not exist');

// retrieve SERVER variables
$request->server->get('HTTP_HOST');

// retrieves an instance of UploadedFile identified by foo
$request->files->get('foo');

// retrieve a COOKIE value
$request->cookies->get('PHPSESSID');

// retrieve an HTTP request header, with normalized, lowercase keys
$request->headers->get('host');
$request->headers->get('content_type');

$request->getMethod();    // GET, POST, PUT, DELETE, HEAD
$request->getLanguages(); // an array of languages the client accepts
    



    public function saveBlacklistAction(Request $request)
    {
        $subscriberData = $request->request->get('subscriber');

        //.....

        return new JsonResponse( [ 'example' => 'example data' ] );
        // or
        return new Response( 'Some plain text, <b>or html</b>' );
    }

The Routing Component

The Routing component maps an HTTP request to a set of configuration variables.

Route definition can be done by

 
  • Annotations
  • YAML
  • XML
  • PHP
 
// ...
class BlogController extends Controller
{
    // ...

    /**
     * @Route("/blog")
     */
    public function indexAction()
    {
        // ...
    }
}
// ...
class CampaignController extends Controller
{
    /**
     * @Route(
     *    "/campaign/{campaignId}", 
     *    name="delete_campaign", 
     *    requirements={
     *        "campaignId": "\d+"
     *    }
     * )
     * @Method("DELETE")
     */
    public function deleteCampaignAction($campaignId)
    {
    }
}

The Templating Component

The Templating component provides all the tools needed to build any kind of template system.

// src/AppBundle/Controller/ArticleController.php
namespace AppBundle\Controller;

// ...

class ArticleController extends Controller
{
    public function recentArticlesAction($max = 3)
    {
        // make a database call or other logic
        // to get the "$max" most recent articles
        $articles = ...;

        return $this->render(
            'article/recent_list.html.twig',
            array('articles' => $articles)
        );
    }
}



{# app/Resources/views/article/recent_list.html.twig #}
{% for article in articles %}
    <a href="/article/{{ article.slug }}">
        {{ article.title }}
    </a>
{% endfor %}
{% extends 'base.html.twig' %}

{% block stylesheets %}
    <link href="{{ asset('assets/vendor/materialize/dist/css/materialize.css') }}" rel="stylesheet">

    <link href="{{ asset('assets/vendor.css') }}" rel="stylesheet">
    <link href="{{ asset('assets/app.css') }}" rel="stylesheet">
{% endblock %}

{% block javascripts %}
    <script src="{{ asset('assets/vendor/jquery/dist/jquery.min.js') }}"></script>
    <script src="{{ asset('assets/vendor/materialize/dist/js/materialize.min.js') }}"></script>
    <script src="{{ asset('assets/vendor/angular/angular.min.js') }}"></script>
    <script src="{{ asset('assets/vendor/angular-ui-router/release/angular-ui-router.min.js') }}"></script>

    <script src="{{ asset('assets/vendor.js') }}"></script>
    <script src="{{ asset('assets/app.js') }}"></script>
    <script src="{{ asset('assets/templates.js') }}"></script>

    <script>
        window.PRELOADED_DATA = {
            currentUser: {{ currentUserData | json_encode | raw }},
            permissions: {{ permissions | json_encode | raw }}
        };
    </script>
{% endblock %}

{% block body %}
    <div class="app" ng-app="app">
		<div ui-view></div>
    </div>
{% endblock %}
class DefaultController extends Controller
{
    /**
     * @Route("/", name="home")
     * @Method("GET")
     */
    public function indexAction()
    {
	    $currentUserData = $this->get('repository.user')
                            ->getCurrentUserData($this->getUser());
	    $permissions = $this
                        ->get('repository.permission')->findAllAsArray();

	    return $this->render('AppBundle:Default:index.html.twig',
			[
				'currentUserData' => $currentUserData,
				'permissions' => $permissions
			]
			);
    }
}

Security

 

The Security component provides a complete security system for your web application. 

 
security:
    encoders:
        AppBundle\Entity\User: plaintext
    providers:
        webauth:
            id: webauth.security.authentication.user_provider
    firewalls:
        dev:
            pattern: ^/(_(profiler|wdt|error)|css|images|js)/
            security: false
        rest:
            pattern: ^/(template\/view\/\d+\/\d+)/
            security: false
        webauth_secured:
            pattern: ^/
            webauth: true
            anonymous: false
    access_control:
        - { path: ^/campaign, roles: ROLE_ADMIN }
        - { path: ^/asset, roles: [ ROLE_ADMIN , ROLE_USER ] }



public function helloAction($name)
{
    // The second parameter is used to specify on what object the role is tested.
    $this->denyAccessUnlessGranted('ROLE_ADMIN', null, 'Unable to access this page!');

    // ...
}

DependencyInjection component

 

(aka) Service Container

 
class HelloController extends Controller
{
    // ...

    public function sendEmailAction()
    {
        // ...
        $mailer = $this->get('app.mailer');
        $mailer->send('ryan@foobar.net', ...);
    }
}
# app/config/services.yml
services:
    app.mailer:
        class:        AppBundle\Mailer
        arguments:    [sendmail]

Configuring Symfony

 
# app/config/config.yml
imports:
    - { resource: parameters.yml }
    - { resource: security.yml }

framework:
    secret:          '%secret%'
    router:          { resource: '%kernel.root_dir%/config/routing.yml' }
    # ...

# Twig Configuration
twig:
    debug:            '%kernel.debug%'
    strict_variables: '%kernel.debug%'

# ...

The Bundle System

 

A bundle is similar to a plugin in other software.
The key difference is that 
everything is a bundle in Symfony

// app/AppKernel.php
public function registerBundles()
{
    $bundles = array(
        new Symfony\Bundle\FrameworkBundle\FrameworkBundle(),
        new Symfony\Bundle\SecurityBundle\SecurityBundle(),
        new Symfony\Bundle\TwigBundle\TwigBundle(),
        new Symfony\Bundle\MonologBundle\MonologBundle(),
        new Symfony\Bundle\SwiftmailerBundle\SwiftmailerBundle(),
        new Symfony\Bundle\DoctrineBundle\DoctrineBundle(),
        new Symfony\Bundle\AsseticBundle\AsseticBundle(),
        new Sensio\Bundle\FrameworkExtraBundle\SensioFrameworkExtraBundle(),
        new AppBundle\AppBundle(),
    );

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

    return $bundles;
}

Databases and Doctrine

 

Doctrine is totally decoupled from Symfony and using it is optional.
Doctrine ORM aims to let you map objects to a relational database (such as 
MySQLPostgreSQL or Microsoft SQL). If you prefer to use raw database queries, this is easy, and explained in the "How to Use Doctrine DBAL" cookbook entry.

// src/AppBundle/Entity/Product.php
namespace AppBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity
 * @ORM\Table(name="product")
 */
class Product
{
    /**
     * @ORM\Column(type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;

    /**
     * @ORM\Column(type="string", length=100)
     */
    protected $name;

    /**
     * @ORM\Column(type="decimal", scale=2)
     */
    protected $price;

    /**
     * @ORM\Column(type="text")
     */
    protected $description;
}
// src/AppBundle/Controller/DefaultController.php

// ...
use AppBundle\Entity\Product;
use Symfony\Component\HttpFoundation\Response;

// ...
public function createAction()
{
    $product = new Product();
    $product->setName('A Foo Bar');
    $product->setPrice('19.99');
    $product->setDescription('Lorem ipsum dolor');

    $em = $this->getDoctrine()->getManager();

    $em->persist($product);
    $em->flush();

    return new Response('Created product id '.$product->getId());
}
$repository = $this->getDoctrine()
    ->getRepository('AppBundle:Product')


// query by the primary key (usually "id")
$product = $repository->find($id);

// dynamic method names to find based on a column value
$product = $repository->findOneById($id);
$product = $repository->findOneByName('foo');

// find *all* products
$products = $repository->findAll();

// find a group of products based on an arbitrary column value
$products = $repository->findByPrice(19.99);



// query for one product matching by name and price
$product = $repository->findOneBy(
    array('name' => 'foo', 'price' => 19.99)
);

// query for all products matching the name, ordered by price
$products = $repository->findBy(
    array('name' => 'foo'),
    array('price' => 'ASC')
);
  • EventDispatcher - Implements the Mediator pattern in a simple and effective way to make projects truly extensible.
  • Console - Eases the creation of beautiful and testable command line interfaces.
  • OptionsResolver - Helps you configuring objects with option arrays.
  • Serializer - Turns objects into a specific format (XML, JSON, Yaml, ...) and the other way around.
  • Validator - A system for creating rules about data and then validating whether or not user-submitted data follows those rules.
1
Made with Slides.com