- June 2008 • 1.2 - December 2008 • 1.3 - November 2009 • 1.4 - November 2009 • 2.0 - July 2011 • 2.1 - September 2012 • 2.2 - March 2013 • 2.3 - June 2013 • 2.4 - November 2013 • 2.5 - June 2014
development framework • Based on the Model-View-Controller Design Pattern • It enhances reusability, productivity and maintainability by providing solutions to common web application software problems • The beauty of Symfony2 comes from the fact that it is totally customizable. Use what you need and throw out what you don’t need!
Response classes, as well as other classes for handling sessions and file uploads; • Routing - Powerful and fast routing system that allows you to map a specific URI (e.g. /contact) to some information about how that request should be handled (e.g. execute the contactAction() method); • Form - A full-featured and flexible framework for creating forms and handling form submissions; • Validator - A system for creating rules about data and then validating whether or not user-submitted data follows those rules; • ClassLoader - An autoloading library that allows PHP classes to be used without needing to manually require the files containing those classes; • Templating - A toolkit for rendering templates, handling template inheritance (i.e. a template is decorated with a layout) and performing other common template tasks; • Security - A powerful library for handling all types of security inside an application; • Translation - A framework for translating strings in your application. Each and every one of these components is decoupled and can be used in any PHP project …
defaults: { _controller: AcmeDemoBundle:Main:contact } // src/Acme/DemoBundle/Controller/MainController.php namespace Acme\DemoBundle\Controller; use Symfony\Component\HttpFoundation\Response; class MainController { public function contactAction() { return new Response('<h1>Contact us!</h1>'); } }
each comma delimiter; • Add a single space around operators (==, &&, ...); • Add a comma after each array item in a multi-line array, even after the last one; • Add a blank line before return statements, unless the return is alone inside a statement-group • Declare class properties before methods; • Declare public methods first, then protected ones and finally private ones.
for variable, function and method names, arguments; • Prefix abstract classes with Abstract. • Suffix interfaces with Interface; • Suffix traits with Trait; • Suffix exceptions with Exception;
contains groups, separated by dots • The DI alias of the bundle is the first group (e.g. fos_user); • Use lowercase letters for service and parameter names; • A group name uses the underscore notation
structure and can host anything from classes to controllers and web resources. “ A bundle is kind of like a plugin in other software… Everything is a bundle in Symfony… A group of files, assets, PHP classes and methods, tests, etc….. - generating a New Bundle Skeleton: php app/console generate:bundle
to keep code consistent between all bundles Controller/ - contains the controllers of the bundle DependencyInjection/ - (this directory is not necessary) holds certain dependency injection extension classes Resource/config/ - contains configuration, including routing configurations Resource/views/ - holds templates organized by controller name Resource/public/ - contains web assets Tests/ - holds all tests fot the bundle
namespace Acme\UserBundle; use Symfony\Component\HttpKernel\Bundle\Bundle; class AcmeUserBundle extends Bundle { public function getParent() { return 'FOSUserBundle'; } }
simply a PHP object that manages the instantiation of services (i.e. objects). $ php app/console container:debug - Show all services and the class for each service # app/config/config.yml services: my_mailer: class: Acme\TestBundle\Mailer class TestController extends Controller { public function sendEmailAction() { $mailer = $this->get('my_mailer'); $mailer->send(‘[email protected]', ...); } }
create a simple Response with a 200 status code (the default) $response = new Response('Hello '.$name, Response::HTTP_OK); // create a JSON-response with a 200 status code $response = new Response(json_encode(array('name' => $name))); $response->headers->set('Content-Type', 'application/json'); • $request->isXmlHttpRequest(); // is it an Ajax request? • $response->setStatusCode(500); // creates a Response object whose content is the rended template $response = $this->render(‘DemoBundle:Demo:index.html.twig’);
$this->container->get('serializer')->serialize($entity, 'json'); return new Response($serializedEntity); • JMSSerializer - Library for (de-)serializing data of any complexity (supports XML, JSON, YAML) http://jmsyst.com/libs/serializer
sure you want to delete this file| ]1,10[ %count% files will be deleted|[10,Inf] Are you sure you want to delete all files', $value, array('%count%' => $value) );
use Symfony\Component\Validator\Constraint; class CustomConstraint extends Constraint { public $message = ‘error message'; } Creating the Validator namespace Acme\DemoBundle\Validator\Constraints; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; class CustomValidator extends ConstraintValidator { public function validate($value, Constraint $constraint) { … } }
in roles or (user and user.isSuperAdmin()) ' )) Retrieving the User Object • $user = $this->get('security.context')->getToken()->getUser(); • or $this->getUser(); Access Control in Templates • is_granted('ROLE_ADMIN')
syntax: • {{ ... }} - prints a variable • {% ... %} - a tag that controls the logic of the template (if, for etc) • {# ... #} – a comment • Caching {% for entry in blog_entries %} <h2>{{ entry.title }}</h2> <p>{{ entry.body }}</p> {% endfor %}
the contents of a parent block instead of completely overriding • {{ include() }} - include template in another template • {{ dump(var) }} - debug variables in a template Global variables: • app.security • app.user • app.request • app.request.get('foo') • app.request.request.get('foo') • app.session • app.environment • app.debug
public function add($a, $b) { return $a + $b; } } The code of the tested controller method: namespace Acme\DemoBundle\Test\Utility; use Acme\DemoBundle\Utility\Calculator; class CalculatorTest extends \PHPUnit_Framework_Test_Case { public function testAdd() { $calc = new Calculator(); $result = $calc->add(30, 12); $this->assertEquals(42, $result); } } The test code:
and the crawler objects to help you out • The client simulates a browser by allowing the developer to make requests • The crawler is returned from a client request and allows traversal of the content of the reply • e.g. traverse HTML tags, select nodes, links and forms $buttonCrawlerNode = $crawler->selectButton(‘submit’); $form = $buttonCrawlerNode->form(); $form = $buttomCrawlerNode->form(array( ‘name’ => ‘Symfony’, ‘my_form[subject]’ => ‘Symfony rocks!’, )); $client->submit($form);
{ _controller: AcmeHelloBundle:Hello:index } • Create the Controller: // src/Acme/HelloBundle/Controller/HelloController.php namespace Acme\HelloBundle\Controller; use Symfony\Component\HttpFoundation\Response; class HelloController { public function indexAction($name) { return new Response('<html><body>Hello '.$name.'!</body></html>'); } }
allows for a great deal of reusability by means of its components • Symfony2 integrates with external components to provide common services. Examples include: • Twig for templating • PHPUnit for testing • Doctrine for database integrating • and many others … • Symfony2 is a full stack web framework