Presentation is loading. Please wait.

Presentation is loading. Please wait.

Dive into

Similar presentations


Presentation on theme: "Dive into"— Presentation transcript:

1 Dive into

2 Maxwell Vandervelde Who the hell are you? Developer at The Nerdery ● Working with o PHP (Zend, Symfony2, Cake) o Android, Javascript o Tools! Git, Jenkins ● Kickstarting Internal Symfony2 The Nerdery

3 Chris Jolly Who the hell are you? CTO at Ontraq Europe ● Working with o PHP (Symfony2, Drupal, OXID) o Javascript o.Net (MVC, WebApi, Forms) ● We do o Integration, Interfaces & SSO

4 What's inside ● Focus on high level birds eye view of framework ● Reinforce low level architecture ● Provide prerequisite knowledge Code Architecture / Components Orientation / Principles

5 let's get started!

6 What is Symfony2? "First, Symfony2 is a reusable set of standalone, decoupled, and cohesive PHP components that solve common web development problems." "... Then, based on these components, Symfony2 is also a full-stack web framework."

7

8 What is Symfony2? Is Symfony2 an MVC Framework? "Symfony2 is never defined as being an MVC framework" "... I really don't care whether Symfony2 is MVC or not." "... The separation of concerns is all I care about.” That’s one way of describing it, but… In fact it’s very similar to MS.Net MVC + Entity Framework

9 What is Symfony2? The original Blog Post: How to Build a Framework from the Components: top-of-the-symfony2-components-part-1 “Getting Started” Documentation

10 Symfony2 Principles Separate Concerns ● Do one thing, ● Make it excellent. ● Stay out of the way. "Design programs to be connected to other programs." - Rule 3, Unix Philosophy

11 Symfony2 Principles Break the chain ● Composition, not inheritance ● Event and DI driven

12 Symfony2 Principles Be Explicit, not Implicit. ● Not 'on rails' ● Improves Flexibility ● Improves Readability Explicit is better than implicit. Simple is better than complex. Complex is better than complicated. - Zen of Python

13 Symfony2 Principles Follow Current Standards ● Uses PHP namespacing o Follows PSR-0 Autoloading standard ● Follows HTTP Specification "Namespaces are one honking great idea -- let's do more of those!" - Zen of Python

14 Symfony2 Principles Don't reinvent the wheel ● Use The right tool for the job o Uses Doctrine as an ORM o Uses Composer as Dependency management o Uses Twig as a View templating engine ● Uses a healthy ecosystem of 3rd-party bundles

15 Symfony2 Principles Decouple your code ● Replace the part, not the machine ● Make code as independent as possible ● Allow for interaction on common interfaces "The old adage "don't reinvent the wheel" doesn't apply when the wheel comes attached to a locomotive engine."

16 Symfony2 Principles Tooling Agnostic ● Each piece of the framework is replaceable o ORM o View templating engine Distrust all claims for “one true way” - Rule 16, Unix Philosophy

17 What is Symfony2? What framework model is Symfony2? “Symfony2 is an HTTP Request -> Response framework” Or… “the HttpFoundation Component does a great job handling the Request -> Response process.”

18 Symfony2's Foundation RequestResponse

19 Symfony2's Foundation RequestResponse

20 HttpFoundation Component ● HttpFoundation defines an object-oriented layer for the HTTP specification. ● It protects the programmer from the real world nastiness ● You can use it stand-alone if wanted ● dation/introduction.html dation/introduction.html ● index.htmlhttps://github.com/symfony/HttpFoundation index.htmlhttps://github.com/symfony/HttpFoundation

21 HttpFoundation\Request Object ● Container for a standard HTTP request ● Created from PHP globals

22 HttpFoundation\Response Object ● Holds all the information that needs to be sent back to the client from a given request. o Content, Status code, HTTP headers

23 HttpFoundation Demo Let’s go OO…

24 Symfony2's Foundation RequestResponse

25 HttpKernel Component ● First object created. The core of the web framework ● Takes in a Request, outputs a Response ● Binds the components together and controls the flow

26 Symfony2's Foundation RequestResponse HttpKernel

27 EventDispatcher ● Symfony's internals are event driven ● Controlled by the EventDispatcher Component

28 Symfony2's Foundation RequestResponse HttpKernel EventDispatcher

29 ● Implements the Observer pattern o Listeners are added to an event o Dispatcher is notified to dispatch the event o Each Listener is notified / called

30 Symfony2's Foundation RequestResponse HttpKernel EventDispatcher Listeners

31 EventDispatcher What does it mean to be event driven? Event A Event B Event C Listener

32 The kernel.request event ● HttpKernel first calls the kernel.request event ● Listeners of the object are called o These listeners may return a Response

33 DependencyInjection ● Allows you to standardize and centralize the way objects are constructed in your application. ● Connects / wires objects together o Defined in a yaml/xml config

34 Symfony2's Foundation RequestResponse HttpKernel EventDispatcher Listeners DependencyInjection

35 Routing ● Given a Request o Defined in Yaml or Annotations o Determines route based on URI and Request Type o Returns a controller to execute

36 Symfony2's Foundation RequestResponse HttpKernel EventDispatcher Listeners DependencyInjection Routing

37 The kernel.controller event ● HttpKernel calls the kernel.controller event BEFORE calling the controller ● Listeners of the object are called o These listeners may return a Response

38 Symfony2's Foundation RequestResponse HttpKernel EventDispatcher Controller Listeners DependencyInjection Routing

39 Controller ● Take a request, may return a response ● Nothing Special o can be any PHP callable

40 The kernel.view event ● What if the controller doesn't return a response? ● After the controller is called the kernel.view event is dispatched o These listeners may return a Response

41 Symfony2's Foundation RequestResponse HttpKernel EventDispatcher Controller Listeners DependencyInjection Routing

42 The kernel.exception event ● Called on uncaught exception ● Called on unhandled request ● the kernel.exception event is dispatched o Application's last chance to return a Response

43 EventDispatcher ● You can make your own listeners ● Can dispatch your own events

44 Using Composer What is Dependency Management? ● Your project needs things (Doctrine, Symfony, Twig) o Those things need things ● Composer installs all the things!

45 Using Composer Composer is not a package manager! ● Familiar with PEAR/PEAR2/PECL? o These install libraries globally o Runs into conflicts if you need two different versions ● Composer installs on per-project

46 Using Composer ● Composer installs dependencies in /vendors/ ● Provides an autoloader for classes ● Will "lock" each dependency down to a version o Each subsequent insall will use the same version

47 Using Composer ● Composer allows libraries to be excluded from Source Control o Keeps project lean o Abstracts wiring of dependencies o Easy to manage installs & updates: composer.phar install composer.phar update

48 Using Composer How does it work? ● Composer is a php executable (.phar file) o Can be included on an individual project basis o Can be installed on the system ● Dependencies are defined in a json file

49 Using Composer { "require": { "symfony/symfony": "2.1.*", "doctrine/orm": ">=2.2.3,<2.5-dev", }, } $ curl -sS https://getcomposer.org/installer | php --install-dir=bin $ composer require symfony/http-foundation

50 The Bundle System Symfony2 project code is broken into "bundles"

51 The Bundle System ● What is a bundle? ForumBundle AdminBundle BlogBundle WebBundle } ● Structured set of files that implement a single feature of your application. ● Every project is a bundle in Symfony2

52 The Bundle System ● Bundles should be self contained ● Bundles can extend other bundles

53 Symfony Configuration ● Configuration kept in yaml files o Prod, Dev, & Test environments.

54 Symfony Configuration ● Routing and others can be defined with annotation namespace Acme\HelloBundle\Controller; use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method; class HelloController { /** */ public function indexAction($name) {... } }

55 Symfony Parameters ● Environment specific configurations? o (Passwords, keys, etc.) o Kept in a parameters.yml file o Can be kept excluded from Version Control o Replaces placeholders in configuration files

56 Symfony Parameters imports: - { resource: parameters.yml } database: driver: MySQL password: %db_password% username: %db_username% Parameter placeholders config.yml

57 Symfony Parameters parameters: db_username: "admin" db_password: "sadjiou34iu3$as" Placeholder values parameters.yml

58 The Symfony2 View ● Layouts are created using Twig Templating engine o May also use php, or another template engine

59 The Symfony2 View ● Why use Twig? o Isn't PHP a templating language? ● View helpers are object oriented o Creates a lot of noise in the view ● Twig aims to clean the noise up ● It’s a lot like Smarty

60 Templates are broken into a block structure The Symfony2 View layout.twigmyView.twig Header Body Header

61 ● Partial views can be included easily ● Twig outputs can be "filtered" ● Output Autoescaped by default The Symfony2 View

62 How do filters work? The Symfony2 View *Hello Damn World* Markdown Filter Hello Damn World Expletive Filter Hello D*mn World Initial output final output

63 Javascript and CSS asset compilation! ● Can combine multiple CSS, JS into single output files ● Can Filter output! The Symfony2 View

64 Templating is slow! ● Templates cached in production! The Symfony2 View

65 Using Doctrine ● Symfony's default database ORM ● Follows strict standards for data entity management

66 Using Doctrine ● Data models are Entity objects o Plain objects ● Data structure defined as annotations on Entities

67 Using Doctrine ● Entities are accessed through Doctrine Repositories o May be customized for custom queries

68 Using Doctrine Entity Repository Custom Repository Database

69 Using Doctrine ● Queries are optimized o Allows for cached Queries ● Associations are lazy loaded o Reduces overhead

70 Application Security

71 Security Component AuthenticationAuthorization ● Identify a user o Form o Http Auth o Custom? ● Resource access o URL o Entity o Action/Method

72 Security Component Firewalls ● Does a user need to be authenticated? ● Based on URLs

73 Security Component Anonymous User Firewall /foo

74 Security Component Anonymous User Firewall /foo Anonymous users are allowed!

75 Security Component Anonymous User Firewall /foo /login No Anonymous users, try logging in!

76 Security Component Access Controls ● Can a user access a resource? ● Based on user ● Permissions distributed as "roles"

77 Security Component Anonymous User Firewall /foo /login Access Control No Required Roles /foo

78 Security Component Anonymous User Firewall /foo Access Control User needs Admin Role! /foo /login Try logging in!

79 Security Component User "Ryan" Firewall /foo Access Control /foo User is logged in and has Admin role

80 Security Component User "Ryan" Firewall /foo Access Control User is missing Admin Role! /foo 403 Already logged in

81 Symfony Forms Forms are a trouble point for most frameworks ● Separation of Concerns ● Decouple from view ● Decouple from entities ● Validation

82 Symfony Forms ● Form Builder o Add fields by name, type, etc. ● Form types ● Bind to gather data

83 Symfony Forms Validation ● Forms don't validate ● Check entity state after form populates it.

84 Symfony Forms How does Symfony2 organize forms? ● Each form is broken into many forms ● Forms are structured in a tree

85 Symfony Forms

86

87 Form [New Employee] Text [Name] Number [salary] BirthDate [birth date] int [Year] int [Month] int [Day]

88 Symfony Forms How do decorators work? ● Leverage template block structure ● Broken into "widgets" o Each widget gets a view block / partial

89 Symfony Forms ● Benefits o View logic detached from Form! o Same form, different views

90 Symfony Forms What about the Data? Got a complex form? Want some more control over form data types?

91 Symfony Forms Form data is stored in three formats o Model o Normalized o View

92 Symfony Forms Wait... what? ModelNormalizedView ●Tied to Entity ●Must associate with property ●Tied to input type ●Reliable for logic ●Tied to view ●Stringly typed

93 Symfony Forms ● Why all the formats? o Decouples View from Model o Decouples Domain logic from View & Model

94 Symfony Forms Form Transformers

95 Symfony Forms Form Transformers ● Used to convert one format to another ● Bijective transformation

96 Symfony Forms setData($data); ModelNormalizedView Transform

97 Symfony Forms bind($data); ModelNormalizedView Reverse Transform

98 Symfony Console ● Provides Useful commands o Cache options o Code Generation o Asset Symlinking o Custom Commands

99 Symfony Console Custom Commands ● Service oriented o Get Database or anything the DI can provide ● Run your own command line ● Cron Tasks, Setup, Etc.

100 Symfony Demo The Framework in action…

101 Questions / Details (Psst... There's more slides)

102 The Symfony2 Controller use Symfony\Component\HttpFoundation\Response; function helloAction() { return new Response('Hello world!'); } ● As a basic callable

103 The Symfony2 Controller namespace Acme\HelloBundle\Controller; use Symfony\Component\HttpFoundation\Response; class HelloController { public function indexAction() { return new Response('Hello World!'); } } ● As a class method

104 The Symfony2 Controller namespace Acme\HelloBundle\Controller; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Request; class HelloController { public function indexAction(Request $request) { if ($request->isXmlHttpRequest()) {... } } } ● Getting the Request object

105 The Symfony2 Controller namespace Acme\HelloBundle\Controller; use Symfony\Component\HttpFoundation\Response; class HelloController { public function indexAction($name) { return new Response('Hello '. $name. '!'); } } ● Parameters can be passed in from router

106 The Symfony2 Router ● Routes defined as a Yaml config ● app/config/routing.yml hello_world: path: /hello/{name} defaults:{ _controller: AcmeHelloBundle:Hello:index }

107 The Symfony2 Router ● Routes can be defined with annotations namespace Acme\HelloBundle\Controller; use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; class HelloController { /** */ public function indexAction($name) {... } }

108 The Symfony2 Router ● Routes follow HTTP GET/POST/PUT/DELETE spec namespace Acme\HelloBundle\Controller; use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method; class HelloController { /** */ public function indexAction($name) {... } }

109 The Symfony2 View Twig basics ● {{... }} Prints a variable or the result of an expression ● {%... %} Controls the logic of the template;

110 The Symfony2 View Properties, methods are accessed through dot notation {% for post in blogPosts %} {{post.title}} {% endfor %}

111 The Symfony2 View Twig views are extendable ● Parent template ● Broken into Blocks ● Blocks are extended or overridden by views

112 The Symfony2 View A Base Template {% block title %}Example.com{% endblock %} {% block body %}{% endblock %}

113 The Symfony2 View Blocks can be extended, or overridden {% extends "::base.html.twig" %} {% block title %} Welcome! {{ parent() }} {% endblock %} {% block body %} Hello World! {% endblock %}

114 DependencyInjection What is dependency injection? ● Inject needed objects into classes o Constructor, setters, properties ● Used to decouple classes ● Use Common interfaces instead of concretes

115 DependencyInjection The problem: public class User { private $session; public function __construct() { $this->session = new Session('SESSION_ID'); }.... }

116 DependencyInjection Dependency Injection solution public class User { private $session; public function __construct(SessionInterface $session) { $this->session = $session; }.... }

117 DependencyInjection Configuring Services parameters: api.class: Acme\HelloBundle\Api curl.class: Acme\HelloBundle\Wrapper\Curl services: api: class: "%api.class%" arguments: "%api.key%"] curl: class: "%curl.class%" arguments: []

118 Doctrine Entities /** */ class Widget { /** string $body type="text", nullable=true) */ private $body; public function getBody() {... } public function setBody($body) {... } } Table name

119 Doctrine Entities /** */ class Widget { /** string $body type="text", nullable=true) */ private $body; public function getBody() {... } public function setBody($body) {... } } Column name

120 Doctrine Entities /** */ class Widget { /** string $body type="text", nullable=true) */ private $body; public function getBody() {... } public function setBody($body) {... } } Column type / attributes

121 Using Doctrine ● Data is accessed through the EntityManager o Each table is a "Repository"

122 Doctrine Entities class AcmeClass { public function doSomething() { $repo = $this->doctrine->getRepository('AcmeBundle:Widgets'); $widget = $repo->findById(5); }

123 Doctrine Entities class AcmeClass { public function doSomething() { $repo = $this->doctrine->getRepository('AcmeBundle:Widgets'); $widget = $repo->findById(5); } Bundle name

124 Doctrine Entities class AcmeClass { public function doSomething() { $repo = $this->doctrine->getRepository('AcmeBundle:Widgets'); $widget = $repo->findById(5); } Entity name

125 Using Doctrine ● Repositories can be explicitly defined for an entity o (Similar to Zend's Db_Table object)

126 Doctrine Entities /** */ class Widget { /** string $body type="text", nullable=true) */ private $body; public function getBody() {... } public function setBody($body) {... } }

127 Doctrine Entities /** * repositoryClass="Acme\HelloBundle\Repository\WidgetRepository" * ) */ class Widget { /** string $body type="text", nullable=true) */ private $body; public function getBody() {... } public function setBody($body) {... } } Repository

128 Doctrine Repositories use Doctrine\ORM\EntityRepository; class WidgetRepository extends EntityRepository { public function findWidgetsByName($string) {... } }

129 Using Doctrine Doctrine provides two ways to access data ● Query Builder ● DQL (Doctrine Query Language)

130 Using DQL ● DQL is structured like SQL ● Aimed at Entities, not at tables

131 Using DQL class AcmeService { private $entityManager; public fucntion __construct(EntityManager $em) {...} public getWidgetsByTag($tag) { $query = $this->entityManager->createQuery( "SELECT w FROM AcmeBlogBundle:Widgets w JOIN w.tag t WHERE t.title = :tag ORDER BY w.created DESC" ); $query->setParameter('tag', $tag); $results = $query->getResults(); return $results; }

132 Using DQL class AcmeService { private $entityManager; public fucntion __construct(EntityManager $em) {...} public getWidgetsByTag($tag) { $query = $this->entityManager->createQuery( "SELECT w FROM AcmeBlogBundle:Widgets w JOIN w.tag t WHERE t.title = :tag ORDER BY w.created DESC" ); $query->setParameter('tag', $tag); $results = $query->getResults(); return $results; } Entity Manager

133 Using DQL class AcmeService { private $entityManager; public fucntion __construct(EntityManager $em) {...} public getWidgetsByTag($tag) { $query = $this->entityManager->createQuery( "SELECT w FROM AcmeBlogBundle:Widgets w JOIN w.tag t WHERE t.title = :tag ORDER BY w.created DESC" ); $query->setParameter('tag', $tag); $results = $query->getResults(); return $results; } Bundle Name

134 Using DQL class AcmeService { private $entityManager; public fucntion __construct(EntityManager $em) {...} public getWidgetsByTag($tag) { $query = $this->entityManager->createQuery( "SELECT w FROM AcmeBlogBundle:Widgets w JOIN w.tag t WHERE t.title = :tag ORDER BY w.created DESC" ); $query->setParameter('tag', $tag); $results = $query->getResults(); return $results; } Entity Class

135 Using DQL class AcmeService { private $entityManager; public fucntion __construct(EntityManager $em) {...} public getWidgetsByTag($tag) { $query = $this->entityManager->createQuery( "SELECT w FROM AcmeBlogBundle:Widgets w JOIN w.tag t WHERE t.title = :tag ORDER BY w.created DESC" ); $query->setParameter('tag', $tag); $results = $query->getResults(); return $results; } Placeholder

136 Using DQL class AcmeService { private $entityManager; public fucntion __construct(EntityManager $em) {...} public getWidgetsByTag($tag) { $query = $this->entityManager->createQuery( "SELECT w FROM AcmeBlogBundle:Widgets w JOIN w.tag t WHERE t.title = :tag ORDER BY w.created DESC" ); $query->setParameter('tag', $tag); $results = $query->getResults(); return $results; } Placeholder Value

137 Using DQL class AcmeService { private $entityManager; public fucntion __construct(EntityManager $em) {...} public getWidgetsByTag($tag) { $query = $this->entityManager->createQuery( "SELECT w FROM AcmeBlogBundle:Widgets w JOIN w.tag t WHERE t.title = :tag ORDER BY w.created DESC" ); $query->setParameter('tag', $tag); $results = $query->getResults(); return $results; } Result Collection

138 Using QueryBuilder class AcmeService { private $entityManager; public fucntion __construct(EntityManager $em) {...} public getWidgetsByTag($tag) { $qb = $this->entityManager->createQueryBuilder(); $qb->select('w') ->from('AcmeBlogBundle:Widgets', 'w') ->innerJoin('w.tags', 't') ->where('t.title = :tag') ->setParameter('tag', $tag) ->orderBy('w.created'); $results = $qb->getQuery()->getResults(); return $results; } Bundle name

139 Using QueryBuilder class AcmeService { private $entityManager; public fucntion __construct(EntityManager $em) {...} public getWidgetsByTag($tag) { $qb = $this->entityManager->createQueryBuilder(); $qb->select('w') ->from('AcmeBlogBundle:Widgets', 'w') ->innerJoin('w.tags', 't') ->where('t.title = :tag') ->setParameter('tag', $tag) ->orderBy('w.created'); $results = $qb->getQuery()->getResults(); return $results; } Entity name

140 Using QueryBuilder class AcmeService { private $entityManager; public fucntion __construct(EntityManager $em) {...} public getWidgetsByTag($tag) { $qb = $this->entityManager->createQueryBuilder(); $qb->select('w') ->from('AcmeBlogBundle:Widgets', 'w') ->innerJoin('w.tags', 't') ->where('t.title = :tag') ->setParameter('tag', $tag) ->orderBy('w.created'); $results = $qb->getQuery()->getResults(); return $results; } Placeholder

141 Using QueryBuilder class AcmeService { private $entityManager; public fucntion __construct(EntityManager $em) {...} public getWidgetsByTag($tag) { $qb = $this->entityManager->createQueryBuilder(); $qb->select('w') ->from('AcmeBlogBundle:Widgets', 'w') ->innerJoin('w.tags', 't') ->where('t.title = :tag') ->setParameter('tag', $tag) ->orderBy('w.created'); $results = $qb->getQuery()->getResults(); return $results; } Placeholder Value

142 Using QueryBuilder class AcmeService { private $entityManager; public fucntion __construct(EntityManager $em) {...} public getWidgetsByTag($tag) { $qb = $this->entityManager->createQueryBuilder(); $qb->select('w') ->from('AcmeBlogBundle:Widgets', 'w') ->innerJoin('w.tags', 't') ->where('t.title = :tag') ->setParameter('tag', $tag) ->orderBy('w.created'); $results = $qb->getQuery()->getResults(); return $results; } Result Collection

143 Security Component security: firewalls: secured_area: pattern: ^/ anonymous: ~ form_login: login_path: login check_path: login_check

144 Security Component security: firewalls: secured_area: pattern: ^/ anonymous: ~ form_login: login_path: login check_path: login_check Secure everything

145 Security Component security: firewalls: secured_area: pattern: ^/foo anonymous: ~ form_login: login_path: login check_path: login_check Secure things in: /foo

146 Security Component security: firewalls: secured_area: pattern: ^/foo anonymous: ~ form_login: login_path: login check_path: login_check Allow anonymous

147 Security Component security: firewalls: secured_area: pattern: ^/foo anonymous: ~ form_login: login_path: login check_path: login_check login route

148 Security Component security: firewalls: secured_area: pattern: ^/foo anonymous: ~ form_login: login_path: login check_path: login_check login check route

149 Security Component Oops! I accidentally the whole security, what should I do? ● Define Routes for login_path and check_path ● Make sure the login page isn't behind a secured firewall or access control ● Make sure check path is behind a firewall ● Multiple firewalls do not share security contexts!

150 Credits ● Symfony Documentation o Symfony.com/doc ● Fabien Potencier o What is symfony o ● Symfony Live Presentations o Bernhard Schussek (Symfony Berlin / forms)

151 Credits ● Nerdery Symfony2 Fork o github.com /TheNerdery/symfony-standard


Download ppt "Dive into"

Similar presentations


Ads by Google