![Page 1: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/1.jpg)
![Page 2: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/2.jpg)
![Page 3: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/3.jpg)
The format – Talks then Hacking
Follow along with the sandbox
![Page 4: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/4.jpg)
What is Symfony2?
![Page 5: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/5.jpg)
A web framework
![Page 6: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/6.jpg)
A web framework is a software that providesgeneric components that ease application development
and team work.
![Page 7: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/7.jpg)
A framework helps developers create flexible and extensible applications, write quality and maintainable code.
![Page 8: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/8.jpg)
Symfony2 is built on top of PHP 5.3
It especially uses the new namespace system
![Page 9: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/9.jpg)
![Page 10: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/10.jpg)
git clone https://github.com/jmikola/top-shelf-php.git
![Page 11: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/11.jpg)
IDEs Integration
Eclipse: https://github.com/pulse00/Twig-Eclipse-Plugin
Netbeans: https://github.com/blogsh/Twig-netbeans
PHPStorm: As of 2.1
VIM: http://jinja.pocoo.org/2/documentation/integration
TextMate: https://github.com/Anomareh/PHP-Twig.tmbundle
![Page 12: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/12.jpg)
Install the standard distribution
![Page 13: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/13.jpg)
php app/check.php
Requirements checks
![Page 14: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/14.jpg)
![Page 15: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/15.jpg)
![Page 16: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/16.jpg)
# web/app_dev.phprequire_once __DIR__.'/../app/AppKernel.php';
use Symfony\Component\HttpFoundation\Request;
$kernel = new AppKernel('dev', true);$kernel->handle(Request::createFromGlobals())->send();
The front controller is the single entry point of the application
The front controller
![Page 17: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/17.jpg)
http://www.domain.tld/web/app_dev.php/
http://www.domain.tld/web/app_dev.php/hello/Fabien
http://www.domain.tld/web/app_dev.php/hello/Toto
The front controller
Every resource the user wants to access is available from the front controller
![Page 18: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/18.jpg)
http://www.domain.tld/
http://www.domain.tld/hello/Fabien
http://www.domain.tld/hello/Toto
If the virtual host is correctly configured to make the web/ folder as the web root directory, URI becomes as follow.
The front controller
![Page 19: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/19.jpg)
<VirtualHost *:80> ServerName www.domain.tld DocumentRoot "/path/to/sandbox/web" DirectoryIndex app.php <Directory "/path/to/sandbox/web"> AllowOverride All Allow from All </Directory></VirtualHost>
Production configuration sample for Apache
In production environment, make sure your Apache is configured to make the web/ folder as the web root directory of your application.
![Page 20: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/20.jpg)
# web/.htaccess<IfModule mod_rewrite.c>
RewriteEngine On RewriteCond %{REQUEST_FILENAME} !-f RewriteRule ^(.*)$ app.php [QSA,L]
</IfModule>
Production configuration sample for Apache
The web/.htaccess file redirects every request on the front controller.
![Page 21: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/21.jpg)
![Page 22: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/22.jpg)
๏ app/ is the application folder
๏ src/ is the libraries folder
๏ web/ is the general public folder
The app/ folder contains the configuration and generated files
The src/ folder contains the PHP code
The web/ folder contains front controllers and web assets (images, Javascripts, stylesheets, ...)
.|-- LICENSE|-- README|-- app/| |-- AppCache.php| |-- AppKernel.php| |-- cache/| |-- config/| |-- console| |-- logs/| |-- autoload.php| |-- check.php| `-- phpunit.xml.dist|-- bin/|-- src/| `-- Acme/|-- vendor/`-- web/ |-- config.php |-- app.php `-- app_dev.php
Architecture
![Page 23: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/23.jpg)
web/should be the web root directory
app/cache/ and app/logs/
must be writable by the web server
Architecture
![Page 24: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/24.jpg)
An Application is a directorycontaining the configurationfor a given set of Bundles
Architecture
![Page 25: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/25.jpg)
A Bundle is a structured set of files(PHP files, stylesheets, JavaScripts, images, ...)
that implements a single feature (a blog, a forum, ...)and which can be easily shared with other developers.
Architecture
![Page 26: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/26.jpg)
Accessing a Resource
![Page 27: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/27.jpg)
Simply browse the following URIhttp://…/…/app_dev.php/hello/Fabien
Virtual path to the resource the user wants to access
![Page 28: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/28.jpg)
Symfony2 provides a routing mechanism that converts a typical URI into a web response
![Page 29: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/29.jpg)
๏To link URIs to the application internal actions
๏To improve SEO optimizations and bookmarks
๏To be able to create or change URIs with ease
๏To avoid to show sensible information
๏To give meaningful URIs to the end user
Architecture
![Page 30: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/30.jpg)
๏They show sensible information
๏They mention variable names and values
๏They are not meaningful and optimized for SEO engines
http://www.domain.com/blog.php?action=show&article_id=123
Default URLs have some problems…
![Page 31: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/31.jpg)
๏Clean and smart URIs to give meaningful information
๏No sensible information or variables
๏Easy URIs configuration in YAML, PHP or XML
http://www.domain.com/blog/2010/09/15/symfony2-rocks
URL rewriting is better !
![Page 32: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/32.jpg)
The Router is responsible to match
a Pattern with a corresponding Controller.
![Page 33: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/33.jpg)
The Router is responsible to match
a Pattern with a corresponding Controller.
![Page 34: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/34.jpg)
A Controller is responsible to process a
Request and to return a Response
![Page 35: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/35.jpg)
How does the routing work?
![Page 36: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/36.jpg)
![Page 37: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/37.jpg)
![Page 38: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/38.jpg)
![Page 39: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/39.jpg)
How to process a request?
![Page 40: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/40.jpg)
The controller is responsible to convert a request into a response
Generating a response
namespace Sensio\HelloBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;use Symfony\Component\HttpFoundation\Response;use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
class HelloController extends Controller{ /** @Route("/hello/{name}", name="greet") */ public function indexAction($name) { return new Response(sprintf('Hello %s!', $name)); }}
![Page 41: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/41.jpg)
namespace Sensio\HelloBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
class HelloController extends Controller{ /** @Route("/hello/{name}", name="greet") */ public function indexAction($name) { return $this->render('SensioHelloBundle:Hello:index.html.twig', array( 'name' => $name )); }}
Generating a response
Unlike previous examples, the render() method decouples the application logic of the controller from the rendering of the view layer.
![Page 42: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/42.jpg)
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
class HelloController extends Controller{ /** * @Route("/hello/{name}", name="greet") * @Template("SensioHelloBundle:Hello:index.html.twig") */ public function indexAction($name) { return array('name' => $name); }}
Variables will be sent to the template thanks to the array
Generating a response
The rendered template can also be mapped with a special annotation coming from the SensioFrameworkExtraBundle bundle.
![Page 43: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/43.jpg)
Variables will be sent to the template thanks to the array
Generating a response
If the logical path to the template follows the following naming convention (BundleName:ControllerName:actionName.html.twig), the logical path can be omitted from the @Template annotation.
class HelloController extends Controller{ /** * @Route("/hello/{name}", name="greet") * @Template() */ public function indexAction($name) { return array('name' => $name); }}
The route name to generate links or uris.
![Page 44: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/44.jpg)
![Page 45: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/45.jpg)
Diving into the view layer
![Page 46: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/46.jpg)
Twig fundamentals
![Page 47: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/47.jpg)
What is Twig?
Twig is a modern template engine for PHP
Fast: Twig compiles templates down to plain optimized PHP code. The overhead compared to regular PHP code was reduced to the very minimum.
Secure: Twig has a sandbox mode to evaluate untrusted template code. This allows Twig to be used as a template language for applications where users may modify the template design.
Flexible: Twig is powered by a fexible lexer and parser. This allows the developer to define its own custom tags and filters, and create its own DSL.
![Page 48: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/48.jpg)
Twig has several tags (markers) to indicate the parser how to process the code. Every marker starts by an opening brace character – {– and ends with a closing brace – } .
Tag Meaning
{{ a_variable }} Outputs an escaped string
{# Some commented code #} Comments a piece of code
{% if glass is empty %} Evaluates an expression (block, loop, condition…)
Twig syntax
![Page 49: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/49.jpg)
Simply use the double curly braces statement, {{ }}, which is equivalent to the echo / print statement in PHP.
{{ }} always outputs something!
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"><html lang="en"> <head> <title>My Webpage</title> </head> <body> <p> Hello, my name is {{ name }}! </p> </body></html>
Printing variables
![Page 50: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/50.jpg)
Twig accepts the following syntax to deal with both objects and arrays
# foo is an array|object and bar a valid index|property|method{{ foo.bar }}
# foo is an array and 0 a valid index# foo is an object that implements ArrayAccess interface{{ foo.0 }}
# foo is an array and bar a valid index.# foo is an object that implements ArrayAccess interface{{ foo['bar'] }}
# bar is a variable containing the index in the foo array{{ foo[bar] }}
Dealing with objects and arrays
![Page 51: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/51.jpg)
When using foo.bar
Check if foo is an array and bar a valid element;
If not, and if foo is an object, check that bar is a valid property;
If not, and if foo is an object, check that bar is a valid method;
if bar is the constructor - use __construct() instead;● If not, and if foo is an object, check that getBar is a valid method;● If not, and if foo is an object, check that isBar is a valid method;● If not, return a null value.
How Twig deals with variables?
![Page 52: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/52.jpg)
When using foo[‘bar’]
Check if foo is an array and bar a valid element;
If not, return a null value.
# foo is an array and 0 a valid index{{ foo.0 }}
# foo is an array and bar a valid index.{{ foo['bar'] }}
# bar is a variable containing the index in the foo array{{ foo[bar] }}
How Twig deals with variables?
![Page 53: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/53.jpg)
The « for » statement loops over each item in a sequence. For example, to display a list of users provided in a variable called users:
The for() loop accepts any array or objects that implements the Traversable interface.
<h1>Members</h1>
<ul> {% for user in users %} <li>{{ user.username }}</li> {% endfor %}</ul>
For loop
![Page 54: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/54.jpg)
Iterating over a sequence of numbers
Iterating over a sequence of letters
The .. operator can take any expression at both sides.
If you need a step different from 1, you can use the range function instead.
{% for i in 0..10 %} * {{ i }}{% endfor %}
{% for letter in 'a'..'z' %} * {{ letter }}{% endfor %}
{% for letter in 'a'|upper..'z'|upper %} * {{ letter }}{% endfor %}
{% for i in range(0, 10, 2) %} * {{ i }}{% endfor %}
For loop
![Page 55: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/55.jpg)
Inside of a for loop block you can access some special variables. Instead, note that you can’t break or continue in a loop.
loop.index The current iteration of the loop. (1 indexed)
loop.index0 The current iteration of the loop. (0 indexed)
loop.revindex The number of iterations from the end of the loop (1 indexed)
loop.revindex0 The number of iterations from the end of the loop (0 indexed)
loop.first True if first iteration
loop.last True if last iteration
loop.length The number of items in the sequence
loop.context The parent context
For loop
![Page 56: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/56.jpg)
If the array is empty or null, you can output something else instead.
If you want to iterate over the array keys, simple use the keys filter.
<ul>
{% for user in users %} <li>{{ user.username }}</li> {% else %} <li><em>no user found</em></li> {% endfor %}
</ul>
<h1>Members</h1>
<ul>
{% for key in users|keys %} <li>{{ key }}</li> {% endfor %}
</ul>
For loop
![Page 57: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/57.jpg)
Of course, you can grab both key and value in a row.
<h1>Members</h1>
<ul>
{% for key, user in users %} <li>{{ key }}: {{ user.username }}</li> {% endfor %}
</ul>
For loop
![Page 58: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/58.jpg)
Twig also brings an « if » conditional statement to perform decisions.
The « is defined » statement is called a « test » in Twig vocabulary. It checks that the variable is defined or not.
{% if users is defined %} <ul> {% for user in users %} <li>{{ user.username }}</li> {% endfor %} </ul>{% endif %}
Conditional statements
![Page 59: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/59.jpg)
Of course, you can expand the « if » conditional statement to « elseif » and « else » clauses as shown in the following snippet.
{% if kenny.sick %}
Kenny is sick.
{% elseif kenny.dead %}
You killed Kenny! You bastard!!!
{% else %}
Kenny looks okay --- so far
{% endif %}
Conditional statements
![Page 60: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/60.jpg)
Experimenting Twig
![Page 61: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/61.jpg)
![Page 62: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/62.jpg)
The controller
Implement your first controller to render « Hello World ».
# src/Acme/TodoBundle/Controller/DefaultController.phpnamespace Sensio\Bundle\TrainingBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;use Symfony\Component\HttpFoundation\Response;use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
class DefaultController extends Controller{ /** @Route("/hello/{name}", name="greet") */ public function indexAction($name) { return new Response(sprintf('Hello %s!', $name)); }}
![Page 63: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/63.jpg)
![Page 64: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/64.jpg)
![Page 65: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/65.jpg)
![Page 66: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/66.jpg)
Simplify the action code by adding a new extra annotation to the method php documentation to specify which template to render.
# src/Acme/TodoBundle/Controller/DefaultController.phpuse Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
class DefaultController extends Controller{ /** * @Route("/hello/{name}", name="greet") * @Template("AcmeTodoBundle:Default:index.html.twig") */ public function indexAction($name) { return array('name' => $name); }}
![Page 67: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/67.jpg)
Simplify the @Template annotation to let Symfony guess the template to render based on coding convention.
# src/Acme/TodoBundle/Controller/DefaultController.phpuse Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
class DefaultController extends Controller{ /** * @Route("/hello/{name}", name="greet") * @Template() */ public function indexAction($name) { return array('name' => $name); }}
![Page 68: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/68.jpg)
![Page 69: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/69.jpg)
![Page 70: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/70.jpg)
![Page 71: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/71.jpg)
![Page 72: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/72.jpg)
![Page 73: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/73.jpg)
![Page 74: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/74.jpg)
![Page 75: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/75.jpg)
![Page 76: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/76.jpg)
Assetic presented by Kris WallsmithAsset Management for PHP 5.3
![Page 77: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/77.jpg)
Lots of awesome tools:CoffeeScript
Compass Framework
CSSEmbed
Google Closure Compiler
JSMin
LESS
Packer
SASS
Sprockets
Stylus
YUI Compressor
![Page 78: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/78.jpg)
Assetic makes using these easy
![Page 79: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/79.jpg)
# /path/to/web/js/core.php$core = new FileAsset('/path/to/jquery.js');
$core->load();
header('Content-Type: text/javascript');
echo $core->dump();
![Page 80: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/80.jpg)
# /path/to/web/js/core.php
$core = new AssetCollection(array(
new FileAsset('/path/to/jquery.js'),
new GlobAsset('/path/to/js/core/*.js'),
));
$core->load();
header('Content-Type: text/javascript');
echo $core->dump();
![Page 81: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/81.jpg)
# /path/to/web/js/core.php
$core = new AssetCollection(array(
new FileAsset('/path/to/jquery.js'),
new GlobAsset('/path/to/js/core/*.js'),
), array(
new YuiCompressorJsFilter('/path/to/yui.jar'),
));
$core->load();
header('Content-Type: text/javascript');
echo $core->dump();
![Page 82: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/82.jpg)
<script src="js/core.php"></script>
![Page 83: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/83.jpg)
Assetic isAssets & Filters
Filters
![Page 84: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/84.jpg)
Inspired by Python’s webassets
https://github.com/miracle2k/webassets
![Page 85: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/85.jpg)
Assets have lazy, mutable content
![Page 86: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/86.jpg)
A filter acts on an asset’s contents during “load”
and “dump”
![Page 87: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/87.jpg)
Assets can be gathered in collections
![Page 88: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/88.jpg)
A collection is an asset
![Page 89: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/89.jpg)
![Page 90: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/90.jpg)
Basic Asset Classes•AssetCollection
•AssetReference
•FileAsset
•GlobAsset
•HttpAsset
•StringAsset
![Page 91: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/91.jpg)
Core Filter ClassesCoffeeScriptFilter
CompassFilter
CssEmbedFilter
CssImportFilter
CssMinFilter
CssRewriteFilter
GoogleClosure\CompilerApiFilter
GoogleClosure\CompilerJarFilter
JpegoptimFilter
JpegtranFilter
LessFilter
LessphpFilter
OptiPngFilter
PackagerFilter
![Page 92: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/92.jpg)
Core Filter ClassesPngoutFilter
Sass\SassFilter
Sass\ScssFilter
SprocketsFilter
StylusFilter
Yui\CssCompressorFilter
Yui\JsCompressorFilter
More to come…
![Page 93: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/93.jpg)
Twig Integration
![Page 94: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/94.jpg)
{% javascripts 'js/*.coffee' filter='coffee,?yui_js' %}
<script src="{{ asset_url }}"></script>
{% endjavascripts %}
![Page 95: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/95.jpg)
<script src="js/92429d8.js"></script>
![Page 96: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/96.jpg)
{% javascripts 'js/*.coffee' filter='coffee,?closure'
debug=true %}
<script src="{{ asset_url }}"></script>
{% endjavascripts %}
![Page 97: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/97.jpg)
<script src="js/92429d8_1.js"></script>
<script src="js/92429d8_2.js"></script>
<script src="js/92429d8_3.js"></script>
![Page 98: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/98.jpg)
AsseticBundleSymfony2 integration
![Page 99: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/99.jpg)
assetic:
debug: %kernel.debug%
use_controller: %kernel.debug%
filters:
coffee: ~
yui_js:
jar: /path/to/yui.jar
![Page 100: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/100.jpg)
{# when use_controller=true #}
<script src="{{ path('assetic_foo') }}"...
![Page 101: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/101.jpg)
# routing_dev.yml_assetic: resource: .
type: assetic
![Page 102: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/102.jpg)
{# when use_controller=false #}<script src="{{ asset('js/core.js') }}"></script>
![Page 103: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/103.jpg)
The Symfony2 Assets Helper
•Multiple asset domains
•Cache buster
![Page 104: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/104.jpg)
framework:
templating:
assets_version: 1.2.3
assets_base_urls:
- http://assets1.domain.com
- http://assets2.domain.com
- http://assets3.domain.com
- http://assets4.domain.com
![Page 105: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/105.jpg)
<link href="http://assets3.domain.com/css/all.css?1.2.3" ...
![Page 106: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/106.jpg)
assetic:dump
![Page 107: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/107.jpg)
$ php app/console assetic:dump web/
![Page 108: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/108.jpg)
assetic:dump --watchDump static assets in the background as you develop
![Page 109: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/109.jpg)
Error Management
![Page 110: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/110.jpg)
Error Management
Symfony2 is HTTP compliant as it’s able to send the corresponding status code depending on the leveraged error or exception when the request is handled.
![Page 111: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/111.jpg)
![Page 112: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/112.jpg)
![Page 113: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/113.jpg)
![Page 114: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/114.jpg)
![Page 115: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/115.jpg)
Persisting data between HTTP requests
![Page 116: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/116.jpg)
Persisting data between HTTP requests
Cookies and sessions were invented to offer a mean to simulate persistence between two different HTTP requests as the HTTP is a stateless protocol.
![Page 117: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/117.jpg)
The Request object API
# Getting the request service$request = $this->getRequest();
# Wether the request comes from an Ajax call$request->isXmlHttpRequest();
# Find the preferred language based on Accept-Language header$request->getPreferredLanguage(array('en', 'fr'));
# Get a $_GET parameter$request->query->get('page');
# Get a $_POST parameter$request->request->get('content');
# Get a $_COOKIE parameter$request->cookies->get('remember-me');
# Get a $_SERVER parameter$request->server->get('SCRIPT_NAME');
![Page 118: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/118.jpg)
{# Wether the request comes from an Ajax call #}{% if app.request.isXmlHttpRequest %}
{# Find the preferred language based on Accept-Language header #}{{ app.request.getPreferredLanguage(['en', 'fr']) }}
{# Get a $_GET parameter #}{{ app.request.query.get('page') }}
{# Get a parameter #}{{ app.request.parameter.get('content') }}
{# Get a $_COOKIE parameter #}{{ app.request.cookies.get('remember-me') }}
{# Get a $_SERVER parameter #}{{ app.request.server.get('SCRIPT_NAME') }}
The Request object from Twig
![Page 119: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/119.jpg)
# Getting a response$response = new Response('<html>...</html>');$response = $this->render('FooBundle:Bar:template.html.twig');
# Triggering a redirect response$response = new RedirectResponse('http://www.domain.tld/job/8');$response = $this->redirect($this->generateUrl('home'));
# Fixing HTTP Expiration headers$response->setExpires(new \DateTime('2011-10-01 11:10:00'));$response->setMaxAge(120);$response->setSharedMaxAge(120);
# Fixing HTTP Validation headers$response->setLastModified(new \DateTime('now'));$response->setETag('a1b2c3');
The Response object API
![Page 120: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/120.jpg)
![Page 121: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/121.jpg)
More with Templates
![Page 122: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/122.jpg)
Create a new « menu.html.twig » template in the « AcmeTodoBundle » bundle that contains the following code.
Include the menu in the header and footer sections of the layout.
{# src/Acme/TodoBundle/Resources/views/menu.html.twig #}<div class="navigation"> <a href="#">Home</a> | <a href="#">About</a> | <a href="#">Contact</a></div>
{# src/Acme/TodoBundle/Resources/views/layout.html.twig #}{% block body %}
<div id="header">{% include 'AcmeTodoBundle::menu.html.twig' %}</div>
<h1>Training Application</h1> {% block content %}{% endblock %} <div id="footer">{% include 'AcmeTodoBundle::menu.html.twig' %}</div>
{% endblock %}
![Page 123: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/123.jpg)
![Page 124: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/124.jpg)
Diving into the Model layer
![Page 125: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/125.jpg)
Symfony2 is a Model View Controller framework!
![Page 126: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/126.jpg)
The Client makes a Request on the Server…
![Page 127: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/127.jpg)
The Request hits the Front Controller.
The Front Controller dispatches to the corresponding Controller…
![Page 128: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/128.jpg)
The Controller handles the Request, calls the Model, passes data to the View,
and finally returns a Response…
![Page 129: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/129.jpg)
The Response is sent to the Client.
![Page 130: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/130.jpg)
In the MVC pattern, the Model is the most important layer as it stores data and business logic to access and modify them.
![Page 131: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/131.jpg)
Doctrine MongoDB ODMKris Wallsmith
![Page 132: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/132.jpg)
This is MongoDB…
![Page 133: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/133.jpg)
$mongo = new Mongo();
$db = $mongo->pdxphp;
$db->people->save(array(
'name' => 'Kris Wallsmith',
));
![Page 134: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/134.jpg)
$cursor = $db->people->find();
print_r(iterator_to_array($cursor));
![Page 135: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/135.jpg)
Array( [4cbdffdae84ded424f000000] => Array (
[_id] => MongoId Object
[name] => Kris Wallsmith ))
![Page 136: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/136.jpg)
MongoDB is where youput your arrays for later.
![Page 137: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/137.jpg)
$db->people->save(array(
'name' => 'Sam Keen',
'roles' => array(
'organizer',
'presenter',
),
));
![Page 138: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/138.jpg)
$query = array('roles' => 'presenter');
$cursor = $db->people->find($query);
print_r(iterator_to_array($cursor));
![Page 139: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/139.jpg)
Array( [4cbe03cfe84dedb850010000] => Array ( [_id] => MongoId Object [name] => Sam Keen [roles] => Array ( [0] => organizer [1] => presenter ) ))
![Page 140: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/140.jpg)
Me too!
![Page 141: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/141.jpg)
$query = array(
'name' => 'Kris Wallsmith',
);
$kris = $db->people->findOne($query);
$kris['roles'] = array('presenter');
$db->people->save($kris);
![Page 142: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/142.jpg)
$query = array('roles' => 'presenter');
$fields = array('name');
$cursor = $db->people->find($query, $fields);
print_r(iterator_to_array($cursor));
![Page 143: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/143.jpg)
Array( [4cbe0a9de84ded7952010000] => Array ( [_id] => MongoId Object [name] => Sam Keen ) [4cbe0a9de84ded7952000000] => Array ( [_id] => MongoId Object [name] => Kris Wallsmith ))
![Page 144: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/144.jpg)
Be surgical.
![Page 145: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/145.jpg)
$query = array('roles' => 'presenter');
$update = array(
'$push' => array(
'roles' => 'cool guy',
),
);
$db->people->update($query, $update);
![Page 146: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/146.jpg)
Atomic Operators
$inc
$set
$unset
$push
$pushAll
$addToSet
$pop
$pull
$pullAll
$rename
![Page 147: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/147.jpg)
Advanced Queries
![Page 148: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/148.jpg)
$roles = array('organizer', 'presenter');
$db->people->find(array(
'roles' => array('$all' => $roles),
));
![Page 149: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/149.jpg)
Conditional Operators
$ne
$in
$nin
$mod
$all
$size
$exists
$type
$or
$elemMatch
![Page 150: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/150.jpg)
Cursor Methods
![Page 151: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/151.jpg)
$cursor = $db->people->find();$cursor->sort(array('name' => 1));foreach ($cursor as $person) { // ...
}
![Page 152: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/152.jpg)
I like you, Sam.
![Page 153: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/153.jpg)
$samRef = MongoDBRef::create('people', $samId);$db->people->update( array('_id' => $kris['_id']), array( '$addToSet' => array( 'likes' => $samRef, ), )
);
![Page 154: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/154.jpg)
$sam = $db->getDBRef($samRef);
![Page 155: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/155.jpg)
$db->people->find(array(
'likes.$id' => $kris['_id'],
));
![Page 156: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/156.jpg)
TerminologyRDBMSRDBMS MongoDBMongoDB
Database Database
Table Collection
Row Document
Foreign Key Database Reference
![Page 157: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/157.jpg)
A document is an array.
![Page 158: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/158.jpg)
Arrays are nice.
![Page 159: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/159.jpg)
Objects are better.*
* Whenever objects are better.
![Page 160: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/160.jpg)
The Doctrine MongoDBObject Document Mapper
maps documentsto and from objects.
![Page 161: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/161.jpg)
We just need to tell it how.
![Page 162: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/162.jpg)
/** @Document(collection="people") */
class Person {
/** @Id */
public $id;
/** @String */
public $name;
/** @Collection */
public $roles = array();
/** @ReferenceMany */
public $likes = array();
/** @EmbedMany(targetDocument="Address") */
public $addresses = array();
}
![Page 163: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/163.jpg)
POPO FTW!
![Page 164: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/164.jpg)
$kris = new Person();
$kris->name = 'Kris Wallsmith';
$kris->roles[] = 'presenter';
$kris->likes[] = $sam;
$kris->addresses[] = $homeAddy;
$documentManager->persist($kris);
$documentManager->flush();
![Page 165: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/165.jpg)
Wherefore art thou->save()
???
![Page 166: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/166.jpg)
![Page 167: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/167.jpg)
![Page 168: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/168.jpg)
ActiveRecord is more abstract.
![Page 169: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/169.jpg)
Doctrine calculates theoptimal query for you.optimal query for you.
![Page 170: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/170.jpg)
$kris = $dm->findOne('Person', array(
'name' => 'Kris Wallsmith',
));
$kris->roles[] = 'cool guy';
$dm->flush();
![Page 171: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/171.jpg)
$db->people->update(array(
'_id' => $kris->id,
), array(
'$push' => array(
'roles' => 'cool guy',
),
));
![Page 172: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/172.jpg)
Query API
![Page 173: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/173.jpg)
$qb = $dm->createQueryBuilder('Person')
->field('name')->notEqual('Kris Wallsmith')
->field('roles')->equals('presenter')
->sort('name', 'asc');
$cursor = $qb->getQuery()->execute();
![Page 174: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/174.jpg)
Lifecycle Callbacks
![Page 175: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/175.jpg)
/** @Document */
class Foo {
/** @Date */
public $createdAt;
/** @PrePersist */
public function ensureCreatedAt() {
$this->createdAt = new DateTime();
}
}
![Page 176: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/176.jpg)
That’s MVC!
![Page 177: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/177.jpg)
Configuration principles
![Page 178: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/178.jpg)
Symfony2 supports several configuration file formats out of the box :
YAML, XML, INI or PHP code.
![Page 179: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/179.jpg)
Choosing the best file format
Pros Cons
XML ValidationIDE completion & help Verbose (not that much)
INI ConciseEasy to read and to change Limited syntax
YAML ConciseEasy to read and to change Hard to validate / YAML component
PHP Flexible, more expressive No validation
![Page 180: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/180.jpg)
Uncomment code to activate XML or PHP configuration
Default configuration format
# app/AppKernel.phpclass AppKernel extends Kernel{ # ... public function registerContainerConfiguration(LoaderInterface $loader) { // use YAML for configuration // comment to use another configuration format $loader->load(__DIR__.'/config/config_'.$this->getEnvironment().'.yml');
// uncomment to use XML for configuration //$loader->load(__DIR__.'/config/config_'.$this->getEnvironment().'.xml');
// uncomment to use PHP for configuration //$loader->load(__DIR__.'/config/config_'.$this->getEnvironment().'.php'); }}
![Page 181: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/181.jpg)
YAML configuration sample
# config/config_dev.ymlimports: - { resource: config.yml }
app.config: router: resource: "%kernel.root_dir%/config/routing_dev.yml"
profiler: { only_exceptions: false }
webprofiler.config: toolbar: true intercept_redirects: true
![Page 182: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/182.jpg)
XML configuration sample
<?xml version="1.0" ?><container xmlns="http://www.symfony-project.org/schema/dic/services" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:zend="http://www.symfony-project.org/schema/dic/zend" xmlns:app="http://www.symfony-project.org/schema/dic/symfony" xmlns:webprofiler="http://www.symfony-project.org/schema/dic/webprofiler" xsi:schemaLocation="http://www.symfony-project.org/schema/dic/services http://www.symfony-project.org/schema/dic/services/services-1.0.xsd http://www.symfony-project.org/schema/dic/webprofiler http://www.symfony-project.org/schema/dic/webprofiler/webprofiler-1.0.xsd http://www.symfony-project.org/schema/dic/zend http://www.symfony-project.org/schema/dic/zend/zend-1.0.xsd »> <imports> <import resource="config.xml" /> </imports> <app:config> <app:router resource="%kernel.root_dir%/config/routing_dev.xml" /> <app:profiler only-exceptions="false" /> </app:config> <webprofiler:config toolbar="true" intercept-redirects="true" /> <zend:config> <zend:logger priority="info" path="%kernel.logs_dir%/%kernel.environment%.log" /> </zend:config></container>
![Page 183: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/183.jpg)
PHP configuration sample
$loader->import('config.php');
$container->loadFromExtension('app', 'config', array( 'router' => array('resource' => '%kernel.root_dir%/config/routing_dev.php'), 'profiler' => array('only-exceptions' => false),));
$container->loadFromExtension('webprofiler', 'config', array( 'toolbar' => true, 'intercept-redirects' => true,));
$container->loadFromExtension('zend', 'config', array( 'logger' => array( 'priority' => 'info', 'path' => '%kernel.logs_dir%/%kernel.environment%.log', ),));
![Page 184: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/184.jpg)
Global configuration can be overloadedaccording to the environment you are on…
![Page 185: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/185.jpg)
Overriding and overloading principles
# config/config_dev.ymlimports: - { resource: config.yml } - { resource: "@FooBarBundle/Resources/config/foo.xml" }
app.config: router: { resource: "%kernel.root_dir%/config/routing_dev.yml" } profiler: { only_exceptions: false }
webprofiler.config: toolbar: true intercept_redirects: true
![Page 186: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/186.jpg)
Importing INI files
# app/config/config.ymlimports: - { resource: dice.config.ini }
parameters: available_colors: [red, green, blue, purple, yellow, black]
# app/config/dice.config.ini[parameters]dice.min = 1dice.max = 6
![Page 187: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/187.jpg)
Forms
![Page 188: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/188.jpg)
How does it work?
1) The form reads properties of an object,
2) Based on these values, form fields are prepopulated,
3) When the form is submitted, data are bound to the form,
4) Then, the validation business logic is applied on each field ,
5) If validation fails, form is displayed again with submitted values,
6) Otherwise, form is processed.
![Page 189: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/189.jpg)
![Page 190: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/190.jpg)
![Page 191: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/191.jpg)
Creating a new formnamespace Acme\DemoBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;use Acme\DemoBundle\Entity\Product;
class ShopController extends Controller{ /** * @Route("/product", name="_new_product") * @Template */ public function indexAction() { $product = new Product(); $product->name = 'Test product'; $product->setPrice('50.00');
$form = $this->createFormBuilder($product) ->add('name', 'text') ->add('price', 'money', array('currency' => 'USD')) ->getForm();
return array('form' => $form->createView()); }}
![Page 192: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/192.jpg)
![Page 193: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/193.jpg)
![Page 194: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/194.jpg)
![Page 195: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/195.jpg)
![Page 196: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/196.jpg)
Prototyping the form rendering
Symfony provides a dedicated Twig function to automate the rendering of a form in a template.
<form action="#" method="post">
{{ form_widget(form) }}
<button type="submit">Create the product</button></form>
![Page 197: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/197.jpg)
Prototyping the form rendering
Symfony provides a dedicated Twig function to automate the rendering of a form in a template.
<form action="#" method="post">
{{ form_widget(form) }}
<button type="submit">Create the product</button></form>
![Page 198: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/198.jpg)
![Page 199: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/199.jpg)
Creating a dedicated form class
To make the controller thinner and the form reusable anywhere, the best practice is
move the form creation code to a dedicated form class.
![Page 200: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/200.jpg)
// src/Acme/DemoBundle/Form/ProductType.phpnamespace Acme\DemoBundle\Form;
use Symfony\Component\Form\AbstractType;use Symfony\Component\Form\FormBuilder;
class ProductType extends AbstractType{ public function buildForm(FormBuilder $builder, array $options) { $builder->add('name'); $builder->add('price', 'money', array( 'currency' => 'USD' )); }}
Creating a custom form
![Page 201: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/201.jpg)
Using a form type from the controller
use Acme\DemoBundle\Entity\Product;use Acme\DemoBundle\Form\ProductType;
// ...
public function indexAction(){ $product = new Product(); $product->name = 'A name'; $product->setPrice(50.00);
$form = $this->createForm(new ProductType(), $product);
// ...}
![Page 202: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/202.jpg)
Experimenting Forms
![Page 203: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/203.jpg)
The contact request form
oBasic form composed of 3 fields (sender, subject, message)
oForm will validate a ContactRequest object
oThe ContactRequest properties are constrainted with validators
![Page 204: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/204.jpg)
First, create the contact type class in the AcmeTodoBundle bundle.
// src/Acme/TodoBundle/Form/ContactRequestType.phpnamespace Sensio\Bundle\TrainingBundle\Form;
use Symfony\Component\Form\AbstractType;use Symfony\Component\Form\FormBuilder;
class ContactRequestType extends AbstractType{ public function buildForm(FormBuilder $builder, array $options) { $builder->add('sender', 'text'); $builder->add('subject', 'text'); $builder->add('message', 'textarea'); }}
![Page 205: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/205.jpg)
The contact request domain object
The sender value is mandatory and must be a valid email address
namespace Sensio\TrainingBundle\Form;
use Symfony\Component\Validator\Constraints as Assert;
class ContactRequest{ /** * @Assert\Email() * @Assert\NotBlank() */ public $sender;
/** * @Assert\MaxLength(50) * @Assert\NotBlank() */ public $subject;
/** @Assert\NotBlank() */ public $message;}
The subject value is mandatory and can’t exceed 50 characters
![Page 206: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/206.jpg)
namespace Sensio\TrainingBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;use Symfony\Component\HttpFoundation\RedirectResponse;use Symfony\Component\HttpFoundation\Request;use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;use Sensio\TrainingBundle\Form\ContactRequest;use Sensio\TrainingBundle\Form\ContactRequestType;
class ContactController extends Controller{ /** * @Route("/contact", name="contact") * @Template */ public function indexAction(Request $request) { $contact = new ContactRequest(); $form = $this->createForm(new ContactRequestType(), $contact);
if ($request->getMethod() == 'POST') { $form->bindRequest($request);
if ($form->isValid()) { // ... send an email return $this->redirect($this->generateUrl('contact_success')); } }
return array('form' => $form->createView()); }}
![Page 207: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/207.jpg)
Prototyping the form rendering
Symfony provides a dedicated Twig function to automate the rendering of a form in a template.
<form action="#" method="post">
{{ form_widget(form) }}
<button type="submit">Create the product</button></form>
![Page 208: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/208.jpg)
Implementing the success page
{# @AcmeTodoBundle/Resources/views/Contact/thankYou.html.twig #}
{% extends 'AcmeTodoBundle::layout.html.twig' %}
{% block content %}
<h2>Contact Us</h2> <p>Thanks for your message</p>
{% endblock %}
/** * @Route("/contact/thank-you", name="contact_success") * @Template */public function thankYouAction(){ return array();}
![Page 209: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/209.jpg)
![Page 210: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/210.jpg)
![Page 211: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/211.jpg)
In order to verify application behaviorAs a software developer
I need tests
![Page 212: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/212.jpg)
In order to verify application behaviorAs a software developer
I need tests
Preferably automated tests
![Page 213: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/213.jpg)
Test-Driven Development...is an iterative design process
● Write a test
![Page 214: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/214.jpg)
Test-Driven Development...is an iterative design process
● Write a test● Ensure the new test fails
![Page 215: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/215.jpg)
Test-Driven Development...is an iterative design process
● Write a test● Ensure the new test fails● Write code to satisfy the test
![Page 216: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/216.jpg)
Test-Driven Development...is an iterative design process
● Write a test● Ensure the new test fails● Write code to satisfy the test● Ensure all tests pass
![Page 217: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/217.jpg)
Test-Driven Development...is an iterative design process
● Write a test● Ensure the new test fails● Write code to satisfy the test● Ensure all tests pass● Refactor
![Page 218: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/218.jpg)
Test-Driven Development...is an iterative design process
● Write a test● Ensure the new test fails● Write code to satisfy the test● Ensure all tests pass● Refactor● Repeat
![Page 219: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/219.jpg)
Dan North Introduces BDD
I had a problem. While using and teaching agile practices like test-driven development (TDD) on projects in different environments, I kept coming across the same confusion and misunderstandings. Programmers wanted to know:● Where to start● What to test and what not to test● How much to test in one go● What to call their tests● How to understand why a test fails
“
http://dannorth.net/introducing-bdd/
![Page 220: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/220.jpg)
I started using the word “behavior” in place of “test” in my dealings with TDD and… I now had answers to some of those TDD questions:● What to call your test is easy – it’s a sentence describing the next behavior in which you are interested.● How much to test becomes moot – you can only describe so much behavior in a single sentence.● When a test fails, simply work through the process described above – either you introduced a bug, the
behavior moved, or the test is no longer relevant.
“
http://dannorth.net/introducing-bdd/
Dan North Introduces BDD
![Page 221: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/221.jpg)
Behavior-Driven Development...builds upon TDD
● Write test cases in a natural language
![Page 222: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/222.jpg)
Behavior-Driven Development...builds upon TDD
● Write test cases in a natural language
•Understood by developers and business folks alike
![Page 223: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/223.jpg)
Behavior-Driven Development...builds upon TDD
● Write test cases in a natural language
•Understood by developers and business folks alike
•Helps relate domain language of requirements to the code
![Page 224: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/224.jpg)
Behavior-Driven Development...builds upon TDD
● Write test cases in a natural language
•Understood by developers and business folks alike
•Helps relate domain language of requirements to the code● Do this with user stories and scenarios
![Page 225: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/225.jpg)
Behavior-Driven Development...builds upon TDD
● Write test cases in a natural language
•Understood by developers and business folks alike
•Helps relate domain language of requirements to the code● Do this with user stories and scenarios
•User stories describe a feature's benefit in context
![Page 226: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/226.jpg)
Behavior-Driven Development...builds upon TDD
● Write test cases in a natural language
•Understood by developers and business folks alike
•Helps relate domain language of requirements to the code● Do this with user stories and scenarios
•User stories describe a feature's benefit in context
•Scenarios are executable acceptance criteria
![Page 227: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/227.jpg)
Behavior-Driven Development...builds upon TDD
● Write test cases in a natural language
• Understood by developers and business folks alike
• Helps relate domain language of requirements to the code● Do this with user stories and scenarios
• User stories describe a feature's benefit in context
• Scenarios are executable acceptance criteria
A story’s behavior is simply its acceptance criteria – if the system fulfills all the acceptance criteria, it’s behaving correctly; if it doesn’t, it isn’t.
http://dannorth.net/introducing-bdd/
“
![Page 228: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/228.jpg)
So what does this look like?
![Page 229: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/229.jpg)
![Page 230: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/230.jpg)
![Page 231: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/231.jpg)
This is where Behat and Mink come in.
![Page 232: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/232.jpg)
This is where Behat and Mink come in.
Acceptance testing (any tests)
Tests a feature by executing its scenarios' steps in a context.
Web acceptance testing (functional tests)
Drivers for Goutte, Sahi and Symfony2's test client.
![Page 233: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/233.jpg)
Initialize Our Bundle With Behat
$ app/console behat --init @AcmeDemoBundle
+d src/Acme/DemoBundle/Features
- place your *.feature files here
+f src/Acme/DemoBundle/Features/Context/FeatureContext.php
- place your feature related code here
● We now have a directory to hold AcmeDemoBundle's features● Behat also creates an empty FeatureContext class, which extends BehatBundle's
BehatContext
• Features describe our behavior, but the context tells Behat how to evaluate our feature as an executable test
![Page 234: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/234.jpg)
Let's Have Behat Analyze Our Feature
$ app/console behat src/Acme/DemoBundle/Features/contact.feature
Feature: Contact form
In order to contact an email address
As a visitor
I need to be able to submit a contact form
Scenario: Successfully submit the contact form # contact.feature:6
Given I am on "/demo/contact"
When I fill in "Email" with "[email protected]"
And I fill in "Message" with "Hello there!"
And I press "Send"
Then I should see "Message sent!"
1 scenario (1 undefined)
5 steps (5 undefined)
![Page 235: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/235.jpg)
Behat Creates the Glue...but the rest is up to you
/**
* @Given /^I am on "([^"]*)"$/
*/
public function iAmOn($argument1)
{
throw new PendingException();
}
/**
* @When /^I fill in "([^"]*)" with "([^"]*)"$/
*/
public function iFillInWith($argument1, $argument2)
{
throw new PendingException();
}
/**
* @Given /^I press "([^"]*)"$/
*/
public function iPress($argument1)
{
throw new PendingException();
}
/**
* @Then /^I should see "([^"]*)"$/
*/
public function iShouldSee($argument1)
{
throw new PendingException();
}
You can implement step definitions for undefined steps with these snippets:
![Page 236: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/236.jpg)
Not so fast. What about Mink?
![Page 237: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/237.jpg)
MinkContext Defines Steps...for making requests
Pattern DescriptionGiven /^I am on "(?P<page>[^"]+)"$/ Opens specified pageWhen /^I go to "(?P<page>[^"]+)"$/ Opens specified pageWhen /^I reload the page$/ Reloads current pageWhen /^I move backward one page$/ Moves backward one page in historyWhen /^I move forward one page$/ Moves forward one page in historyWhen /^I press "(?P<button>(?:[^"]|\\")*)"$/
Presses button with specified id|name|title|alt|value
When /^I follow "(?P<link>(?:[^"]|\\")*)"$/ Clicks link with specified id|title|alt|text
![Page 238: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/238.jpg)
MinkContext Defines Steps...for interacting with forms
Pattern DescriptionWhen /^I fill in "(?P<field>(?:[^"]|\\")*)" with "(?P<value>(?:[^"]|\\")*)"$/ Fills in form field with specified id|name|label|value
When /^I fill in "(?P<value>(?:[^"]|\\")*)" for "(?P<field>(?:[^"]|\\")*)"$/ Fills in form field with specified id|name|label|value
When /^I fill in the following:$/ Fills in form fields with provided table
When /^I select "(?P<option>(?:[^"]|\\")*)" from "(?P<select>(?:[^"]|\\")*)"$/ Selects option in select field with specified id|name|label|value
When /^I check "(?P<option>(?:[^"]|\\")*)"$/ Checks checkbox with specified id|name|label|value
When /^I uncheck "(?P<option>(?:[^"]|\\")*)"$/ Unchecks checkbox with specified id|name|label|value
When /^I attach the file "(?P<path>[^"]*)" to "(?P<field>(?:[^"]|\\")*)"$/ Attaches file to field with specified id|name|label|value
![Page 239: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/239.jpg)
![Page 240: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/240.jpg)
MinkContext Defines Steps...for querying the DOM
Pattern DescriptionThen /^I should see "(?P<text>(?:[^"]|\\")*)" in the "(?P<element>[^"]*)" element$/
Checks that element with specified CSS contains specified text
Then /^the "(?P<element>[^"]*)" element should contain "(?P<value>(?:[^"]|\\")*)"$/
Checks that element with specified CSS contains specified HTML
Then /^I should see an? "(?P<element>[^"]*)" element$/ Checks that element with specified CSS exists on page
Then /^I should not see an? "(?P<element>[^"]*)" element$/ Checks that element with specified CSS doesn't exist on page
Then /^the "(?P<field>(?:[^"]|\\")*)" field should contain "(?P<value>(?:[^"]|\\")*)"$/
Checks that form field with specified id|name|label|value has specified value
Then /^the "(?P<field>(?:[^"]|\\")*)" field should not contain "(?P<value>(?:[^"]|\\")*)"$/
Checks that form field with specified id|name|label|value doesn't have specified value
Then /^the "(?P<checkbox>(?:[^"]|\\")*)" checkbox should be checked$/ Checks that checkbox with specified id|name|label|value is checked
Then /^the "(?P<checkbox>(?:[^"]|\\")*)" checkbox should not be checked$/ Checks that checkbox with specified id|name|label|value is unchecked
![Page 241: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/241.jpg)
MinkContext Defines Steps...for examining responses
Pattern DescriptionThen /^I should be on "(?P<page>[^"]+)"$/ Checks that current page path is equal to specified
Then /^the url should match "(?P<pattern>(?:[^"]|\\")*)"$/ Checks that current page path matches pattern
Then /^the response status code should be (?P<code>\d+)$/ Checks that current page response status is equal to specified
Then /^I should see "(?P<text>(?:[^"]|\\")*)"$/ Checks that page contains specified text
Then /^I should not see "(?P<text>(?:[^"]|\\")*)"$/ Checks that page doesn't contain specified text
Then /^the response should contain "(?P<text>(?:[^"]|\\")*)"$/ Checks that HTML response contains specified string
Then /^the response should not contain "(?P<text>(?:[^"]|\\")*)"$/ Checks that HTML response doesn't contain specified string
Then /^print last response$/ Prints last response to console
Then /^show last response$/ Opens last response content in browser
![Page 242: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/242.jpg)
![Page 243: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/243.jpg)
![Page 244: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/244.jpg)
Let's Execute Our Feature With Behat
$ app/console behat @AcmeDemoBundle --env=test
Feature: Contact form
In order to contact an email address
As a visitor
I need to be able to submit a contact form
Scenario: Successfully submit the contact form # contact.feature:6
Given I am on "/demo/contact" # FeatureContext::visit()
When I fill in "Email" with "[email protected]" # FeatureContext::fillField()
Form field with id|name|label|value "Email" not found
And I fill in "Message" with "Hello there!" # FeatureContext::fillField()
And I press "Send" # FeatureContext::pressButton()
Then I should see "Message sent!" # FeatureContext::assertPageContainsText()
1 scenario (1 failed)
5 steps (1 passed, 3 skipped, 1 failed)
![Page 245: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/245.jpg)
![Page 246: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/246.jpg)
A Note About Step Results...of which there are seven
● Success: a definition was found and executing it did not throw an Exception●Undefined: a definition couldn't be found; all subsequent steps will be skipped●Pending: the definition threw the special PendingException, which means you have
work to do; skip remaining steps● Failure: a definition throws an Exception; Behat will skip remaining steps and
terminate with exit status 1•Behat can easily use PHPUnit's assertion framework or you can roll your own● Skipped: steps which were never executed●Ambiguous: multiple definitions matched a step●Redundant: multiple definitions share the same pattern
![Page 247: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/247.jpg)
Implement the Contact Form
![Page 248: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/248.jpg)
Implement the Contact Form
![Page 249: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/249.jpg)
Implement the Contact Form
![Page 250: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/250.jpg)
Let's Try That Again
$ app/console behat @AcmeDemoBundle --env=test
Feature: Contact form
In order to contact an email address
As a visitor
I need to be able to submit a contact form
Scenario: Successfully submit the contact form # contact.feature:6
Given I am on "/demo/contact" # FeatureContext::visit()
When I fill in "Email" with "[email protected]" # FeatureContext::fillField()
And I fill in "Message" with "Hello there!" # FeatureContext::fillField()
And I press "Send" # FeatureContext::pressButton()
Then I should see "Message sent!" # FeatureContext::assertPageContainsText()
1 scenario (1 passed)
5 steps (5 passed)
![Page 251: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/251.jpg)
![Page 252: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/252.jpg)
What Else Can Mink Do?
● Provide a single API for browser behavior• HTTP authentication, cookies, headers, sessions• Page examination via XPath or CSS selectors• Page manipulation (e.g. complete forms, click, hover, drag-and-drop)● Existing drivers can be used interchangeably• Symfony2 test client – simulated request serving • Goutte – headless, PHP web scraper• Sahi – brower-control toolkit (necessary for JS)• PhantomJS – headless browser-control for Webkit•http://www.ryangrenz.com/2011/05/30/experiments-with-behat-part1-mink-sahi-phantomjs/
![Page 253: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/253.jpg)
Thanks!
http://behat.org/
http://mink.behat.org/
http://github.com/Behat
![Page 254: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/254.jpg)
![Page 255: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/255.jpg)
Create a bundle
php app/console generate:bundle --namespace=Acme/TodoBundle
![Page 256: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/256.jpg)
git clone https://github.com/jmikola/top-shelf-php.git
![Page 257: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/257.jpg)
Questions?
![Page 258: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/258.jpg)
Thanks for joining Top Shelf PHP!
http://symfony.com
http://github.com/kriswallsmith/assetic
http://behat.org
![Page 259: The format – Talks then Hackingassets.en.oreilly.com/1/event/61/Top Shelf PHP Presentation 1.pdf · The format – Talks then Hacking. Follow along with the sandbox](https://reader036.vdocuments.net/reader036/viewer/2022062504/5a72a1347f8b9abb538dbb66/html5/thumbnails/259.jpg)