Using Multi-Byte Character Sets in PHP (Unicode, UTF-8, etc)
Changing Mailman Python Scripts for Virtual Host Support
A Simple ISAPI Filter for Authentication on IIS
Nice n' Easy JQuery Image Rotator
Symfony 2 Crash Course
Scrollable Tables with Floating Header using CSS

Symfony 2 Crash Course

Saturday, 24 October 15, 10:47 am
Symfony is a collection of over twenty libraries, called the Symfony Components, that can be used by themselves in any PHP project. The idea of these classes is to perform many of the common tasks found in web projects, such as encapsulating the request and response, creating forms and handling form submissions, handling security and templating. Various third-party libraries are incorporated into the Symfony framework along with the Symfony Components. The Symfony framework provides classes that tie all these libraries together, and allows configuration in a consistent way.

Symfony is a PHP Open Source MVC Framework heavily inspired by other web frameworks such as Ruby on Rails, Django, and Spring. It was originally developed by the French web development company SensioLabs under the name Sensio Framework and was released n 2007 as an Open Source project under an MIT licence. It was at this point that the name was changed to Symfony. Version 2 came out in July 2011 and Version 3 is due for release in November 2015.

Symfony 3 isn't introducing any changes to the low-level architecture of the framework. Technically speaking, Symfony 3 includes no new features compared to Symfony 2.8, which will be released at the same time. The main change introduced by Symfony 3 is that any feature, option or behavior marked as deprecated in version 2.8 will be removed. See here for information about how to make your Symfony 2 projects ready for version 3. Symfony 3 will also require PHP 5.5+ as opposed to 5.3+.

Architecture

All requests to a Symfony application are handled by a single Front Controller, which uses routing rules to determine which class, and method on that class, should generate the response. The following image, taken from the Symfony documentation, shows how this would work for 3 different requests:


Installation

When Symfony 2 was released, the installation process worked by reading a text file which specified all the components needed by the web app, along with the required versions where necessary. This install process eventually became the Composer project, and Composer has been the recommended way for installing Symfony up until January 2015. Since then, the recommended way is to use the Symfony installer, a PHAR archive that when executed, downloads the framework and creates a skeleton for your new web project. Symfony projects created with the installer still have a composer.json file and the vendor directory, as Composer is still the way to manage your project's dependencies, including Symfony itself. The installer simply makes setting up your projects quicker and cleaner.

Get the installer PHAR from symfony.com/installer, save it somewhere on your path and make it executable:
sudo wget http://symfony.com/installer -O /usr/local/bin/symfony sudo chmod +x /usr/local/bin/symfony
Make sure the line extension=phar.so is uncommented in your php.ini, and then from the directory where you want to create your Symfony project, run the installer like so:
symfony new reddit
It will then download the latest stable Symfony release, and create a new Symfony project in the folder called reddit (yes that's right, in this crash course we're going to create a reddit replacement!). The web subfolder of this new directory is the web root of your new project. If you open that location in your web browser, you should be greeted by the Symfony welcome page:



The installer creates the following five directories inside the project folder:
  • app - this contains configuration files, the cache, logs and template files
  • bin - some command line tools
  • src - your source code for the site, including the controllers and unit tests
  • vendor - the directory where Composer downloads your project's dependencies
  • web - your project's web root, so this is where you'll need to put CSS and JS files

Making a 'Web Page'

In MVC, what we normally consider a single web page doesn't correspond to a single PHP file on the server. Instead, your application will contain multiple controllers which construct the appropriate response for a given request. Generally, a controller will be implemented as a single method on a class, also called an 'action' method. The act of mapping a request to a particular controller is called routing. For instance, you could choose to map the first part of the URL to the controller class, and the second to the action method, so that /profile/edit would fire the edit action on the profile controller, while /profile/view would fire the view action on the same controller.

Let's create a controller class in the src/AppBundle/Controller directory and define two action methods called editAction() and viewAction():
<?php   namespace AppBundle\Controller;   use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; use Symfony\Bundle\FrameworkBundle\Controller\Controller; use Symfony\Component\HttpFoundation\Request;   class ProfileController extends Controller { /** * @Route("/profile", name="profile") */ public function viewAction() { // 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').'/..'), )); }   /** * @Route("/profile/edit", name="profileEdit") */ public function editAction() { // 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').'/..'), )); } }
You can define your routing rules in a configuration file written in either YAML, XML or PHP or you can specify the route for an action method with a @Route annotation as in the code above. The first part of the @Route annotation specifies the URL pattern that will trigger that particular action method. As well as the URL, each @Route is given a name, which is useful for creating URLs for links and redirects as we'll see later.

The ProfileController class extends \Symfony\Bundle\FrameworkBundle\Controller\Controller (note the use statements at the top of the file). Extending this class isn't actually necessary, but it does give us access to an assortment of useful helper methods from the parent class. One such method is the render() method used by both our action methods. Each action method must return an Symfony\Component\HttpFoundation\Response object, and in this case we're using the render() method to generate it for us based on the specified Twig template.

We can't go to these controllers directly in our browser just yet, as the necessary config and cache files don't exist. Instead, we need to access them through the app_dev.php file like so: http://localhost/reddit/web/app_dev.php/profile or http://localhost/reddit/web/app_dev.php/profile/edit. Right now, the content of each action method just uses the same code as the default controller generated by the installer, so visiting either will display the same Welcome message we saw earlier.

Passing Parameters to a Controller

Often, we want to pass a parameter from the route to the view. As an example, we'll create a controller for subreddits:
<?php   namespace AppBundle\Controller;   use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; use Symfony\Bundle\FrameworkBundle\Controller\Controller; use Symfony\Component\HttpFoundation\Request;   class SubredditController extends Controller { /** * @Route("/r/{subreddit}", name="subreddit") */ public function viewAction($subreddit) { // render our view, passing in view parameters as an array return $this->render('subreddit/view.html.twig', array( 'base_dir' => realpath($this->container->getParameter('kernel.root_dir').'/..'), 'name' => $subreddit )); } }
Notice how the @Route annotation contains a parameter inside curly brackets: {subreddit}. The action method must have a corresponding PHP parameter with the exact same name. If you visit this page using a URL such as http://localhost/reddit/web/app_dev.php/r/noobs, you should get the Symfony error page complaining it's Unable to find template "subreddit/view.html.twig". So fix this by creating a file with this name in app/Resources/views/subreddit/ with the following content:
{% extends 'base.html.twig' %}   {% block body %} <div id="wrapper"> <div id="container"> <h1>{{ name }}</h1> </div> </div> {% endblock %}   {% block title %}{{ name }}{% endblock %}
Reload the page, and you should see the subreddit name that you specified in the URL.

Excellent! We've pretty much got a working reddit-type website already. Next, we look at how to persist items in a relational database using Doctrine.

Please enter your comment in the box below. Comments will be moderated before going live. Thanks for your feedback!

Cancel Post

/xkcd/ Physics vs. Magic