Slide 1

Slide 1 text

State of the Symfony World FabienPotencier fabpot h﬙ps:/ /secure.flickr.com/photos/abufaiqa/4408154571

Slide 2

Slide 2 text

Twig 1.7M downloads

Slide 3

Slide 3 text

1.5M downloads

Slide 4

Slide 4 text

~21M downloads

Slide 5

Slide 5 text

Console Event Dispatcher Finder HTTP Foundation HTTP Kernel Yaml Process Routing Translation Dom Crawler Filesystem CSS Selector Browser Kit ICU Debug

Slide 6

Slide 6 text

easybook Sulu CMF

Slide 7

Slide 7 text

The Symfony Family https://secure.flickr.com/photos/65073487@N00/3132301417

Slide 8

Slide 8 text

h﬙p:/ /symfony.com/components

Slide 9

Slide 9 text

h﬙p:/ /symfony.com/components/H﬙pKernel

Slide 10

Slide 10 text

h﬙p:/ /symfony.com/projects

Slide 11

Slide 11 text

h﬙p:/ /symfony.com/projects/phpbb

Slide 12

Slide 12 text

Add your project to the SymfonyFamily today! h﬙ps:/ /github.com/symfony/symfony-marketing/tree/component/projects 40+ projects https://secure.flickr.com/photos/kismihok/2894418909

Slide 13

Slide 13 text

2.4 1200+ commits

Slide 14

Slide 14 text

h﬙p:/ /symfony.com/roadmap

Slide 15

Slide 15 text

2.4 30+ new/improved features

Slide 16

Slide 16 text

Form Panel in the Web Profiler Limiting Session Metadata Writes Quicker Access to the Profiler when working on an API A more powerful image validator Flushing stdout and stderr on a Process Easier debugging of not-found resources Using Constants for HTTP Status Code Disabling internal Validation of DomCrawler ChoiceFormFields Dumping the default Configuration for an Extension Be﬙er Console Integration with third-par﬚ Tools Namespaces auto-discovery in DowCrawler A be﬙er Callback constraint Console improvements Restrict Securi﬚ Firewalls to specific Hosts Limit a Process Run with an idle Timeout A Stopwatch Tag for Twig Be﬙er Error Messages for missing Classes and Functions Show logs in console Customize the Securi﬚ Features with ease h﬙p:/ /symfony.com/blog/category/living-on-the-edge

Slide 17

Slide 17 text

No content

Slide 18

Slide 18 text

2.4 2 big features

Slide 19

Slide 19 text

2.4 Expression Language Request Stack

Slide 20

Slide 20 text

Expression Language https://secure.flickr.com/photos/sergiu_bacioiu/3930657923

Slide 21

Slide 21 text

foo.bar foo.getBar() foo['bar']

Slide 22

Slide 22 text

$language = new ExpressionLanguage(); echo $language->evaluate('1 + 1'); // will echo 2 echo $language->compile('1 + 2'); // will echo "(1 + 2)"

Slide 23

Slide 23 text

not foo or bar foo in ['foo', 'bar'] foo ? true : false foo matches "/^foo/i"

Slide 24

Slide 24 text

http://www.flickr.com/photos/doug88888/4561376850

Slide 25

Slide 25 text

class Foo { public function __construct($locale) { $this->locale = $locale; } }

Slide 26

Slide 26 text

acme.locale: class: Symfony\Component\HttpFoundation\Request factory_service: request factory_method: getLocale

Slide 27

Slide 27 text

$c->register('foo', 'Foo')->addArgument( new Expression('container.get("request").getLocale()') ); container.get("request").getLocale()

Slide 28

Slide 28 text

$c->register('foo', 'Foo')->addArgument( new Expression('service("request").getLocale()') ); $c->register('foo', 'Foo')->addArgument( new Expression( 'service("request").getLocale(parameter("def_locale"))' ));

Slide 29

Slide 29 text

$this->get("request")->getLocale( $this->getParameter("def_locale") )

Slide 30

Slide 30 text

http://www.flickr.com/photos/21496790@N06/5065834411

Slide 31

Slide 31 text

access_control: - path: ^/_internal roles: IS_AUTHENTICATED_ANONYMOUSLY ip: 127.0.0.1 - path: ^/_internal roles: ROLE_NO_ACCESS access_control: - path: ^/_internal roles: IS_AUTHENTICATED_ANONYMOUSLY ip: 127.0.0.1

Slide 32

Slide 32 text

access_control: - path: ^/_internal/secure allow_if: "'127.0.0.1' == request.getClientIp()"

Slide 33

Slide 33 text

'127.0.0.1' == request.getClientIp() or has_role('ROLE_ADMIN')

Slide 34

Slide 34 text

/** * @Route("/post/{id}") * @Security("has_role('ROLE_ADMIN')") */ public function showAction(Post $post) { }

Slide 35

Slide 35 text

/** * @Route("/post/{id}") * @Cache(smaxage="15") */ public function showAction(Request $request, Post $post) { $response = new Response(); $response->setLastModified($post->getUpdated()); if ($response->isNotModified($request)) { return $response; } // ... }

Slide 36

Slide 36 text

/** * @Route("/post/{id}") * @Cache(smaxage="15", lastModified="post.getUpdatedAt()") */ public function showAction(Post $post) { // ... }

Slide 37

Slide 37 text

http://www.flickr.com/photos/bootbearwdc/234526475

Slide 38

Slide 38 text

hello: path: /hello/{name} condition: "request.getMethod() in ['GET', 'HEAD'] and request.headers.get('User-Agent') matches '/firefox/i'"

Slide 39

Slide 39 text

// hello if ( 0 === strpos($pathinfo, '/hello') && preg_match('#^/hello/(?P[^/]++)$#s', $pathinfo, $matches) && (in_array($context->getMethod(), array("GET", "HEAD")) && preg_match("/firefox/i", $request->headers- >get("User-Agent")))) { }

Slide 40

Slide 40 text

http://www.flickr.com/photos/xfile001/5249936929

Slide 41

Slide 41 text

/** * @Assert\Expression( * "value <= this.getMaxNumberOfLoginAttempts()", * message="Too many login attempts." * ) */ private $loginAttempts;

Slide 42

Slide 42 text

# Get the special price if user.getGroup() in ['good_customers', 'collaborator'] # Promote article to the homepage when article.commentCount > 100 and article.category not in ["misc"] # Send an alert when product.stock < 15

Slide 43

Slide 43 text

The Request Stack https://secure.flickr.com/photos/kemped/3705729840

Slide 44

Slide 44 text

What is a scope? What is a strict service? What is a synchronized service?

Slide 45

Slide 45 text

Master Request {{ render(controller('a:b:c')) }} Sub-Request

Slide 46

Slide 46 text

Request Response response Call Controller response? expection Sub-Request terminate controller view resolve controller resolve arguments request exception “sub-response” content

Slide 47

Slide 47 text

Call Controller Request Response response response? expection Sub-Request terminate controller view resolve controller resolve arguments request exception “sub-response” content

Slide 48

Slide 48 text

class FooService { public function __construct(Request $request) { $this->request = $request; } public function doSomething() { $this->request->...(); } }

Slide 49

Slide 49 text

class FooService { public function __construct(ContainerInterface $container) { $this->container = $container; } public function doSomething() { $this->container->get('request')->...(); } }

Slide 50

Slide 50 text

Inject the dependencies Not the Container Pro Tip #1

Slide 51

Slide 51 text

Scopes Strict services Synchronized services

Slide 52

Slide 52 text

No content

Slide 53

Slide 53 text

How can I depend on the Request in my services?

Slide 54

Slide 54 text

use Symfony\Component\HttpFoundation\RequestStack; class FooService { public function __construct(RequestStack $requestStack) { $this->requestStack = $requestStack; } public function doSomething() { $this->requestStack->getCurrentRequest()->...(); } }

Slide 55

Slide 55 text

$requestStack->getCurrentRequest()

Slide 56

Slide 56 text

class FooController { public function indexAction(Request $request) { $request->...(); } } class FooListener { public function onKernelRequest(GetResponseEvent $event) { $event->getRequest()->...(); } }

Slide 57

Slide 57 text

Inject the Request Stack Not the Request Pro Tip #2

Slide 58

Slide 58 text

3.0

Slide 59

Slide 59 text

Silex 2.0 h﬙ps:/ /github.com/silexphp/Silex/tree/2.0-experimental

Slide 60

Slide 60 text

SensioLabsInsight insight.sensiolabs.com

Slide 61

Slide 61 text

h﬙p:/ /awards.symfony.com/

Slide 62

Slide 62 text

No content

Slide 63

Slide 63 text

!ank y"!