Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Symfony Introduction

Symfony Introduction

Symfony Introduction

Razvan Moldovan

July 25, 2014
Tweet

More Decks by Razvan Moldovan

Other Decks in Technology

Transcript

  1. the one true framework ?! Symfony is the most popular

    PHP framework ?! Symfony is the best PHP framework ?!
  2. Ex. : Laravel - Components used by this project •

    BrowserKit • Console • CssSelector • Debug • DomCrawler • EventDispatcher • Filesystem • Finder • HttpFoundation • HttpKernel • Process • PropertyAccess • Routing • Translation
  3. History of Symfony • 1.0 - January 2007 • 1.1

    - 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
  4. What is Symfony “ Symfony is a set of PHP

    Components, a Web Application framework, a Philosophy, and a Community — all working together in harmony. “
  5. Symfony2 • Symfony2 is an open source PHP-based web application

    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!
  6. The Symfony2 Components • HttpFoundation - Contains the Request and

    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 …
  7. “Create your own framework... on top of the Symfony2 Components”

    http://fabien.potencier.org/article/50/create-your-own-framework-on-top-of-the-symfony2-components-part-1
  8. A Symfony Request in Action # app/config/routing.yml contact: path: /contact

    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>'); } }
  9. A Symfony Request in Action # app/config/routing.yml hello: path: /hello/{firstName}/{lastName}

    defaults: { _controller: AcmeHelloBundle:Hello:index, color: green } public function indexAction($firstName, $lastName, $color) { // ... }
  10. HTTP method of a request test_show: path: /test/{var} defaults: {

    _controller: DemoBundle:Test:show } methods: [GET] test_update: path: /test/{var} defaults: { _controller: DemoBundle:Test:update } methods: [PUT] test_delete: path: / test/{var} defaults: { _controller: DemoBundle:Test:delete } methods: [DELETE] test_post: path: /test/ defaults: { _controller: DemoBundle:Test:show } methods: [POST]
  11. Coding Standards - Structure • Add a single space after

    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.
  12. Coding Standards - Naming Conventions • Use camelCase, not underscores,

    for variable, function and method names, arguments; • Prefix abstract classes with Abstract. • Suffix interfaces with Interface; • Suffix traits with Trait; • Suffix exceptions with Exception;
  13. Coding Standards - Service Naming Conventions • A service name

    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
  14. Directory Structure • app: the application configuration • src: the

    project's PHP code • vendor: the third-party dependencies • web: the web root directory
  15. Bundles “A bundle is a directory that has a well-defined

    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
  16. Bundle directory structure • Bundle system follows set of conventions

    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
  17. Bundle Inheritance to Override parts of a Bundle // src/Acme/UserBundle/AcmeUserBundle.php

    namespace Acme\UserBundle; use Symfony\Component\HttpKernel\Bundle\Bundle; class AcmeUserBundle extends Bundle { public function getParent() { return 'FOSUserBundle'; } }
  18. Some Useful bundles • GearmanBundle - https://github.com/mrazvan92/GearmanBundle • SonataAdminBundle -

    https://github.com/sonataproject/SonataAdminBundle • CMFBundle - https://github.com/symfony-cmf/standard-edition • HWIOAuthBundle - https://github.com/hwi/HWIOAuthBundle • MonologBundle - https://github.com/symfony/MonologBundle • SphinxsearchBundle - https://github.com/timewasted/Search- SphinxsearchBundle • FOSRestBundleByExample - https://github.com/sdiaz/FOSRestBundleByExample • MemcacheBundle - https://github.com/tarjei/MemcacheBundle • RedisBundle - https://github.com/da-wen/PhpRedisBundle • SolrBundle - https://github.com/tapronto/SolrBundle
  19. Service Container A Service Container (or dependency injection container) is

    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]', ...); } }
  20. Create a Console Command class ExampleCommand extends ContainerAwareCommand { protected

    function configure() { //name, description, argument } protected function execute(InputInterface $input, OutputInterface $output) { //$this->getContainer() … $name = $input->getArgument('name'); $output->writeln($name); } } Run: php app/console bundle:test Razvan
  21. Controller • A controller is a PHP function you create

    that takes information from the HTTP request and constructs and returns an HTTP response
  22. Controller - Request & Response • $request->query->get('foo'); // GET •

    $request->request->get('bar'); // POST • $request->server->get('HTTP_HOST'); //server variables • $request->getPathInfo(); //gets the URI.
  23. Controller - Session & Cookie • $session = $this->get('session'); •

    $session->get('foo'); • $session->set('foo','bar'); • $request->cookies->get('PHPSESSID'); //cookies
  24. Controller - Flash messages • $this->get('session')->getFlashBag()->add('notice','message'); • {% for flashMessage

    in app.session.flashbag.get('notice') %} <div class="flash notice">{{ flashMessage }}</div> {% endfor %}
  25. Controller - Simple JSON response in controller use Symfony\Component\HttpFoundation\Response; //

    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’);
  26. Controller - Simple JSON response in controller (JMS) $serializedEntity =

    $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
  27. Translations • translations can be created in several different formats:

    xliff, php, yml $translated = $this->get('translator')->trans('Symfony2 is great'); In controller In twig {% trans %}Symfony2 is great{% endtrans %}
  28. Translations echo $translator->transChoice( '[-Inf, 0]There is nothing to delete|{1}Are you

    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) );
  29. Validation - The Basics of Validation use Symfony\Component\Validator\Constraints as Assert;

    class Entity { /** * @Assert\NotBlank() * @Assert\MaxLenght (100) */ protected $name; } $entity= new Entity(); $validator = $this->get('validator'); $errors = $validator->validate($entity); var_dump($errors); {% for error in errors %} {{ error.message }} {% endfor %}
  30. Validation - Custom Validation Constraint Creating Constraint class namespace Acme\DemoBundle\Validator\Constraints;

    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) { … } }
  31. Forms - Simple Form use Symfony\Component\Validator\Constraints as Assert; class Demo

    { /** * @Assert\NotBlank() */ protected $name; //setter and getter }
  32. Forms - Simple Form class DemoType extends AbstractType { public

    function buildForm(FormBuilderInterface $builder, array $options) { $builder->add('name'); } public function setDefaultOptions(OptionsResolverInterface $resolver) { $resolver->setDefaults(array( 'data_class' => ‘DemoBundle\Entity\Demo', // 'cascade_validation' => true, 'csrf_protection' => true, )); } public function getName() { return ‘demo'; } }
  33. Forms - Adding an Event Listener to a Form Class

    class DemoType extends AbstractType { public function buildForm(FormBuilderInterface $builder, array $options) { $builder->add(‘name'); $builder->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) { $data = $event->getData(); $form = $event->getForm(); // ... $form->add(‘surname’); }); } }
  34. Forms - Adding an Event Listener to a Form Class

    class DemoType extends AbstractType { public function buildForm(FormBuilderInterface $builder, array $options) { $builder->add(‘name'); $builder->addEventSubscriber(new AddNameFieldSubscriber()); } }
  35. Forms - Adding an Event Listener to a Form Class

    class AddNameFieldSubscriber implements EventSubscriberInterface { public static function getSubscribedEvents() { return array(FormEvents::PRE_SET_DATA => 'preSetData'); } public function preSetData(FormEvent $event) { $data = $event->getData(); $form = $event->getForm(); //…. } }
  36. Security • Security is a two-step process whose goal is

    to prevent a user from accessing a resource that they should not have access to.
  37. Security Check role • $this->get('security.context')->isGranted('ROLE_ADMIN') • $this->get('security.context')->isGranted(new Expression( ‘ "ROLE_ADMIN"

    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')
  38. Template • PHP template or Twig • Setup template engine:

    yml: templating:engines: ['twig', 'php'] annotation: @Template(engine="php")
  39. Template - Twig • Twig defines three types of special

    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 %}
  40. Template - Twig - Template Inheritance {# app/Resources/views/base.html.twig #} <!DOCTYPE

    html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title> {% block title %}Test Application{% endblock %} </title> </head> <body> <div id="sidebar"> {% block sidebar %} <ul> <li><a href="/">Home</a></li> <li><a href="/blog">Blog</a></li> </ul> {% endblock %} </div> <div id="content"> {% block body %}{% endblock %} </div> </body> </html>
  41. Template - Twig - Template Inheritance {# src/Acme/BlogBundle/Resources/views/Blog/index.html.twig #} {%

    extends '::base.html.twig' %} {% block title %}My cool blog posts{% endblock %} {% block body %} {% for entry in blog_entries %} <h2>{{ entry.title }}</h2> <p>{{ entry.body }}</p> {% endfor %} {% endblock %}
  42. Template – Twig • {{ parent() }} - add to

    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
  43. Template – Twig - Linking to Pages _welcome: path: /

    defaults: { _controller: AcmeDemoBundle:Welcome:index } <a href="{{ path('_welcome') }}">Home</a> article_show: path: /article/{slug} defaults: { _controller: AcmeArticleBundle:Article:show } <a href="{{ path('article_show', {'slug': slug}) }}"> Link </a>
  44. Template – Twig - Linking to Assets <img src="{{ asset('images/logo.png')

    }}" alt="Symfony!" /> <link href="{{ asset('css/blog.css') }}" rel="stylesheet" type="text/css" />
  45. Twig Extension // src/Acme/DemoBundle/Twig/AcmeExtension.php namespace Acme\DemoBundle\Twig; class AcmeExtension extends \Twig_Extension

    { public function getFilters() { return array(new \Twig_SimpleFilter('price', array($this, 'priceFilter')),); } public function priceFilter($number, $decimals = 0, $decPoint = '.', $thousandsSep = ',') { $price = number_format($number, $decimals, $decPoint, $thousandsSep); $price = '$'.$price; return $price; } public function getName() { return 'acme_extension'; } }
  46. Twig Extension Register an Extension as a Service: # src/Acme/DemoBundle/Resources/config/services.yml

    services: acme.twig.acme_extension: class: Acme\DemoBundle\Twig\AcmeExtension tags:- { name: twig.extension } Using the custom Extension: {{ '5500'|price }} {{ '5500.25155'|price(4, ',', '') }}
  47. Testing Component • Symfony2 integrates with the PHPUnit testing framework

    • All tests must be placed in the Tests/ directory of your project • The test directory will replicate the structure of your bundle’s directory
  48. Testing Component – Unit test namespace Acme\DemoBundle\Utility; class Calculator {

    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:
  49. Testing Component – Functional test • PHPUnit provides the client

    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);
  50. “Hello world!” in Symfony2 • http://localhost/app_dev.php/hello/Arobs • Create the Bundle:

    $ php app/console generate:bundle --namespace=Acme/HelloBundle --format=yml // app/AppKernel.php public function registerBundles() { $bundles = array( ..., new Acme\HelloBundle\AcmeHelloBundle(), ); // ... return $bundles; } • Create the Route: # app/config/routing.yml acme_hello: resource: "@AcmeHelloBundle/Resources/config/routing.yml" prefix: /
  51. “Hello world!” in Symfony2 # src/Acme/HelloBundle/Resources/config/routing.yml hello: path: /hello/{name} defaults:

    { _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>'); } }
  52. Conclusion • Though Symfony2 is an MVC based framework, it

    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