Robert Lemke


Fluent Development With
FLOW3 1.0
Robert Lemke

chief "architect" of TYPO3 5.0 and FLOW3

co-founder of the TYPO3 Association

35 years old

lives in Lübeck, Germany

1 wife, 1 daughter, 1 espresso machine

likes drumming
At a Glance

FLOW3 is a web application framework
 • brings PHP development to a new level



 • made for PHP 5.3, full namespaces support

 • modular, extensible, package based

 • free & Open Source (LGPL v3)

 • backed by one of the largest Open Source projects

   with 6000+ contributors
Foundation for the Next Generation


TYPO3 5.0 is the all-new
Enterprise CMS
 • content repository, workspaces,
   versions, i18n, ExtJS based UI ...

 • powered by FLOW3

 • compatible code base

 • use TYPO3 features in FLOW3
   standalone apps as you like
Work in Progress



            WARNING

           The current documen
                                 tation of FLOW3 does
           cover the version in                         not
                                our Git master – a lo
           changed since the la                       t has
                                st alpha release!
           We are currently upd
                                 ating the manuals an
           tutorials for the 1.0 b                     d
                                   eta release though.
Hello World!

Package.php


   <?php
   namespace F3Demo;

   use F3FLOW3PackagePackage as BasePackage;

   class Package extends BasePackage {
   }




   $ ./flow3_dev flow3:package:create Demo
Hello World!

StandardController.php

   <?php
   namespace F3DemoController;

   use F3FLOW3MVCControllerActionController;

   class StandardController extends ActionController {
   	
   	 /**
   	   * @param string $name
   	   * @return string
   	   */
   	 public function indexAction($name) {
   	 	 return "Hello $name!";
   	 }
   }

   ?>
Hello World!

http://dev.flow3.rob/demo/standard/index?name=Robert



 Hello Robert!
Tackling the Heart of Software Development

                                         /**
Domain-Driven Design                      * Paper submmited by
                                          *
                                                               a speaker

                                          * @scope prototype
                                          * @entity
A methodology which ...                   */
                                        class Paper {

 • results in rich domain models        	    /**
                                        	     * @var Participant
                                        	     */
 • provides a common language           	    protected $author;

   across the project team          	       /**
                                    	        * @var string
                                    	        */
 • simplify the design of complex   	       protected $title;
   applications                     	       /**
                                    	        * @var string
                                    	        */
                                    	       protected $shortAbstra
                                                                   ct;
FLOW3 is the first PHP framework
                                    	       /**
tailored to Domain-Driven Design    	        * @var string
                                    	        */
                                    	       protected $abstract;
Domain-Driven Design
Persistence

Object Persistence in the Flow
 • based on Doctrine 2

 • seamless integration into FLOW3

 • provides all the great Doctrine 2 features

 • uses UUIDs

 • low level persistence API:

   • allows for own, custom persistence
     backends (instead of Doctrine 2)

   • CouchDB is supported natively
Basic Object Persistence




	   	 // Create a new customer and persist it:
	   $customer = new Customer("Robert");
	   $this->customerRepository->add($customer);

	   	 // Find an existing customer:
	   $otherCustomer = $this->customerRepository->findByFirstName("Karsten");
	
	   	 // and delete it:
	   $this->customerRepository->remove($otherCustomer);
Advanced Queries
PostRepository.php
	   /**
	     * Finds most recent posts excluding the given post
	     *
	     * @param F3BlogDomainModelPost $post Post to exclude from result
	     * @param integer $limit The number of posts to return at max
	     * @return array All posts of the $post's blog except for $post
	     */
	   public function findRecentExceptThis(F3BlogDomainModelPost $post, $limit = 20) {
	   	    $query = $this->createQuery();
	   	    $posts = $query->matching($query->equals('blog', $post->getBlog()))
	   	    	    	   ->setOrderings(array('date' => F3FLOW3PersistenceQueryInterface::ORDER_DESCENDING))
	   	    	    	   ->setLimit($limit)
	   	    	    	   ->execute()
	   	    	    	   ->toArray();
	   	    unset($posts[array_search($post, $posts)]);
	   	    return $posts;



	   	   	   // this is an alternative way of doing this when extending the Doctrine 2
	   	   	   // specific repository and using DQL.
	   	   return $this->entityManager
	   	   	   ->createQuery('SELECT p FROM F3BlogDomainModelPost p WHERE p.blog = :blog' .
                           'AND NOT p = :excludedPost ORDER BY p.date DESC')
	   	   	   ->setMaxResults($limit)
	   	   	   ->execute(array('blog' => $post->getBlog(), 'excludedPost' => $post));
	   }
Purely Doctrine 2
       <?php
       namespace MyExample;

       /**
        * @Entity(repositoryClass="BugRepository")
        */
       class Bug {

       	   /**
       	    * @var integer
       	    * @Id
         	 * @Column(type="integer")
       	    * @GeneratedValue
       	    */
            public $id;

       	   /**
       	    * @var string
       	    * @Column(type="string")
       	    */
            public $description;

       	   /**
       	    * @var DateTime
Doctrine 2 in FLOW3
       <?php
       namespace MyExample;

       /**
        * @Entity(repositoryClass="BugRepository")
        */
       class Bug {

       	   /**
       	    * @var integer
       	    * @Id
         	 * @Column(type="integer")
       	    * @GeneratedValue
       	    */
            public $id;

       	   /**
       	    * @var string
       	    * @Column(type="string")
       	    */
            public $description;

       	   /**
       	    * @var DateTime
Purely Doctrine 2

    	    /**
    	     * @var DateTime
    	     * @Column(type="datetime")
    	     */
          public $created;

    	    /**
    	     * @var User
    	     * @ManyToOne(targetEntity="User", inversedBy="assignedBugs")
    	     */
          private $engineer;

    	    /**
    	     * @var DoctrineCommonCollectionsArrayCollection<Product>
    	     * @ManyToMany(targetEntity="Product")
    	     */
          private $products;
    }

    ?>
Doctrine 2 in FLOW3

    	    /**
    	     * @var DateTime
    	     * @Column(type="datetime")
    	     */
          public $created;

    	    /**
    	     * @var User
    	     * @ManyToOne(targetEntity="User", inversedBy="assignedBugs")
    	     */
          private $engineer;

    	    /**
    	     * @var DoctrineCommonCollectionsArrayCollection<Product>
    	     * @ManyToMany(targetEntity="Product")
    	     */
          private $products;
    }

    ?>
Object Management

Dependency Injection
 • a class doesn't create or retrieve the instance
   of another class but get's it injected

 • fosters loosely-coupling and high cohesion

 ‣ more stable, reusable code
Object Management

FLOW3's take on Dependency Injection
 • one of the first PHP implementations
   (started in 2006, improved ever since)

 • object management for the whole lifecycle of all objects

 • no unnecessary configuration if information can be
   gatered automatically (autowiring)

 • intuitive use and no bad magical surprises

 • fast! (like hardcoded or faster)
War
Constructor Injection: Symfony 2                                                   nin
                                                                                       g
                                                                                    (I'm
                                                                                           :m
                                                                                                 igh
                                                                                           no           t co
                                                                                                Sym
                                                                                                    f          nta
                                                                                                     ony
                                                                                                           exp     in     erro
    <?php                                                                                                      ert ..
                                                                                                                     .)       rs
namespace AcmeDemoBundleController;

use   SymfonyBundleFrameworkBundleControllerController;
use   SymfonyComponentHttpFoundationRedirectResponse;
use   SensioBundleFrameworkExtraBundleConfigurationRoute;
use   SensioBundleFrameworkExtraBundleConfigurationTemplate;
use   AcmeDemoBundleGreeterService;

class DemoController extends Controller {
	
	   /**
	    * @var AcmeDemoBundleGreeterService
	    */
	   protected $greeterService;

	     /**
	       * @param AcmeDemoBundleGreeterService
	       */
	     public function __construct($greeterService = NULL) {
	     	    $this->greeterService = $greeterService;
	     }
	
      /**
        * @Route("/hello/{name}", name="_demo_hello")
        */
      public function helloAction($name) {
      	    return new Response('Hello ' . $name, 200, array('Content-Type' => 'text/plain'));
      }
}
War
  Constructor Injection: Symfony 2                                                 nin
                                                                                       g
                                                                                    (I'm
                                                                                           :m
                                                                                                 igh
                                                                                           no           t co
                                                                                                Sym
                                                                                                    f          nta
                                                                                                     ony
                                                                                                           exp     in     erro
                                                                                                               ert ..
                                                                                                                     .)       rs




   <?xml version="1.0" ?>

<container xmlns="http://symfony.com/schema/dic/services"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/
services-1.0.xsd">

    <services>
        <service id="acme.demo.greeterservice" class="AcmeDemoBundleGreeterService" public="false" />
        <service id="acme.demo.democontroller" class="AcmeDemoBundleControllerDemoController">
             <argument type="service" id="acme.demo.greeterservice" />
        </service>
    </services>
</container>
Constructor Injection

    <?php
namespace F3DemoController;

use F3FLOW3MVCControllerActionController;
use F3DemoServiceGreeterService;

class DemoController extends ActionController {
	
	   /**
	    * @var F3DemoServiceGreeterService
	    */
	   protected $greeterService;

	   /**
	     * @param F3DemoServiceGreeterService
	     */
	   public function __construct(F3DemoServiceGreeterService $greeterService) {
	   	    $this->greeterService = $greeterService;
	   }
	
    /**
      * @param string $name
      */
    public function helloAction($name) {
    	
    	     return 'Hello ' . $name;
    }
}
Constructor Injection
Setter Injection

<?php
namespace F3DemoController;

use F3FLOW3MVCControllerActionController;
use F3DemoServiceGreeterService;

class DemoController extends ActionController {
	
	   /**
	    * @var F3DemoServiceGreeterService
	    */
	   protected $greeterService;

	   /**
	     * @param F3DemoServiceGreeterService
	     */
	   public function injectGreeterService(F3DemoServiceGreeterService $greeterService) {
	   	    $this->greeterService = $greeterService;
	   }
	
    /**
      * @param string $name
      */
    public function helloAction($name) {
    	    	   return 'Hello ' . $name;
    }
}
Property Injection

<?php
namespace F3DemoController;

use F3FLOW3MVCControllerActionController;
use F3DemoServiceGreeterService;

class DemoController extends ActionController {
	
	   /**
	     * @var F3DemoServiceGreeterService
	     * @inject
	     */
	   protected $greeterService;
	
    /**
      * @param string $name
      */
    public function helloAction($name) {
    	
    	     return 'Hello ' . $name;
    }
}
Objects.yaml


   F3FLOW3SecurityCryptographyRsaWalletServiceInterface:
     className: F3FLOW3SecurityCryptographyRsaWalletServicePhp
     scope: singleton
     properties:
       keystoreCache:
         object:
           factoryObjectName: F3FLOW3CacheCacheManager
           factoryMethodName: getCache
           arguments:
             1:
                value: FLOW3_Security_Cryptography_RSAWallet
Object Management

FLOW3's take on Dependency Injection
 • one of the first PHP implementations
   (started in 2006, improved ever since)

 • object management for the whole lifecycle of all objects

 • no unnecessary configuration if information can be
   gatered automatically (autowiring)

 • intuitive use and no bad magical surprises

 • fast! (like hardcoded or faster)
Object Management

    class Customer {

	   /**
	    * @inject
	    * @var CustomerNumberGenerator
	    */
	   protected $customerNumberGenerator;

	   ...
}

$customer = new Customer();
Object Management
                                     <?php
                                     declare(ENCODING = 'u
                                                           tf-8');
                                     namespace F3Confere
                                                          nceDomain   ModelConference;
                                    /**
FLOW3 creates proxy classes          * Autogenerated Prox
                                                           y Class
for realizing DI and AOP magic       * @scope prototype
                                     * @entity
                                     */
                                   class Paper extends
 • new operator is supported       F3FLOW3Persistenc
                                                         Paper_Original implem
                                                         eAspectPersistence
                                                                               ents F3FLOW3Object
                                                                              MagicInterface {
                                                                                                     Pr

                                   	     /**
 • proxy classes are created      	
                                   	      * @var string
                                          * @Id
   on the fly                      	
                                  	
                                          * @Column(length="40
                                                               ")
                                          * introduced by F3F
                                                               LOW3PersistenceAsp
                                  	       */                                        ectPersistenceMagic

 • in production context all      	     protected $FLOW3_Per
                                                             sistence_Identifier
                                                                                  = NULL;

   code is static                	      private $FLOW3_AOP_P
                                                             roxy_targetMethodsAn
                                                                                  dGroupedAdvices = ar
                                                                                                       ra
                                 	     private $FLOW3_AOP_P
                                                             roxy_groupedAdviceCh
                                                                                  ains = array();
                                 	     private $FLOW3_AOP_P
                                                            roxy_methodIsInAdvic
                                                                                 eMode = array();

                                 	    /**
                                 	     * Autogenerated Prox
                                                            y Method
                                 	     */
                                 	    public function __co
                                                           nstruct()    {
AOP

Aspect-Oriented Programming
 • programming paradigm

 • separates concerns to improve modularization

 • OOP modularizes concerns into objects

 • AOP modularizes cross-cutting concerns into aspects



 • FLOW3 makes it easy (and possible at all) to use AOP in PHP
AOP
                                 /**
                                  * @aspect
FLOW3 uses AOP for ...            * @introduce
                                  */
                                                  F3FLOW3Pers
                                                                istenceAspec
                                                                              tPersistence
                                class Persist                                               MagicInterfac
                                                enceMagicAspe                                              e, F3FLO
                                                              ct {
 • persistence magic           	
                               	
                                       /**
                                        * @pointcut c
                                                      lassTaggedWit
                               	        */                          h(entity) ||
                                                                                  classTaggedWi
                              	                                                                 th(valueobjec
 • logging                            public functi
                                                     on isEntityOr
                                                                   ValueObject()
                                                                                  {}
                                                                                                               t)

                              	       /**
                             	         * @var string

 • debugging                 	
                             	
                                       * @Id
                                       * @Column(len
                                                     gth="40")
                             	        * @introduce
                                                     F3FLOW3Pers
                            	         */                           istenceAspec
                                                                                 tPersistence
 • security                 	       protected $FL
                                                   OW3_Persisten
                                                                 ce_Identifier
                                                                               ;
                                                                                               MagicAspect->
                                                                                                              isEnti

                           	        /**
                           	         * After retur
                                                    ning advice,
                           	         *                            making sure w
                                                                                e have an UUI
                           	         * @param F3                                            D for each an
                                                    FLOW3AOPJoi                                            d every
                          	         * @return voi                 nPointInterfa
                                                   d                            ce $joinPoint
                          	         * @before cla                                              The current j
                                                   ssTaggedWith(                                              oin po
                          	         */                           entity) && me
                                                                               thod(.*->__co
                         	        public functi                                              nstruct())
                                                  on generateUU
                         	        	      $proxy = $joi          ID(F3FLOW3
                                                       nPoint->getPr          AOPJoinPoint
                         	       	                                   oxy();                 Interface $jo
                                         F3FLOW3Ref                                                     inPoint)
                         	                             lectionObjec
                                 }                                   tAccess::setP
                                                                                   roperty($prox
                                                                                                 y , 'FLOW3_Per
                                                                                                                siste
Security

Touchless Security, Flow-Style
 • security is handled at a central place (through AOP)

 • third-party code is as secure as possible by default

 • modeled after our experiences in the TYPO3 project and
   Spring Security (Java framework)

 • provides authentication, authorization, validation, filtering ...

   • can intercept arbitrary method calls

   • transparently filters content through query-rewriting

 • extensible for new authentication or authorization mechanisms
Security Policy
The Zen of Templating

FLOW3 comes with an elegant, flexible and secure
templating engine: Fluid

 • templates are valid HTML

 • templates contain no PHP

 • object access, control structures, loops ...

 • designer-friendly

 • extensible (view helpers, widgets)
The Zen of Templating
...
<body>
	   <h1>Latest Blog Posts</h1>
	   <f:if condition="{posts}">
	   	   <f:then>
	   	   	   <ol>
	   	   	   	   <f:for each="{posts}" as="post">
	   	   	   	   	   <li class="post">
	   	   	   	   	   	   <h2>
	   	   	   	   	   	   	   <f:link.action action="show" controller="Post" arguments="{post: post}">{post.title}
	   	   	   	   	   	   	   <f:security.ifHasRole role="Editor">
	   	   	   	   	   	   	   	   <f:link.action action="edit" arguments="{post: post}" controller="Post"><img src
	   	   	   	   	   	   	   	   <f:link.action onclick="return confirm('Really delete this post?');" action="del
	   	   	   	   	   	   	   </f:security.ifHasRole>
	   	   	   	   	   	   </h2>
	   	   	   	   	   	   <f:render partial="PostMetaData" arguments="{post: post}"/>
	   	   	   	   	   	   <f:link.action action='show' arguments='{post: post}'>Read more</f:link.action></p>
	   	   	   	   	   </li>
	   	   	   	   </f:for>
	   	   	   </ol>
	   	   </f:then>
	   	   <f:else>
	   	   	   <p>This blog currently doesn't contain any posts.
    	   	      <f:link.action action="new" controller="Post">Create the first post</f:link.action>
            </p>
	   	   </f:else>
	   </f:if>
</f:section>
Forms

 <?php
 namespace F3BlogDomainModel;

 /**
  * A blog post
  *
  * @scope prototype
  * @entity
  */
 class Post {

 	   /**
 	    * @var string
 	    * @validate StringLength(minimum = 1, maximum = 100)
 	    */
 	   protected $title;

 	   /**
 	    * @var string
 	    * @validate StringLength(minimum = 1, maximum = 50)
 	    */
 	   protected $author;
Forms



<h2>Create a new post</h2>

<f:form action="create" object="{newPost}" name="newPost" enctype="multipart/form-data">
	 <label for="title">Title</label><br />
	 <f:form.textbox property="title" id="title" /><br />

	   <label for="content">Content</label><br />
	   <f:form.textarea property="content" rows="5" cols="40" id="content" /><br />

	 <label for="image">Image resource</label><br />
	 <f:form.textbox property="image.title" value="My image title" />
	 <f:form.upload property="image.originalResource" />
</f:form>
Forms

<?php
namespace F3BlogController;
use F3FLOW3MVCControllerActionController;

class PostController extends ActionController {

	    /**
	     * @inject
	     * @var F3BlogDomainRepositoryPostRepository
	     */
	    protected $postRepository;

	    /**
	      * Creates a new post
	      *
	      * @param F3BlogDomainModelPost $newPostadded to the repository
	      * @return void
	      */
	    public function createAction(F3BlogDomainModelPost $newPost) {
	    	 $this->blog->addPost($newPost);
	    	 $this->flashMessageContainer->add('Your new post was created.');
	    	 $this->redirect('index');
	    }
Speed and Performance

For the snappy user experience:

 • multi-layered, tagged caches

 • various cache backends (file, Memcached, APC, Redis, PDO, ...)

 • reverse-proxy support (Varnish, ESI) in the works

 • code compilation

 • regular benchmarks

 • focus on good scalibility
More Features

Command Line Support
(including interactive shell!)
More Features

 • Resource Management (CDNs, private resources, ...)

 • Logging

 • Caching

 • Signal Slot event handling

 • File Monitoring

 • Configuration Management

 • Routing

 • REST / SOAP

 • ...
Roadmap

http://forge.typo3.org/projects/flow3-distribution-base/roadmap
Live Projects?
Thank You!

 • These slides: http://slideshare.net/robertlemke

 • Download FLOW3: http://flow3.typo3.org

 • Follow me on Twitter: @t3rob

 • Give me feedback:

   • robert@typo3.org

   • http://joind.in/3492

Fluent Development with FLOW3 1.0

  • 1.
  • 2.
    Robert Lemke chief "architect"of TYPO3 5.0 and FLOW3 co-founder of the TYPO3 Association 35 years old lives in Lübeck, Germany 1 wife, 1 daughter, 1 espresso machine likes drumming
  • 3.
    At a Glance FLOW3is a web application framework • brings PHP development to a new level • made for PHP 5.3, full namespaces support • modular, extensible, package based • free & Open Source (LGPL v3) • backed by one of the largest Open Source projects with 6000+ contributors
  • 4.
    Foundation for theNext Generation TYPO3 5.0 is the all-new Enterprise CMS • content repository, workspaces, versions, i18n, ExtJS based UI ... • powered by FLOW3 • compatible code base • use TYPO3 features in FLOW3 standalone apps as you like
  • 5.
    Work in Progress WARNING The current documen tation of FLOW3 does cover the version in not our Git master – a lo changed since the la t has st alpha release! We are currently upd ating the manuals an tutorials for the 1.0 b d eta release though.
  • 6.
    Hello World! Package.php <?php namespace F3Demo; use F3FLOW3PackagePackage as BasePackage; class Package extends BasePackage { } $ ./flow3_dev flow3:package:create Demo
  • 7.
    Hello World! StandardController.php <?php namespace F3DemoController; use F3FLOW3MVCControllerActionController; class StandardController extends ActionController { /** * @param string $name * @return string */ public function indexAction($name) { return "Hello $name!"; } } ?>
  • 8.
  • 9.
    Tackling the Heartof Software Development /** Domain-Driven Design * Paper submmited by * a speaker * @scope prototype * @entity A methodology which ... */ class Paper { • results in rich domain models /** * @var Participant */ • provides a common language protected $author; across the project team /** * @var string */ • simplify the design of complex protected $title; applications /** * @var string */ protected $shortAbstra ct; FLOW3 is the first PHP framework /** tailored to Domain-Driven Design * @var string */ protected $abstract;
  • 10.
  • 11.
    Persistence Object Persistence inthe Flow • based on Doctrine 2 • seamless integration into FLOW3 • provides all the great Doctrine 2 features • uses UUIDs • low level persistence API: • allows for own, custom persistence backends (instead of Doctrine 2) • CouchDB is supported natively
  • 12.
    Basic Object Persistence // Create a new customer and persist it: $customer = new Customer("Robert"); $this->customerRepository->add($customer); // Find an existing customer: $otherCustomer = $this->customerRepository->findByFirstName("Karsten"); // and delete it: $this->customerRepository->remove($otherCustomer);
  • 13.
    Advanced Queries PostRepository.php /** * Finds most recent posts excluding the given post * * @param F3BlogDomainModelPost $post Post to exclude from result * @param integer $limit The number of posts to return at max * @return array All posts of the $post's blog except for $post */ public function findRecentExceptThis(F3BlogDomainModelPost $post, $limit = 20) { $query = $this->createQuery(); $posts = $query->matching($query->equals('blog', $post->getBlog())) ->setOrderings(array('date' => F3FLOW3PersistenceQueryInterface::ORDER_DESCENDING)) ->setLimit($limit) ->execute() ->toArray(); unset($posts[array_search($post, $posts)]); return $posts; // this is an alternative way of doing this when extending the Doctrine 2 // specific repository and using DQL. return $this->entityManager ->createQuery('SELECT p FROM F3BlogDomainModelPost p WHERE p.blog = :blog' . 'AND NOT p = :excludedPost ORDER BY p.date DESC') ->setMaxResults($limit) ->execute(array('blog' => $post->getBlog(), 'excludedPost' => $post)); }
  • 14.
    Purely Doctrine 2 <?php namespace MyExample; /** * @Entity(repositoryClass="BugRepository") */ class Bug { /** * @var integer * @Id * @Column(type="integer") * @GeneratedValue */ public $id; /** * @var string * @Column(type="string") */ public $description; /** * @var DateTime
  • 15.
    Doctrine 2 inFLOW3 <?php namespace MyExample; /** * @Entity(repositoryClass="BugRepository") */ class Bug { /** * @var integer * @Id * @Column(type="integer") * @GeneratedValue */ public $id; /** * @var string * @Column(type="string") */ public $description; /** * @var DateTime
  • 16.
    Purely Doctrine 2 /** * @var DateTime * @Column(type="datetime") */ public $created; /** * @var User * @ManyToOne(targetEntity="User", inversedBy="assignedBugs") */ private $engineer; /** * @var DoctrineCommonCollectionsArrayCollection<Product> * @ManyToMany(targetEntity="Product") */ private $products; } ?>
  • 17.
    Doctrine 2 inFLOW3 /** * @var DateTime * @Column(type="datetime") */ public $created; /** * @var User * @ManyToOne(targetEntity="User", inversedBy="assignedBugs") */ private $engineer; /** * @var DoctrineCommonCollectionsArrayCollection<Product> * @ManyToMany(targetEntity="Product") */ private $products; } ?>
  • 18.
    Object Management Dependency Injection • a class doesn't create or retrieve the instance of another class but get's it injected • fosters loosely-coupling and high cohesion ‣ more stable, reusable code
  • 19.
    Object Management FLOW3's takeon Dependency Injection • one of the first PHP implementations (started in 2006, improved ever since) • object management for the whole lifecycle of all objects • no unnecessary configuration if information can be gatered automatically (autowiring) • intuitive use and no bad magical surprises • fast! (like hardcoded or faster)
  • 20.
    War Constructor Injection: Symfony2 nin g (I'm :m igh no t co Sym f nta ony exp in erro <?php ert .. .) rs namespace AcmeDemoBundleController; use SymfonyBundleFrameworkBundleControllerController; use SymfonyComponentHttpFoundationRedirectResponse; use SensioBundleFrameworkExtraBundleConfigurationRoute; use SensioBundleFrameworkExtraBundleConfigurationTemplate; use AcmeDemoBundleGreeterService; class DemoController extends Controller { /** * @var AcmeDemoBundleGreeterService */ protected $greeterService; /** * @param AcmeDemoBundleGreeterService */ public function __construct($greeterService = NULL) { $this->greeterService = $greeterService; } /** * @Route("/hello/{name}", name="_demo_hello") */ public function helloAction($name) { return new Response('Hello ' . $name, 200, array('Content-Type' => 'text/plain')); } }
  • 21.
    War ConstructorInjection: Symfony 2 nin g (I'm :m igh no t co Sym f nta ony exp in erro ert .. .) rs <?xml version="1.0" ?> <container xmlns="http://symfony.com/schema/dic/services" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/ services-1.0.xsd"> <services> <service id="acme.demo.greeterservice" class="AcmeDemoBundleGreeterService" public="false" /> <service id="acme.demo.democontroller" class="AcmeDemoBundleControllerDemoController"> <argument type="service" id="acme.demo.greeterservice" /> </service> </services> </container>
  • 22.
    Constructor Injection <?php namespace F3DemoController; use F3FLOW3MVCControllerActionController; use F3DemoServiceGreeterService; class DemoController extends ActionController { /** * @var F3DemoServiceGreeterService */ protected $greeterService; /** * @param F3DemoServiceGreeterService */ public function __construct(F3DemoServiceGreeterService $greeterService) { $this->greeterService = $greeterService; } /** * @param string $name */ public function helloAction($name) { return 'Hello ' . $name; } }
  • 23.
  • 24.
    Setter Injection <?php namespace F3DemoController; useF3FLOW3MVCControllerActionController; use F3DemoServiceGreeterService; class DemoController extends ActionController { /** * @var F3DemoServiceGreeterService */ protected $greeterService; /** * @param F3DemoServiceGreeterService */ public function injectGreeterService(F3DemoServiceGreeterService $greeterService) { $this->greeterService = $greeterService; } /** * @param string $name */ public function helloAction($name) { return 'Hello ' . $name; } }
  • 25.
    Property Injection <?php namespace F3DemoController; useF3FLOW3MVCControllerActionController; use F3DemoServiceGreeterService; class DemoController extends ActionController { /** * @var F3DemoServiceGreeterService * @inject */ protected $greeterService; /** * @param string $name */ public function helloAction($name) { return 'Hello ' . $name; } }
  • 26.
    Objects.yaml F3FLOW3SecurityCryptographyRsaWalletServiceInterface: className: F3FLOW3SecurityCryptographyRsaWalletServicePhp scope: singleton properties: keystoreCache: object: factoryObjectName: F3FLOW3CacheCacheManager factoryMethodName: getCache arguments: 1: value: FLOW3_Security_Cryptography_RSAWallet
  • 27.
    Object Management FLOW3's takeon Dependency Injection • one of the first PHP implementations (started in 2006, improved ever since) • object management for the whole lifecycle of all objects • no unnecessary configuration if information can be gatered automatically (autowiring) • intuitive use and no bad magical surprises • fast! (like hardcoded or faster)
  • 28.
    Object Management class Customer { /** * @inject * @var CustomerNumberGenerator */ protected $customerNumberGenerator; ... } $customer = new Customer();
  • 29.
    Object Management <?php declare(ENCODING = 'u tf-8'); namespace F3Confere nceDomain ModelConference; /** FLOW3 creates proxy classes * Autogenerated Prox y Class for realizing DI and AOP magic * @scope prototype * @entity */ class Paper extends • new operator is supported F3FLOW3Persistenc Paper_Original implem eAspectPersistence ents F3FLOW3Object MagicInterface { Pr /** • proxy classes are created * @var string * @Id on the fly * @Column(length="40 ") * introduced by F3F LOW3PersistenceAsp */ ectPersistenceMagic • in production context all protected $FLOW3_Per sistence_Identifier = NULL; code is static private $FLOW3_AOP_P roxy_targetMethodsAn dGroupedAdvices = ar ra private $FLOW3_AOP_P roxy_groupedAdviceCh ains = array(); private $FLOW3_AOP_P roxy_methodIsInAdvic eMode = array(); /** * Autogenerated Prox y Method */ public function __co nstruct() {
  • 30.
    AOP Aspect-Oriented Programming •programming paradigm • separates concerns to improve modularization • OOP modularizes concerns into objects • AOP modularizes cross-cutting concerns into aspects • FLOW3 makes it easy (and possible at all) to use AOP in PHP
  • 31.
    AOP /** * @aspect FLOW3 uses AOP for ... * @introduce */ F3FLOW3Pers istenceAspec tPersistence class Persist MagicInterfac enceMagicAspe e, F3FLO ct { • persistence magic /** * @pointcut c lassTaggedWit */ h(entity) || classTaggedWi th(valueobjec • logging public functi on isEntityOr ValueObject() {} t) /** * @var string • debugging * @Id * @Column(len gth="40") * @introduce F3FLOW3Pers */ istenceAspec tPersistence • security protected $FL OW3_Persisten ce_Identifier ; MagicAspect-> isEnti /** * After retur ning advice, * making sure w e have an UUI * @param F3 D for each an FLOW3AOPJoi d every * @return voi nPointInterfa d ce $joinPoint * @before cla The current j ssTaggedWith( oin po */ entity) && me thod(.*->__co public functi nstruct()) on generateUU $proxy = $joi ID(F3FLOW3 nPoint->getPr AOPJoinPoint oxy(); Interface $jo F3FLOW3Ref inPoint) lectionObjec } tAccess::setP roperty($prox y , 'FLOW3_Per siste
  • 32.
    Security Touchless Security, Flow-Style • security is handled at a central place (through AOP) • third-party code is as secure as possible by default • modeled after our experiences in the TYPO3 project and Spring Security (Java framework) • provides authentication, authorization, validation, filtering ... • can intercept arbitrary method calls • transparently filters content through query-rewriting • extensible for new authentication or authorization mechanisms
  • 33.
  • 34.
    The Zen ofTemplating FLOW3 comes with an elegant, flexible and secure templating engine: Fluid • templates are valid HTML • templates contain no PHP • object access, control structures, loops ... • designer-friendly • extensible (view helpers, widgets)
  • 35.
    The Zen ofTemplating ... <body> <h1>Latest Blog Posts</h1> <f:if condition="{posts}"> <f:then> <ol> <f:for each="{posts}" as="post"> <li class="post"> <h2> <f:link.action action="show" controller="Post" arguments="{post: post}">{post.title} <f:security.ifHasRole role="Editor"> <f:link.action action="edit" arguments="{post: post}" controller="Post"><img src <f:link.action onclick="return confirm('Really delete this post?');" action="del </f:security.ifHasRole> </h2> <f:render partial="PostMetaData" arguments="{post: post}"/> <f:link.action action='show' arguments='{post: post}'>Read more</f:link.action></p> </li> </f:for> </ol> </f:then> <f:else> <p>This blog currently doesn't contain any posts. <f:link.action action="new" controller="Post">Create the first post</f:link.action> </p> </f:else> </f:if> </f:section>
  • 36.
    Forms <?php namespaceF3BlogDomainModel; /** * A blog post * * @scope prototype * @entity */ class Post { /** * @var string * @validate StringLength(minimum = 1, maximum = 100) */ protected $title; /** * @var string * @validate StringLength(minimum = 1, maximum = 50) */ protected $author;
  • 37.
    Forms <h2>Create a newpost</h2> <f:form action="create" object="{newPost}" name="newPost" enctype="multipart/form-data"> <label for="title">Title</label><br /> <f:form.textbox property="title" id="title" /><br /> <label for="content">Content</label><br /> <f:form.textarea property="content" rows="5" cols="40" id="content" /><br /> <label for="image">Image resource</label><br /> <f:form.textbox property="image.title" value="My image title" /> <f:form.upload property="image.originalResource" /> </f:form>
  • 38.
    Forms <?php namespace F3BlogController; use F3FLOW3MVCControllerActionController; classPostController extends ActionController { /** * @inject * @var F3BlogDomainRepositoryPostRepository */ protected $postRepository; /** * Creates a new post * * @param F3BlogDomainModelPost $newPostadded to the repository * @return void */ public function createAction(F3BlogDomainModelPost $newPost) { $this->blog->addPost($newPost); $this->flashMessageContainer->add('Your new post was created.'); $this->redirect('index'); }
  • 39.
    Speed and Performance Forthe snappy user experience: • multi-layered, tagged caches • various cache backends (file, Memcached, APC, Redis, PDO, ...) • reverse-proxy support (Varnish, ESI) in the works • code compilation • regular benchmarks • focus on good scalibility
  • 40.
    More Features Command LineSupport (including interactive shell!)
  • 41.
    More Features •Resource Management (CDNs, private resources, ...) • Logging • Caching • Signal Slot event handling • File Monitoring • Configuration Management • Routing • REST / SOAP • ...
  • 42.
  • 43.
  • 44.
    Thank You! •These slides: http://slideshare.net/robertlemke • Download FLOW3: http://flow3.typo3.org • Follow me on Twitter: @t3rob • Give me feedback: • robert@typo3.org • http://joind.in/3492