Standing on the shoulders of giants, Silex is a micro framework built on top of Symfony2 components. It provides an ideal environment for throwing together a simple, single file application. We’ll look at a real example of installing and setting up Silex and creating our first application with full dependency injection, templating and all the other features that you would expect of a modern day PHP framework. This session is recommended for anyone looking to break into the Symfony ecosystem with a simple introduction to a small framework build upon the core components of it’s bigger brother (Symfony2).
OO layer for the HTTP specification\nRequest and Response object\nUploaded files, cookies & sessions\n
Lightweight implementation of the Observer design pattern\naddListener with event\ndispatch event\n
Associates a request with the code that will convert it to a response\n
The engine for Silex and Symfony\nThe building blocks for building a framework\n- Reverse Proxy with caching and ESI\n- Exception Listener\n- Functional Testing\nSimple interface to turn a request into a response\n
Simple Dependency Injection Container\n50 lines of code\n
You COULD use Plain Old PHP.\nSingle Page apps\n- Concise\n- Extensible via Pimple\n- Testable abstract Request and Response\n
\n
\n
Easy installation\n
Minimum config required to get you up and running\n
A tip for people who use composer a lot\n
Symfony dependencies and versions\n
Lock file (install specific version)\nAutoload file which we use in our code\n
Minimum bootstrap\nSet’s composers autoloader and sets up Silex\n
PHP Development server\nNo apache required before we get started!\n
No controllers, so all requests will 404.\n
\n
\n
How the framework translates your request into the code that is executed\nEffectively maps Request data to Code\n
Request data & Code\nMethod = HTTP Method\nPattern = URL path\nClosure (anoymous function) = the code\n
Closure returns a string, or a response object\nGET, POST, PUT, DELETE\n\n
\n
\n
This route will only match a Url *with* a name supplied\nParam is passed into the function\n
The default allows it to match / and optionally {name}\n
\n
The results of the convert function passed to Closure\nThis could be an object of a class, for example.\n
Allow us to add arbitrary conditions to a route before it will match\n
Contrived example! 2 routes with asserts\n/word matched the first route\n/4 matches the second\n
Key part of the provided functionality in Silex\n\n
Service providers are a way of reusing code across controllers\nController Providers are a way of reusing Controllers themselves\n
These are provided\nThird party to provide Propel, Redis, Mongo, alternative templating engines, Config (XML/JSON/YAML), Gravatar, Memcache, Solr etc.\n
Silex supports Twig out the box\n
A few more dependencies - silex is very light on its own\ntwig-bridge optional but adds some convenience methods to Twig\n - path and url for UrlGeneratorServiceProvider\n - trans and transchoice for TranslationServiceProvider\n - set of methods for handling forms in templates (which is what we are using)\n - is_granted for SecurityServiceHelper\n
Pass a directory for where the templates can be found\nWe’re not actually using twig at this point - just registering\n
\n
\n
Is everyone familiar with Traits in PHP 5.4?\n“compiler assisted copy & paste”\n
All built-in providers have traits to enhance the Application object\nShort array syntax since we know we’re using 5.4!\n
\n
We add two line to our dependencies - symfony/form and symfony translation.\n
The translation provider is required for the default form layout\nSymfony forms are a talk on there own and there’s docs out there\nSplit the services and traits out into a bootstrap file\n
This looks like too much controller logic\n
We don’t like fat controllers...\n
Refactor form code\nmake it more re-usable\n
Reduce code in controllers\n
form_widget is a twig helper from the symfony bridge\n
Until the invention of twitter bootstrap all my forms looked like this\n
Much better\nExcept now all my forms look like this\n
Any old enough to remember the 1990’s ‘guestbooks’ on websites\n
In handling POST we need to identify the target URL\n\n
We do this with another service provider\nAnd an optional Trait\n
We’re using the trait and registering the provider\n
We use bind to give this route a name, ‘homepage’.\n
Template grown a little since the last time we saw it\nEssentially the only change is the form action\n
Update the method to match\nAdd methods to match to method\nAdd code to validate and save the new entry\nRecap!\n
This creates a guestbook and adds the new entry\nProblem with instantiating the model in the controller\nWe need to create a service to supply the guestbook\n
This is a shared service\nFirst time it’s accessed it will create the object\nOnce created it returns the same object\nlazy loading\n
We then refactor code to make use of the service we defined\nReduce controller responsibility\n
\n
Set up a new route with the code to display the messages list\n
\n
The render function allows us to use another controller\nThis is excellent for apps using AJAX as calling this route will return the HTML block\n
\n
Caches are the reason the web is able to scale\nBrowser caches are good but server cache is fun!\nSymfony has a built in reverse proxy with support for ESI\nOr we can use varnish\n\n
Small markup language for edge level dynamic content assembly\n
Inserted into HTML or any text based content as creation\nInterpreted by an intermediary\nAllow for blocks of code to be independently cached from the main page\n
Because no presentation is complete without a picture of a cloud...\nSymfony components can handle Server Cache and Application as part of the same app\n
This is the version that caused Silex to render the result of the messages controller\nA small change required to use ESI\n
We simply update the markup so that the http output contains the ESI directive\n
Set the cache directory to store static HTML\nSet debug so we can see the headers\n
Set TTL on responses and Surrogate-Control header for proxy\nrun the http_cache rather than $app->run\nDEMO!\n