112
The State of Symfony2 Fabien Potencier

The state of Symfony2 - SymfonyDay 2010

Embed Size (px)

DESCRIPTION

 

Citation preview

Page 1: The state of Symfony2 - SymfonyDay 2010

The State of Symfony2

Fabien Potencier

Page 2: The state of Symfony2 - SymfonyDay 2010

@fabpot

fabien.potencier.org

Page 3: The state of Symfony2 - SymfonyDay 2010

How many of you have already played with Symfony2?

http://www.flickr.com/photos/bartworldv6/4206815555

Page 4: The state of Symfony2 - SymfonyDay 2010

Symfony2 is not ready for production

http://www.flickr.com/photos/rknickme/2205111920

Page 5: The state of Symfony2 - SymfonyDay 2010

Current guestimate for stable release March 2011

http://www.flickr.com/photos/pictureperfectpose/76138988

Page 6: The state of Symfony2 - SymfonyDay 2010

Crazy people do use Symfony2

http://www.flickr.com/photos/funky64/4267353106/

Page 7: The state of Symfony2 - SymfonyDay 2010

http://www.flickr.com/photos/lululemonathletica/4229883622

Page 8: The state of Symfony2 - SymfonyDay 2010

http://www.flickr.com/photos/cayusa/1209794692

Page 9: The state of Symfony2 - SymfonyDay 2010

http://www.flickr.com/photos/y-a-n/29789408

Page 10: The state of Symfony2 - SymfonyDay 2010

http://www.flickr.com/photos/migrainechick/3704150226

Symfony2 Translation Component

Page 11: The state of Symfony2 - SymfonyDay 2010

http://www.flickr.com/photos/muffytyrone/4096351705

Page 12: The state of Symfony2 - SymfonyDay 2010

symfony vs Symfony2

http://www.flickr.com/photos/thebusybrain/2492945625

Page 13: The state of Symfony2 - SymfonyDay 2010

http://www.flickr.com/photos/rinux/631345826

Messages

Domains

Locales

Page 14: The state of Symfony2 - SymfonyDay 2010

$t->trans('Symfony2 is great!')

Page 15: The state of Symfony2 - SymfonyDay 2010

$t->trans('Hello {{ name }}!', array('{{ name }}' => 'Symfony2'))

Page 16: The state of Symfony2 - SymfonyDay 2010

$t->trans('Symfony2 is great!', array(), 'app')

Page 17: The state of Symfony2 - SymfonyDay 2010

http://www.flickr.com/photos/orinrobertjohn/114430223

Pluralization vs Choice

Page 18: The state of Symfony2 - SymfonyDay 2010

$t->transChoice($string, $count, $vars)

Page 19: The state of Symfony2 - SymfonyDay 2010

One apple|{{ count }} apples

Page 20: The state of Symfony2 - SymfonyDay 2010

one: One apple|some: {{ count }} apples

Page 21: The state of Symfony2 - SymfonyDay 2010

{1} One apple|[0,Inf] {{ count }} apples

Page 22: The state of Symfony2 - SymfonyDay 2010

0 apples

No apples

Page 23: The state of Symfony2 - SymfonyDay 2010

{0} No apples| {1} One apple|

]1,Inf] {{ count }} apples

Page 24: The state of Symfony2 - SymfonyDay 2010

[-Inf,0[ WTF?!| {0} No apples| {1} One apple|

[2,19] Some apples| [20,Inf] Many apples

Page 25: The state of Symfony2 - SymfonyDay 2010

{0} No apples| One apple|

{{ count }} apples

Page 26: The state of Symfony2 - SymfonyDay 2010

<app:translator fallback="en" />

fr_FR fr en

Page 27: The state of Symfony2 - SymfonyDay 2010

PHP vs Twig

http://www.flickr.com/photos/danielmarenco/4775410299

Page 28: The state of Symfony2 - SymfonyDay 2010

« All templating engines are equal in the eyes of Symfony2 »

Page 29: The state of Symfony2 - SymfonyDay 2010

$this->render('BlogBundle:Post:index.php', array());

PHP renderer

Page 30: The state of Symfony2 - SymfonyDay 2010

$this->render('BlogBundle:Post:index.twig', array());

Twig renderer

Page 31: The state of Symfony2 - SymfonyDay 2010

$this->render('BlogBundle:Post:index.twig', array());

Template logical name

Page 32: The state of Symfony2 - SymfonyDay 2010

« Template engines are all equals, but some are more equals than others »

Page 33: The state of Symfony2 - SymfonyDay 2010

<?php echo $view['translator'] ->trans('Symfony2 is great!') ?>

vs

{% trans "Symfony2 is great!" %}

Page 34: The state of Symfony2 - SymfonyDay 2010

<?php echo $view['translator'] ->trans('Symfony2 is {{ what }}!', array('{{ what }}' => 'great'), 'app') ?>

vs

{% trans from app %} Symfony2 is {{ what }}! {% endtrans %}

Page 35: The state of Symfony2 - SymfonyDay 2010

<?php echo $view['translator'] ->transChoice( 'No apples|One apple|{{ count }} apples', 1, array('{{ count }}' => 1), 'app') ?>

vs

{% transchoice 1 from app %} No apples|One apple|{{ count }} apples {% endtranschoice %}

Page 36: The state of Symfony2 - SymfonyDay 2010

<?php echo $view['translator'] ->transChoice( 'No apples|One apple|{{ count }} apples', 1, array('{{ count }}' => 1), 'app') ?>

Page 37: The state of Symfony2 - SymfonyDay 2010

<?php echo $view['translator'] ->transChoice( 'No apples|One apple|{{ count }} apples', 1, array('{{ count }}' => 1), 'app') ?>

Page 38: The state of Symfony2 - SymfonyDay 2010

<?php echo $view['translator'] ->transChoice( 'No apples|One apple|{{ count }} apples', 1, array('{{ count }}' => 1), 'app') ?>

Page 39: The state of Symfony2 - SymfonyDay 2010

{% transchoice 1 from app %} No apples|One apple|{{ count }} apples {% endtranschoice %}

Page 40: The state of Symfony2 - SymfonyDay 2010

<?php echo $view['session']->getFlash('notice') ?>

vs

{% flash "notice" %}

Page 41: The state of Symfony2 - SymfonyDay 2010

<?php $view['slots']->start('title') ?> Post: <?php echo $post->getTitle() ?> <?php $view['slots']->stop() ?>

vs

{% block title %} Post: {{ post.title }} {% endblock title %}

Page 42: The state of Symfony2 - SymfonyDay 2010

Customizing Forms

http://www.flickr.com/photos/blackbutterfly/2304084815

Page 43: The state of Symfony2 - SymfonyDay 2010

{{ form|render_enctype }} {{ form|render_errors }} {{ form|render_hidden }}

{{ form.name|render_widget }} {{ form.name|render_label }} {{ form.name|render_errors }} {{ form.name|render_data }}

Page 44: The state of Symfony2 - SymfonyDay 2010

{{ form.name|render_widget }}

Page 45: The state of Symfony2 - SymfonyDay 2010

An InputField instance

is rendered by

an input_field template block

Page 46: The state of Symfony2 - SymfonyDay 2010

{% block input_field %} {% tag "input" with attributes %} {% endblock %}

{% block textarea_field %} {% contenttag "textarea" with attributes %} {{ field.displayedData }} {% endcontenttag %} {% endblock %}

Page 47: The state of Symfony2 - SymfonyDay 2010

{{ form.name|render_widget }}

Page 48: The state of Symfony2 - SymfonyDay 2010

{{ form.user.name|render_widget }}

Page 49: The state of Symfony2 - SymfonyDay 2010

How can I customize the rendering of the widget?

Page 50: The state of Symfony2 - SymfonyDay 2010

{{ form.name|render_widget("BlogBundle::widgets.twig") }}

Page 51: The state of Symfony2 - SymfonyDay 2010

{% block input_field %} <span class="input_field"> {% tag "input" with attributes %} </span> {% endblock %}

Page 52: The state of Symfony2 - SymfonyDay 2010

{% extends 'TwigBundle::widgets.twig' %}

{% block input_field %} <span class="input_field"> {% parent %} </span> {% endblock %}

Page 53: The state of Symfony2 - SymfonyDay 2010

How can I customize the rendering of all input widgets for a given form?

Page 54: The state of Symfony2 - SymfonyDay 2010

{% form_theme form "BlogBundle::widgets.twig" %}

Page 55: The state of Symfony2 - SymfonyDay 2010

How can I customize the rendering of all input widgets for all forms?

Page 56: The state of Symfony2 - SymfonyDay 2010

<twig:config> <twig:form> <twig:resource> BlogBundle::widgets.twig </twig:resource> </twig:form> </twig:config>

Page 57: The state of Symfony2 - SymfonyDay 2010

Nice inheritance/fallback templating system

Page 58: The state of Symfony2 - SymfonyDay 2010

Same questions as before but now for several widgets

Page 59: The state of Symfony2 - SymfonyDay 2010

{% block input_field %} <span class="input_field"> {% parent %} </span> {% endblock %}

{% block textarea_field %} <span class="textarea_field"> {% parent %} </span> {% endblock %}

...

Page 60: The state of Symfony2 - SymfonyDay 2010

{% block input_field %} {% tag "input" with attributes %} {% endblock input_field %}

{% block textarea_field %} {% contenttag "textarea" with attributes %}{{ field.displayedData }}{% endcontenttag %} {% endblock textarea_field %}

{% block choice_field %} {% if field.options.expanded %} {% for child in field %}{{ child|render_widget }}{% endfor %} {% else %} {% contenttag "select" with attributes %}{{ field|render_choices }}{% endcontenttag %} {% endif %} {% endblock choice_field %}

{% block toggle_field %} {% display input_field %} {% if field.options.label %}{% contenttag "label" with ['for': field.id] %}{% trans field.options.label %}{% endcontenttag %}{% endif %} {% endblock toggle_field %}

{% block date_time_field %} {{ field.date|render_widget }}{{ field.time|render_widget }} {% endblock date_time_field %}

{% block date_field %} {% if field.field %} {% display input_field %} {% else %} {{ field.pattern|replace(['{{ year }}': field.year|render_widget, '{{ month }}': field.month|render_widget, '{{ day }}': field.day|render_widget,]) }} {% endif %} {% endblock date_field %}

{% block time_field %} {% if field.isfield %} {% display input_field %} {% else %} {{ field.hour|render_widget }}:{{ field.minute|render_widget }} {% if field.options.with_seconds %}:{{ field.second|render_widget }}{% endif %} {% endif %} {% endblock time_field %}

{% block money_field %} {% set widget %}{% display input_field %}{% endset %}{{ field.pattern|replace(['{{ widget }}': widget]) }} {% endblock money_field %}

{% block percent_field %} {% display input_field %} % {% endblock percent_field %}

Page 61: The state of Symfony2 - SymfonyDay 2010

http://www.flickr.com/photos/powerbooktrance/466709245

Symfony2 Security

Page 62: The state of Symfony2 - SymfonyDay 2010

XSS CSRF SQL Injection

http://www.flickr.com/photos/mastrobiggo/2322337810

Page 63: The state of Symfony2 - SymfonyDay 2010

Authentication Authorization

http://www.flickr.com/photos/stevendepolo

Page 64: The state of Symfony2 - SymfonyDay 2010

$this->getUser()->getGuardUser()->getProfile()

symfony Core sf*GuardPlugin Your Code

Page 65: The state of Symfony2 - SymfonyDay 2010

$this->getUser()->getGuardUser()->getProfile()

sfBasicSecurityUser tied to the session

sfGuardUser tied to an ORM

comes from sf*GuardPlugin

Your object tied to an ORM

OO Composition

Page 66: The state of Symfony2 - SymfonyDay 2010

What if I don’t want to use an ORM?

Page 67: The state of Symfony2 - SymfonyDay 2010

$this['security.context']->getUser()

Symfony2 Core Your Code

Page 68: The state of Symfony2 - SymfonyDay 2010

$this['security.context']->getUser()

Your POPO Implements AccountInterface

Page 69: The state of Symfony2 - SymfonyDay 2010

How does Symfony2 know about your Users?

Page 70: The state of Symfony2 - SymfonyDay 2010

AccountInterface

UserProviderInterface

Page 71: The state of Symfony2 - SymfonyDay 2010

namespace Bundle\AccountBundle\Model;

use Symfony\Component\Security\User\AccountInterface;

class User implements AccountInterface { // ... }

Page 72: The state of Symfony2 - SymfonyDay 2010

<provider> <class="AccountBundle\\Model\\User" /> </provider>

Page 73: The state of Symfony2 - SymfonyDay 2010

namespace Bundle\AccountBundle\Entity;

use Symfony\Component\Security\User\AccountInterface;

/** * @Entity */ class User implements AccountInterface { // ... }

Page 74: The state of Symfony2 - SymfonyDay 2010

<provider> <entity class="AccountBundle:User" /> </provider>

Page 75: The state of Symfony2 - SymfonyDay 2010

namespace Bundle\AccountBundle\Entity\Repository;

use Doctrine\ORM\EntityRepository; use Symfony\Component\Security\User\UserProviderInterface;

class UserRepository extends EntityRepository implements UserProviderInterface { public function loadUserByUsername($username) { return $this->findOneBy(array('user' => $username)); } }

Page 76: The state of Symfony2 - SymfonyDay 2010

<provider> <entity class="AccountBundle:User" property="user" /> </provider>

Page 77: The state of Symfony2 - SymfonyDay 2010

What if I want to use the email for the username?

Page 78: The state of Symfony2 - SymfonyDay 2010

namespace Bundle\BlogBundle\Entity;

use Symfony\Component\Security\User\AccountInterface;

/** * @Entity */ class User implements AccountInterface { public function getUsername() { return $this->email; }

// ... }

Page 79: The state of Symfony2 - SymfonyDay 2010

But, I just have one administrator

or… How can I secure my personal website backend?

Page 80: The state of Symfony2 - SymfonyDay 2010

<provider> <user name="fabien" password="C00!" role="ROLE_ADMIN" /> </provider>

Page 81: The state of Symfony2 - SymfonyDay 2010

<provider> <password-encoder hash="sha1" /> <user name="fabien" password="0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33" role="ROLE_ADMIN" /> </provider>

Page 82: The state of Symfony2 - SymfonyDay 2010

namespace Bundle\BlogBundle\Entity;

use Symfony\Component\Security\User\AccountInterface;

/** * @Entity */ class User implements AccountInterface { public function getSalt() { return $this->id; }

// ... }

Page 83: The state of Symfony2 - SymfonyDay 2010

Also useful for testing and prototyping

Page 84: The state of Symfony2 - SymfonyDay 2010

What if I want to use LDAP, in-memory, and a DB for my users?

Page 85: The state of Symfony2 - SymfonyDay 2010

<provider> <password-encoder hash="sha1" /> <user name="fabien" password="..." role="ROLE_ADMIN" /> </provider>

<provider> <entity class="AccountBundle:User" property="user" /> </provider>

Page 86: The state of Symfony2 - SymfonyDay 2010

How is Security plugged in?

Page 87: The state of Symfony2 - SymfonyDay 2010

Request

Response

core.controller

core.response

core.view

core.request

getController()

getArguments()

core.exception

Page 88: The state of Symfony2 - SymfonyDay 2010

Symfony2 Firewall

http://www.flickr.com/photos/mederic/68456509

Page 89: The state of Symfony2 - SymfonyDay 2010

Request

Response

core.controller

core.response

core.view

core.request

getController()

getArguments()

core.security HttpKernel\Security\Firewall

Page 90: The state of Symfony2 - SymfonyDay 2010

Authentication http://www.flickr.com/photos/ul_marga/755378645

Page 91: The state of Symfony2 - SymfonyDay 2010

<firewall> <http-basic /> </firewall>

Page 92: The state of Symfony2 - SymfonyDay 2010

What if I want stateless authentication?

Page 93: The state of Symfony2 - SymfonyDay 2010

<firewall stateless="true"> <http-basic /> </firewall>

Page 94: The state of Symfony2 - SymfonyDay 2010

What if I want different authentication strategies in one app?

Page 95: The state of Symfony2 - SymfonyDay 2010

<firewall pattern="/api/.*" stateless="true"> <http-basic /> </firewall>

<firewall pattern=".*" security="none" />

Page 96: The state of Symfony2 - SymfonyDay 2010

<firewall pattern="/api/.*" stateless="true"> <http-basic /> </firewall>

<firewall pattern="/public/.*" security="none" />

<firewall> <form-login /> </firewall>

Page 97: The state of Symfony2 - SymfonyDay 2010

One Application per Symfony2 Project

http://www.flickr.com/photos/cdell/548548453

Page 98: The state of Symfony2 - SymfonyDay 2010

What if I want to support different authentication strategies

in one section of an app?

Page 99: The state of Symfony2 - SymfonyDay 2010

<firewall> <form-login /> <http-basic /> </firewall>

Page 100: The state of Symfony2 - SymfonyDay 2010

Using LDAP/certificate/OpenID authentication is really easy

Page 101: The state of Symfony2 - SymfonyDay 2010

Authorization

http://www.flickr.com/photos/theodevil/4911737917

Page 102: The state of Symfony2 - SymfonyDay 2010

<access> <url path="/api/.*" role="ROLE_REMOTE" /> </access>

Page 103: The state of Symfony2 - SymfonyDay 2010

<access> <url role="ROLE_USER"> <attribute key="_controller" pattern=".*\\BlogBundle\\.*" /> </url> </access>

Page 104: The state of Symfony2 - SymfonyDay 2010

/article/:id

<access> <url role="ROLE_ADMIN"> <attribute key="id" pattern="21" /> </url> </access>

<access> <url path="/article/21" role="ROLE_ADMIN" /> </access>

Page 105: The state of Symfony2 - SymfonyDay 2010

<access> <url path="/admin/.*" ip="10.0.0.0/24" role="ROLE_ADMIN" /> </access>

Page 106: The state of Symfony2 - SymfonyDay 2010

<access> <url path="/api/.*" role="ROLE_REMOTE" />

<url path="/public/.*" role="IS_AUTHENTICATED_ANONYMOUSLY" />

<url role='ROLE_USER'> <attribute key="controller" pattern=".*\\BlogBundle\\.*" /> </url> </access>

Page 107: The state of Symfony2 - SymfonyDay 2010

… and much more

Page 108: The state of Symfony2 - SymfonyDay 2010

Implementation based on Spring Security

Page 109: The state of Symfony2 - SymfonyDay 2010

First proof-of-concept available next week

Page 110: The state of Symfony2 - SymfonyDay 2010

Symfony2: The Web Operating System?

http://www.flickr.com/photos/declanjewell/2687934284

Kernel

Events

Proxy

Firewall

Bundles

Page 111: The state of Symfony2 - SymfonyDay 2010

Questions?

Page 112: The state of Symfony2 - SymfonyDay 2010