Dive into
-
Upload
marshall-bell -
Category
Documents
-
view
223 -
download
4
Transcript of Dive into
![Page 1: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/1.jpg)
Dive into
http://blog.nerdery.com/2013/06/symfony2-tech-talk/
![Page 2: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/2.jpg)
Maxwell VanderveldeWho 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 Development @ The Nerdery
![Page 3: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/3.jpg)
Chris JollyWho 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
![Page 4: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/4.jpg)
What's inside
● Focus on high level birds eye view of framework
● Reinforce low level architecture
● Provide prerequisite knowledge
Code
Architecture / Components
Orientation / Principles
![Page 5: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/5.jpg)
let's get started!
![Page 6: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/6.jpg)
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."
![Page 7: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/7.jpg)
![Page 8: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/8.jpg)
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
![Page 9: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/9.jpg)
What is Symfony2?The original Blog Post:
http://fabien.potencier.org/article/49/what-is-symfony2
How to Build a Framework from the Components:
http://fabien.potencier.org/article/50/create-your-own-framework-on-top-of-the-symfony2-components-part-1
“Getting Started” Documentation
http://symfony.com/doc/current/quick_tour/the_big_picture.html
![Page 10: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/10.jpg)
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
![Page 11: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/11.jpg)
Symfony2 Principles
Break the chain
● Composition, not inheritance
● Event and DI driven
![Page 12: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/12.jpg)
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
![Page 13: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/13.jpg)
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
![Page 14: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/14.jpg)
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
![Page 15: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/15.jpg)
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."
![Page 16: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/16.jpg)
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
![Page 17: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/17.jpg)
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.”
![Page 18: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/18.jpg)
Symfony2's Foundation
Request Response
![Page 19: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/19.jpg)
Symfony2's Foundation
Request Response
![Page 20: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/20.jpg)
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
● http://symfony.com/doc/current/components/http_foundation/introduction.html
● index.htmlhttps://github.com/symfony/HttpFoundation
![Page 21: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/21.jpg)
HttpFoundation\Request Object
● Container for a standard HTTP request
● Created from PHP globals
![Page 22: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/22.jpg)
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
![Page 23: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/23.jpg)
HttpFoundation Demo
Let’s go OO…
![Page 24: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/24.jpg)
Symfony2's Foundation
Request Response
![Page 25: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/25.jpg)
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
![Page 26: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/26.jpg)
Symfony2's Foundation
Request Response
HttpKernel
![Page 27: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/27.jpg)
EventDispatcher
● Symfony's internals are event driven
● Controlled by the EventDispatcher Component
![Page 28: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/28.jpg)
Symfony2's Foundation
Request Response
HttpKernelEventDispatche
r
![Page 29: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/29.jpg)
EventDispatcher
● 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
![Page 30: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/30.jpg)
Symfony2's Foundation
Request Response
HttpKernelEventDispatche
r
Listeners
![Page 31: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/31.jpg)
EventDispatcher
What does it mean to be event driven?
Event A
Event B
Event C
Listener
Listener
Listener
Listener
Listener
![Page 32: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/32.jpg)
The kernel.request event
● HttpKernel first calls the kernel.request event
● Listeners of the object are called
o These listeners may return a Response
![Page 33: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/33.jpg)
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
![Page 34: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/34.jpg)
Symfony2's Foundation
Request Response
HttpKernelEventDispatche
r
Listeners
DependencyInjection
![Page 35: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/35.jpg)
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
![Page 36: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/36.jpg)
Symfony2's Foundation
Request Response
HttpKernelEventDispatche
r
Listeners
DependencyInjection
Routing
![Page 37: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/37.jpg)
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
![Page 38: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/38.jpg)
Symfony2's Foundation
Request Response
HttpKernelEventDispatche
r
Controller
Listeners
DependencyInjection
Routing
![Page 39: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/39.jpg)
Controller
● Take a request, may return a response
● Nothing Special
o can be any PHP callable
![Page 40: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/40.jpg)
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
![Page 41: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/41.jpg)
Symfony2's Foundation
Request Response
HttpKernelEventDispatche
r
Controller
Listeners
DependencyInjection
Routing
![Page 42: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/42.jpg)
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
![Page 43: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/43.jpg)
EventDispatcher
● You can make your own listeners
● Can dispatch your own events
![Page 44: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/44.jpg)
Using Composer
What is Dependency Management?
● Your project needs things (Doctrine, Symfony, Twig)
o Those things need things
● Composer installs all the things!
![Page 45: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/45.jpg)
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
![Page 46: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/46.jpg)
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
![Page 47: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/47.jpg)
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
![Page 48: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/48.jpg)
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
![Page 49: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/49.jpg)
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
![Page 50: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/50.jpg)
The Bundle System
Symfony2 project code is broken into "bundles"
![Page 51: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/51.jpg)
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
![Page 52: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/52.jpg)
The Bundle System
● Bundles should be self contained
● Bundles can extend other bundles
![Page 53: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/53.jpg)
Symfony Configuration
● Configuration kept in yaml files
o Prod, Dev, & Test environments.
![Page 54: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/54.jpg)
Symfony Configuration
● Routing and others can be defined with annotationnamespace Acme\HelloBundle\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
class HelloController { /** * @Route("/hello/{name}") * @Method("GET") */ public function indexAction($name) { ... }}
![Page 55: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/55.jpg)
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
![Page 56: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/56.jpg)
Symfony Parameters
imports:
- { resource: parameters.yml }
database:
driver: MySQL
password: %db_password%
username: %db_username%Parameter placeholders
config.yml
![Page 57: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/57.jpg)
Symfony Parameters
parameters:
db_username: "admin"
db_password: "sadjiou34iu3$as"
Placeholder values
parameters.yml
![Page 58: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/58.jpg)
The Symfony2 View
● Layouts are created using Twig Templating engine
o May also use php, or another template engine
![Page 59: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/59.jpg)
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
![Page 60: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/60.jpg)
Templates are broken into a block structure
The Symfony2 View
layout.twig myView.twig
Header
Body Body
Header
![Page 61: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/61.jpg)
● Partial views can be included easily
● Twig outputs can be "filtered"
● Output Autoescaped by default
The Symfony2 View
![Page 62: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/62.jpg)
How do filters work?
The Symfony2 View
*Hello Damn World*
Markdown Filter
<b>Hello Damn World</b>
Expletive Filter
<b>Hello D*mn World</b>
Initial output
final output
![Page 63: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/63.jpg)
Javascript and CSS asset compilation!
● Can combine multiple CSS, JS into single output files
● Can Filter output!
The Symfony2 View
![Page 64: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/64.jpg)
Templating is slow!
● Templates cached in production!
The Symfony2 View
![Page 65: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/65.jpg)
Using Doctrine
● Symfony's default database ORM
● Follows strict standards for data entity management
![Page 66: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/66.jpg)
Using Doctrine
● Data models are Entity objects
o Plain objects
● Data structure defined as annotations on Entities
![Page 67: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/67.jpg)
Using Doctrine
● Entities are accessed through Doctrine Repositories
o May be customized for custom queries
![Page 68: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/68.jpg)
Using Doctrine
Entity
EntityRepository
CustomRepository
Database
![Page 69: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/69.jpg)
Using Doctrine
● Queries are optimized
o Allows for cached Queries
● Associations are lazy loaded
o Reduces overhead
![Page 70: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/70.jpg)
Application Security
![Page 71: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/71.jpg)
Security Component
Authentication
Authorization● Identify a user
o Formo Http Autho Custom?
● Resource accesso URLo Entityo Action/Method
![Page 72: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/72.jpg)
Security Component
Firewalls
● Does a user need to be authenticated?
● Based on URLs
![Page 73: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/73.jpg)
Security Component
Anonymous User
Firew
all
/foo
![Page 74: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/74.jpg)
Security Component
Anonymous User
Firew
all
/foo
/foo
Anonymous users are allowed!
![Page 75: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/75.jpg)
Security Component
Anonymous User
Firew
all
/foo
/foo
/login
No Anonymous users, try logging in!
![Page 76: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/76.jpg)
Security Component
Access Controls
● Can a user access a resource?
● Based on user
● Permissions distributed as "roles"
![Page 77: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/77.jpg)
Security Component
Anonymous User
Firew
all
/foo
/foo
/login
Acce
ss Con
trol
No Required Roles
/foo
![Page 78: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/78.jpg)
Security Component
Anonymous User
Firew
all
/foo
/foo
Acce
ss Con
trol User needs Admin Role!
/foo
/loginTry logging in!
![Page 79: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/79.jpg)
Security Component
User "Ryan"
Firew
all
/foo
/foo
Acce
ss Con
trol
/foo
User is logged in and has Admin role
![Page 80: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/80.jpg)
Security Component
User "Ryan"
Firew
all
/foo
/foo
Acce
ss Con
trol
User is missing Admin Role!
/foo
403
Already logged in
![Page 81: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/81.jpg)
Symfony Forms
Forms are a trouble point for most frameworks
● Separation of Concerns
● Decouple from view
● Decouple from entities
● Validation
![Page 82: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/82.jpg)
Symfony Forms
● Form Builder
o Add fields by name, type, etc.
● Form types
● Bind to gather data
![Page 83: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/83.jpg)
Symfony Forms
Validation
● Forms don't validate
● Check entity state after form populates it.
![Page 84: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/84.jpg)
Symfony Forms
How does Symfony2 organize forms?
● Each form is broken into many forms
● Forms are structured in a tree
![Page 85: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/85.jpg)
Symfony Forms
![Page 86: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/86.jpg)
Symfony Forms
![Page 87: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/87.jpg)
Symfony FormsForm
[New Employee]
Text[Name]
Number[salary]
BirthDate[birth date]
int[Year]
int[Month]
int[Day]
![Page 88: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/88.jpg)
Symfony Forms
How do decorators work?
● Leverage template block structure
● Broken into "widgets"
o Each widget gets a view block / partial
![Page 89: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/89.jpg)
Symfony Forms
● Benefits
o View logic detached from Form!
o Same form, different views
![Page 90: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/90.jpg)
Symfony Forms
What about the Data?
Got a complex form?
Want some more control over form data types?
![Page 91: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/91.jpg)
Symfony Forms
Form data is stored in three formats
o Model
o Normalized
o View
![Page 92: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/92.jpg)
Symfony Forms
Wait... what?
Model Normalized View
● Tied to Entity● Must associate
with property
● Tied to input type● Reliable for logic
● Tied to view● Stringly typed
![Page 93: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/93.jpg)
Symfony Forms
● Why all the formats?
o Decouples View from Model
o Decouples Domain logic from View & Model
![Page 94: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/94.jpg)
Symfony Forms
Form Transformers
![Page 95: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/95.jpg)
Symfony Forms
Form Transformers
● Used to convert one format to another
● Bijective transformation
![Page 96: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/96.jpg)
Symfony Forms
setData($data);
Model Normalized ViewTransform Transform
![Page 97: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/97.jpg)
Symfony Forms
bind($data);
Model Normalized View
Reverse Transform
Reverse Transform
![Page 98: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/98.jpg)
Symfony Console
Symfony Console
● Provides Useful commands
o Cache options
o Code Generation
o Asset Symlinking
o Custom Commands
![Page 99: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/99.jpg)
Symfony Console
Custom Commands
● Service oriented
o Get Database or anything the DI can provide
● Run your own command line
● Cron Tasks, Setup, Etc.
![Page 100: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/100.jpg)
Symfony Demo
The Framework in action…
![Page 101: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/101.jpg)
Questions / Details
(Psst... There's more slides)
![Page 102: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/102.jpg)
The Symfony2 Controller
use Symfony\Component\HttpFoundation\Response;
function helloAction(){ return new Response('Hello world!');}
● As a basic callable
![Page 103: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/103.jpg)
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
![Page 104: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/104.jpg)
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
![Page 105: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/105.jpg)
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
![Page 106: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/106.jpg)
The Symfony2 Router
● Routes defined as a Yaml config
● app/config/routing.yml
hello_world: path: /hello/{name} defaults:{ _controller: AcmeHelloBundle:Hello:index }
![Page 107: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/107.jpg)
The Symfony2 Router
● Routes can be defined with annotations
namespace Acme\HelloBundle\Controller;use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
class HelloController { /** * @Route("/hello/{name}") */ public function indexAction($name) { ... }}
![Page 108: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/108.jpg)
The Symfony2 Router
● Routes follow HTTP GET/POST/PUT/DELETE specnamespace Acme\HelloBundle\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
class HelloController { /** * @Route("/hello/{name}") * @Method("GET") */ public function indexAction($name) { ... }}
![Page 109: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/109.jpg)
The Symfony2 View
Twig basics
● {{ ... }} Prints a variable or the result of an expression
● {% ... %} Controls the logic of the template;
![Page 110: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/110.jpg)
The Symfony2 View
Properties, methods are accessed through dot notation{% for post in blogPosts %}<li> <ul> <a href="{{post.getLink()}}">{{post.title}}</a> </ul>
</li>{% endfor %}
![Page 111: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/111.jpg)
The Symfony2 View
Twig views are extendable
● Parent template
● Broken into Blocks
● Blocks are extended or overridden by views
![Page 112: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/112.jpg)
The Symfony2 View
A Base Template
<html> <head> <title> {% block title %}Example.com{% endblock %} </title> </head> <body> {% block body %}{% endblock %} </body></html>
![Page 113: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/113.jpg)
The Symfony2 View
Blocks can be extended, or overridden
{% extends "::base.html.twig" %}
{% block title %}
Welcome! {{ parent() }}
{% endblock %}
{% block body %}
Hello World!
{% endblock %}
![Page 114: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/114.jpg)
DependencyInjection
What is dependency injection?
● Inject needed objects into classes
o Constructor, setters, properties
● Used to decouple classes
● Use Common interfaces instead of concretes
![Page 115: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/115.jpg)
DependencyInjection
The problem:public class User { private $session; public function __construct() { $this->session = new Session('SESSION_ID'); } ....}
![Page 116: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/116.jpg)
DependencyInjection
Dependency Injection solutionpublic class User { private $session; public function __construct(SessionInterface $session) { $this->session = $session; } ....}
![Page 117: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/117.jpg)
DependencyInjection
Configuring Servicesparameters: api.class: Acme\HelloBundle\Api curl.class: Acme\HelloBundle\Wrapper\Curlservices: api: class: "%api.class%" arguments: [@curl, "%api.key%"] curl: class: "%curl.class%" arguments: []
![Page 118: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/118.jpg)
Doctrine Entities/** * @ORM\Table(name="widget") */class Widget{ /** * @var string $body * @ORM\Column(name="body", type="text", nullable=true) */ private $body; public function getBody() { ... } public function setBody($body) { ... }}
Table name
![Page 119: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/119.jpg)
Doctrine Entities/** * @ORM\Table(name="widget") */class Widget{ /** * @var string $body * @ORM\Column(name="body", type="text", nullable=true) */ private $body; public function getBody() { ... } public function setBody($body) { ... }}
Column name
![Page 120: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/120.jpg)
Doctrine Entities/** * @ORM\Table(name="widget") */class Widget{ /** * @var string $body * @ORM\Column(name="body", type="text", nullable=true) */ private $body;
public function getBody() { ... } public function setBody($body) { ... }}
Column type / attributes
![Page 121: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/121.jpg)
Using Doctrine
● Data is accessed through the EntityManager
o Each table is a "Repository"
![Page 122: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/122.jpg)
Doctrine Entitiesclass AcmeClass{ public function doSomething() { $repo = $this->doctrine->getRepository('AcmeBundle:Widgets'); $widget = $repo->findById(5); }}
![Page 123: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/123.jpg)
Doctrine Entitiesclass AcmeClass{ public function doSomething() { $repo = $this->doctrine->getRepository('AcmeBundle:Widgets'); $widget = $repo->findById(5); }} Bundle
name
![Page 124: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/124.jpg)
Doctrine Entitiesclass AcmeClass{ public function doSomething() { $repo = $this->doctrine->getRepository('AcmeBundle:Widgets'); $widget = $repo->findById(5); }} Entity name
![Page 125: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/125.jpg)
Using Doctrine
● Repositories can be explicitly defined for an entity
o (Similar to Zend's Db_Table object)
![Page 126: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/126.jpg)
Doctrine Entities/** * @ORM\Table(name="widget") */class Widget{ /** * @var string $body * @ORM\Column(name="body", type="text", nullable=true) */ private $body; public function getBody() { ... } public function setBody($body) { ... }}
![Page 127: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/127.jpg)
Doctrine Entities/** * @ORM\Table(name="widget") * @ORM\Entity( * repositoryClass="Acme\HelloBundle\Repository\WidgetRepository" * ) */class Widget{ /** * @var string $body * @ORM\Column(name="body", type="text", nullable=true) */ private $body; public function getBody() { ... } public function setBody($body) { ... }}
Repository
![Page 128: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/128.jpg)
Doctrine Repositoriesuse Doctrine\ORM\EntityRepository;
class WidgetRepository extends EntityRepository{ public function findWidgetsByName($string) { ... }}
![Page 129: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/129.jpg)
Using Doctrine
Doctrine provides two ways to access data
● Query Builder
● DQL (Doctrine Query Language)
![Page 130: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/130.jpg)
Using DQL
● DQL is structured like SQL
● Aimed at Entities, not at tables
![Page 131: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/131.jpg)
Using DQLclass 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; }}
![Page 132: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/132.jpg)
Using DQLclass 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
![Page 133: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/133.jpg)
Using DQLclass 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
![Page 134: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/134.jpg)
Using DQLclass 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
![Page 135: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/135.jpg)
Using DQLclass 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
![Page 136: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/136.jpg)
Using DQLclass 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
![Page 137: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/137.jpg)
Using DQLclass 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
![Page 138: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/138.jpg)
Using QueryBuilderclass 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
![Page 139: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/139.jpg)
Using QueryBuilderclass 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
![Page 140: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/140.jpg)
Using QueryBuilderclass 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
![Page 141: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/141.jpg)
Using QueryBuilderclass 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
![Page 142: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/142.jpg)
Using QueryBuilderclass 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
![Page 143: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/143.jpg)
Security Component
security: firewalls: secured_area: pattern: ^/ anonymous: ~ form_login: login_path: login check_path: login_check
![Page 144: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/144.jpg)
Security Component
security: firewalls: secured_area: pattern: ^/ anonymous: ~ form_login: login_path: login check_path: login_check
Secure everything
![Page 145: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/145.jpg)
Security Component
security: firewalls: secured_area: pattern: ^/foo anonymous: ~ form_login: login_path: login check_path: login_check
Secure things in:
/foo
![Page 146: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/146.jpg)
Security Component
security: firewalls: secured_area: pattern: ^/foo anonymous: ~ form_login: login_path: login check_path: login_check
Allow anonymous
![Page 147: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/147.jpg)
Security Component
security: firewalls: secured_area: pattern: ^/foo anonymous: ~ form_login: login_path: login check_path: login_check
login route
![Page 148: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/148.jpg)
Security Component
security: firewalls: secured_area: pattern: ^/foo anonymous: ~ form_login: login_path: login check_path: login_check
login check route
![Page 149: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/149.jpg)
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!
![Page 150: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/150.jpg)
Credits● Symfony Documentation
o Symfony.com/doc
● Fabien Potenciero What is symfonyo http://fabien.potencier.org/article/49/what-is-symfony2
● Symfony Live Presentationso Bernhard Schussek (Symfony Berlin / forms)
![Page 151: Dive into](https://reader036.fdocuments.us/reader036/viewer/2022062421/56649cca5503460f94993308/html5/thumbnails/151.jpg)
Credits
● Nerdery Symfony2 Fork
o github.com/TheNerdery/symfony-standard