SlideShare a Scribd company logo
1 of 94
Download to read offline
San Francisco, USA


Karsten Dambekalns & Robert Lemke




Fluent Development
with FLOW3
San Francisco, USA



Karsten Dambekalns

co-lead of TYPO3 5.0 and FLOW3

34 years old

lives in Lübeck, Germany

1 wife, 3 sons, 1 espresso machine

likes canoeing
San Francisco, USA



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
San Francisco, USA



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
San Francisco, USA



 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
San Francisco, USA



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.
San Francisco, USA



Check Out from Git – Stable State




$ git clone --recursive git://git.typo3.org/FLOW3/Distributions/Base.git .
Cloning into ....
remote: Counting objects: 3837, done.
remote: Compressing objects: 100% (2023/2023), done.
remote: Total 3837 (delta 2007), reused 2721 (delta 1465)
Receiving objects: 100% (3837/3837), 3.49 MiB | 28 KiB/s, done.
Resolving deltas: 100% (2007/2007), done.
San Francisco, USA



Set File Permissions



$ ./Packages/Framework/FLOW3/Scripts/setfilepermissions.sh robert _www _www
FLOW3 File Permission Script

Checking permissions from here upwards ...
 (if a password prompt appears it's from sudo)
Password:

Making sure Data and Web/_Resources exist ...
Setting file permissions, this might take a minute ...

$
San Francisco, USA



Set Up Database
Configuration/Settings.yaml


 #                                                                              #
 # Global Settings                                                              #
 #                                                                              #

 FLOW3:
   persistence:
     backendOptions:
        driver: 'pdo_mysql'
        dbname: 'blog'
        user: 'bloguser'
        password: 'blogpassword'
        host: '127.0.0.1'
        path: '127.0.0.1'
        port: 3306
     doctrine:
        dbal:
          sessionInitialization: 'SET NAMES utf8 COLLATE utf8_unicode_ci'
San Francisco, USA



Set Up Virtual Host

Apache Virtual Host



  <VirtualHost *:80>
       DocumentRoot /opt/local/apache2/htdocs/Talks/FLOW3/Web/
       ServerName dev.flow3.rob
       SetEnv FLOW3_CONTEXT Development
  </VirtualHost>

  <VirtualHost *:80>
       DocumentRoot /opt/local/apache2/htdocs/Talks/FLOW3/Web/
       ServerName flow3.rob
       SetEnv FLOW3_CONTEXT Production
  </VirtualHost>
San Francisco, USA



Final Check
San Francisco, USA



Update from Git to Latest State


$ git submodule foreach "git checkout master"

-✂-----✂-----✂-----✂-----✂-----✂-----✂-----✂-----✂-----✂-----✂-----✂-

$ git submodule foreach "git pull --rebase"

Entering 'Build/Common'
First, rewinding head to replay your work on top of it...
Fast-forwarded master to 6f27f1784240b414e966ce0e5a12e23cb2f7ab02.
Entering 'Packages/Application/TYPO3'
First, rewinding head to replay your work on top of it...
Fast-forwarded master to 5187430ee44d579ae2bac825e2a069c4cd3f38a4.
Entering 'Packages/Application/TYPO3CR'
First, rewinding head to replay your work on top of it...
Fast-forwarded master to b1f5331aa51d390fa3d973404f31b9fd773f7059.
Entering 'Packages/Application/Twitter'
Current branch master is up to date.
…
San Francisco, USA



Hello World!

Package.php


   <?php
   namespace F3Demo;

   use F3FLOW3PackagePackage as BasePackage;

   class Package extends BasePackage {
   }



Today:

   $ ./flow3_dev flow3:package:create --package-key Demo



Soon:

   $ ./flow3_dev flow3:package:create Demo
L i ve H ac k ing

 5        1                1   1
        K. Damb ek aln s & R. Lem ke
        D.P. F l u x t r
       time ();
San Francisco, USA



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!";
   	 }
   }

   ?>
San Francisco, USA



Hello World!

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



 Hello Robert!
San Francisco, USA



Tackling the Heart of Software Development

                                         /**
Domain-Driven Design                      * Paper submitted 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;
San Francisco, USA



Domain-Driven Design

Domain
 activity or business of the user

Domain-Driven Design
 is about

 • focussing on the domain and domain logic

 • accurately mapping the concepts to software

 • forming a ubiquitous language among the
   project members
San Francisco, USA



Domain-Driven Design

Ubiquitous Language
 • important prerequisite for successful
   collaboration

 • use the same words for

   • discussion

   • modeling

   • development

   • documentation
San Francisco, USA



Domain: Conference
Ex t re me Mo de li ng

 5        2                1   1
       K. Damb ek aln s & R. Lem ke
        D.P. F l u x t r
       time ();
San Francisco, USA



Example Model: Paper

    /**
 * A Paper
 *
 * @scope prototype
 * @entity
 */
class Paper {

	   /**
	    * @var F3ConferenceDomainModelAccountParticipant
	    * @ManyToOne(cascade={"persist"})
	    * @validate NotEmpty
	    */
	   protected $author;

	   /**
	    * @var string
	    * @validate StringLength(minimum = 1, maximum = 50)
	    */
	   protected $title;
San Francisco, USA



Example Model: Paper

    	   /**
	    * @var string
	    * @Column(type="text")
	    * @validate StringLength(minimum = 30, maximum = 150)
	    */
	   protected $shortAbstract;

	   /**
	    * @var string
	    * @Column(type="text")
	    * @validate StringLength(minimum = 100, maximum = 1000)
	    */
	   protected $abstract;

	   /**
	    * @var F3ConferenceDomainModelConferenceSessionType
	    * @ManyToOne(cascade={"persist"})
	    * @validate NotEmpty
	    */
	   protected $proposedSessionType;
San Francisco, USA



Example Model: Paper

    	   /**
	    * @var F3ConferenceDomainModelConferenceTrack
	    * @ManyToOne(cascade={"persist"})
	    * @validate NotEmpty
	    */
	   protected $proposedTrack;

	   /**
	    * @var DoctrineCommonCollectionsArrayCollection<F3ConferenceDomainModelComment>
	    * @ManyToMany(cascade={"persist", "remove"})
	    */
	   protected $comments;

	   /**
	    * @var string
	    */
	   protected $slideShareUrl;

	   /**
	    * @var string
	    */
	   protected $tags;
San Francisco, USA



Example Model: Paper

    	   /**
	    * @var string
	    * @Column(type="text", nullable=true)
	    */
	   protected $links;

	   /**
	    * @var DoctrineCommonCollectionsArrayCollection<F3ConferenceDomainModelAccount
Participant>
	    * @ManyToMany(cascade={"all"})
	    */
	   protected $speakers;

	   /**
	    * one of the STATUS_* constants
	    * @var string
	    */
	   protected $status = self::STATUS_DRAFT;
San Francisco, USA



Example Model: Paper

    	   /**
	    * STATUS_* constants
	    */
	   const STATUS_DRAFT = 'draft';
	   const STATUS_SUBMITTED = 'submitted';
	   const STATUS_REJECTED = 'rejected';
	   const STATUS_ACCEPTED = 'accepted';
	   const STATUS_SCHEDULED = 'scheduled';

	   public function __construct() {
	   	   $this->comments = new DoctrineCommonCollectionsArrayCollection();
	   	   $this->speakers = new DoctrineCommonCollectionsArrayCollection();
	   }

	   /**
	     * @param F3ConferenceDomainModelAccountParticipant $author
	     * @return void
	     */
	   public function setAuthor(F3ConferenceDomainModelAccountParticipant $author) {
	   	    $this->author = $author;
	   }

	   /**
	    * @return F3ConferenceDomainModelAccountParticipant
	    */
	   public function getAuthor() {
San Francisco, USA



Domain-Driven Design
San Francisco, USA



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
San Francisco, USA



    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);
San Francisco, USA



    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));
	   }
San Francisco, USA



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
San Francisco, USA



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
San Francisco, USA



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;
    }

    ?>
San Francisco, USA



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;
    }

    ?>
San Francisco, USA



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
San Francisco, USA



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
   gathered automatically (autowiring)

 • intuitive use and no bad magical surprises

 • fast! (like hardcoded or faster)
San Francisco, USA

                                                                               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'));
      }
}
San Francisco, USA

                                                                               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>
San Francisco, USA



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;
    }
}
San Francisco, USA



Constructor Injection
San Francisco, USA



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;
    }
}
San Francisco, USA



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;
    }
}
San Francisco, USA



Objects.yaml


   F3FLOW3SecurityCryptographyRsaWalletServiceInterface:
     className: F3FLOW3SecurityCryptographyRsaWalletServicePhp
     scope: singleton
     properties:
       keystoreCache:
         object:
           factoryObjectName: F3FLOW3CacheCacheManager
           factoryMethodName: getCache
           arguments:
             1:
                value: FLOW3_Security_Cryptography_RSAWallet
San Francisco, USA



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)
San Francisco, USA



Object Management

    class Customer {

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

	   ...
}

$customer = new Customer();
$customer->getCustomerNumber();
San Francisco, USA



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()    {
Birt h o f a Blo g

 5        3                1   1
        K. Damb ek aln s & R. Lem ke
        D.P. F l u x t r
       time ();
San Francisco, USA



The Zen of Templating

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

 • templates are valid HTML

 • templates contain no PHP code

 • object access, control structures, loops ...

 • designer-friendly

 • extensible (view helpers, widgets)
San Francisco, USA



Fluid


Example for assigning a string to a Fluid variable:

	   	 // in the action controller:
	   $this->view->assign('title', 'Welcome to Fluid');




	   <!-- in the Fluid template: -->
	   <head>
	   	 <title>{title}</title>
	   </head>
San Francisco, USA



Fluid


Variables can also be objects:

	   	 // in the action controller:
	   $this->view->assign('conference', $conference);




	   <!-- in the Fluid template: -->
	   <div class="venue">
	   	 <p>Venue Street: {conference.venue.street}</p>
	   </div>
San Francisco, USA



Fluid


if-then-else:

	   	 // in the action controller:
	   $this->view->assign('post', $blogPost);




	   <!-- in the Fluid template: -->
	   <f:if condition="{post.comments}">
	   	 <f:then>There are some comments.</f:then>
	   	 <f:else>There are no comments.</f:else>		
	   </f:if>
San Francisco, USA



Fluid


for-each:

	   	 // in the action controller:
	   $this->view->assign('ages', array("Karsten" => 34, "Robert" => 35));




	   <!-- in the Fluid template: -->
	   <ul>
	   	 <f:for each="{ages}" as="age" key="name">
	   	 	 <li>{name} is {age} year old.</li>
	   	 </f:for>
	   </ul>
San Francisco, USA



Fluid


for-each:

	   	 // in the action controller:
	   $this->view->assign('post', $blogPost);




	   <!-- in the Fluid template: -->
	   <f:if condition="{post.comments}">
	   	 <ul>
	   	 	 <f:for each="{post.comments}" as="comment" >
	   	 	 	 <li>{post.title}</li>
	   	 	 </f:for>
	   	 </ul>	 	 	
	   </f:if>
San Francisco, USA



Fluid


View helpers – in this case the link.action view helper:


	   <!-- in the Fluid template: -->
	   {namespace f=F3FluidViewHelpers}

	   <f:link.action action="delete" arguments="{post: post, really: 'yes'}">
	   	 Delete this post
	   </f:link.action>
F lue n t F lu id

 5         8                1   1
         K. Damb ek aln s & R. Lem ke
         D.P. F l u x t r
        time ();
San Francisco, USA



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;
San Francisco, USA



    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>
San Francisco, USA



    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');
	    }
San Francisco, USA


Karsten Dambekalns & Robert Lemke




Fluent Development
with FLOW3 (PART TWO)
San Francisco, USA



Validation

Validation is about different things

• incoming data needs to be validated for security reasons

 • no evil markup in submitted content

• domain model integrity needs to be ensured

 • an email needs to be (syntactically) valid

 • credit card numbers should consist only of digits
San Francisco, USA



Validation

Validation in FLOW3

• you do not want to code checks into your controllers

• FLOW3 separates validation from your controller’s concerns

 • no PHP code needed for validation

 • declared through annotations
San Francisco, USA



Validation

Validation Models

• BaseProperties
  rules defining the minimum requirements on individual properties of a
  model

• BaseModel
  rules or custom validators enforcing the minimum requirements on the
  combination of properties of a model

• Supplemental
  rules defining additional requirements on a model for a specific
  situation (e.g. a certain action method)
San Francisco, USA



Validation

Base Properties

• Validation rules defined directly at the properties


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

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



Validation

Validators

• validators provided by FLOW3 can be used through their short name

 • Count, Float, NotEmpty, RegularExpression, Uuid, DateTime,
   NumberRange, StringLength, Alphanumeric, Integer, Number, String,
   EmailAddress, Label, Raw, Text

• custom validators need to implement the ValidatorInterface

• use them by specifying the fully qualified class name
 	   /**
 	    * @var DambekalnsStuffDomainModelStuff
 	    * @validate DambekalnsStuffDomainValidatorStuffValidator
 	    */
 	   protected $stuff;
San Francisco, USA



Schema Management

Automatic database updates
• when first running FLOW3 the schema will be created

• when a model has changed, the schema is updated



• be careful with existing data, updates can be destructive

• for production you should manually manage schema changes
San Francisco, USA



Schema Management

Manual database updates
• for simple situations this can be good enough:


$ ./flow3_dev flow3:doctrine:create

$ ./flow3_dev flow3:doctrine:update




• useful when

 • you need to use an existing database dump

 • using SQLite, due to limited schema change functionality
San Francisco, USA



Schema Management

Doctrine 2 Migrations
• Migrations allow schema versioning and
  change deployment

• Migrations are the recommended way for
  DB updates

• Tools to create and deploy migrations are
  integrated with FLOW3
San Francisco, USA



Schema Management

Migrations Workflow
• use schema auto update in early development until your model is
  ready for a first “freeze”, then switch off schema auto update and
  drop your tables

• create migration diff and customize it
$ ./flow3_dev flow3:doctrine:migrationdiff
Generated new migration class to "…/Version20110608074324.php" from schema differences.
$ vi …/Version20110608074324.php




• migrate to create the tables

$ ./flow3_dev flow3:doctrine:migrate
San Francisco, USA



Schema Management

Migrations Workflow

$ ./flow3_dev flow3:doctrine:migrationstatus

 == Configuration
    >> Name:                   Doctrine Database Migrations
    >> Database Driver:        pdo_mysql
    >> Database Name:          blog
    >> Configuration Source:   manually configured
    >> Version Table Name:     flow3_doctrine_migrationstatus
    >> Migrations Namespace:   F3FLOW3PersistenceDoctrineMigrations
    >> Migrations Directory:   /Users/karsten/Sites/blog/Configuration/Doctrine/Migrations
    >> Current Version:        2011-06-08 07:43:24 (20110608074324)
    >> Latest Version:         2011-06-08 07:43:24 (20110608074324)
    >> Executed Migrations:    1
    >> Available Migrations:   1
    >> New Migrations:         0

 == Migration Versions
    >> 2011-06-08 07:43:24 (20110608074324)          migrated
San Francisco, USA



Schema Management

Migrations Workflow
• rinse and repeat: from now on create a new migration whenever
  you changed your model classes

• generated migrations most probably need to be adjusted

 • e.g. renaming a model means renaming a table, not dropping
   and creating

 • data migration needs to be added



• remember: good migrations make your user’s day
S ch e m at ic De mo

 5        8                1   1
       K. Damb ek aln s & R. Lem ke
        D.P. F l u x t r
       time ();
San Francisco, USA



Command Line Support
Sh e b a ng!

 5        8                1   1
        K. Damb ek aln s & R. Lem ke
        D.P. F l u x t r
       time ();
San Francisco, USA



    Command Line Support

<?php
namespace F3FLOW3Command;

/**
 * Package command controller to handle packages from CLI (create/activate/deactivate packages)
 *
 * @scope singleton
 */
class PackageCommandController extends F3FLOW3MVCControllerCommandController {

	    /**
	     * @inject
	     * @var F3FLOW3PackagePackageManagerInterface
	     */
	    protected $packageManager;

	    /**
	      * Creates a new package
	      *
	      * Creates a new package with the given package key. The package key
	      * should be the vendor namespace segments.
	      *
	      * @param string $packageKey The package key of the package to create
	      * @return string
	      */
	    public function createCommand($packageKey) {
	    	    if (!$this->packageManager->isPackageKeyValid($packageKey)) {
	    	    	   $this->response->appendContent('The package key "' . $packageKey . '" is not
San Francisco, USA



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
San Francisco, USA



Security Policy
San Francisco, USA



Security

Cross-Site Request Forgery
 • enables an attacker to execute privileged operations without being
   authenticated

 • the risk lies in using malicious links or forms while still being
   authenticated

 • imagine a link coming in through an URL shortener...
San Francisco, USA



Security

Avoiding Cross-Site Request Forgery
 • add a (truly!) random string token to each link or form

 • make sure this token is correct before executing anything



 • change the token as often as possible to make it impossible to send
   you a working malicious link while you’re logged in

 • in most cases, we can assume that it should be enough to generate
   one token when you log in – that’s the default
San Francisco, USA



Security

CSRF Protection in FLOW3
 • you must not forget to add that token to any link

 • FLOW3 automatically adds the CSRF token to each

   • link you generate

   • each form you create with Fluid

 • and checks it for every call to a protected action



 • the protection can be disabled using
   @skipCsrfProtection on an action
Us e rs a n d L o g in

 5         8                1   1
        K. Damb ek aln s & R. Lem ke
         D.P. F l u x t r
        time ();
San Francisco, USA



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
San Francisco, USA



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
Th e Wiz a rd o f AOP

 5       8                1   1
      K. Damb ek aln s & R. Lem ke
       D.P. F l u x t r
      time ();
San Francisco, USA



Signal-Slot Event Handling

Signal

  • can be fired on any event

  • can be freely defined by the developer

Slot

  • is invoked when a signal is emitted

  • any method can be used as a slot



any signal can be wired to any slot
San Francisco, USA



Signal-Slot Event Handling

   /**
     * @param F3BlogDomainModelPost $post
     * @param F3BlogDomainModelComment $newComment
     * @return void
     */
   public function createAction(F3BlogDomainModelPost $post,
           F3BlogDomainModelComment $newComment) {
        $post->addComment($newComment);
        $this->emitCommentCreated($newComment, $post);
        …
   }




   /**
    * @param F3BlogDomainModelComment $comment
    * @param F3BlogDomainModelPost $post
    * @return void
    * @signal
    */
   protected function emitCommentCreated(F3BlogDomainModelComment $comment,
       F3BlogDomainModelPost $post) {}
San Francisco, USA



Signal-Slot Event Handling

Signals are wired to Slots in a package’s bootstrap:


 /**
   * Invokes custom PHP code directly after the package manager has been
   * initialized.
   *
   * @param F3FLOW3CoreBootstrap $bootstrap The current bootstrap
   * @return void
   */
 public function boot(F3FLOW3CoreBootstrap $bootstrap) {
      $dispatcher = $bootstrap->getSignalSlotDispatcher();
      $dispatcher->connect(
          'F3BlogControllerCommentController', 'commentCreated',
          'F3BlogServiceNotification', 'sendNewCommentNotification'
      );
 }
San Francisco, USA



Signal-Slot Event Handling

Any method can be a slot:

  /**
   * @param F3BlogDomainModelComment $comment
   * @param F3BlogDomainModelPost $post
   * @return void
   */
  public function sendNewCommentNotification(F3BlogDomainModelComment $comment,
         F3BlogDomainModelPost $post) {

      $mail = new F3SwiftMailerMessage();
      $mail
          ->setFrom(array('john@doe.org ' => 'John Doe'))
          ->setTo(array('karsten@typo3.org ' => 'Karsten Dambekalns'))
          ->setSubject('New comment on blog post "' . $post->getTitle() . '"')
          ->setBody($comment->getContent())
          ->send();
  }
San Francisco, USA



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 scalability
San Francisco, USA



More Features


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

 • Logging

 • File Monitoring

 • Configuration Management

 • Routing

 • REST / SOAP

 • ...
San Francisco, USA



Roadmap

http://forge.typo3.org/projects/flow3-distribution-base/roadmap
San Francisco, USA



Discover the source code of the conference app

git://git.typo3.org/TYPO3v5/Distributions/Conference.git
San Francisco, USA



Try out the blog app

git://git.typo3.org/FLOW3/Applications/Blog.git
San Francisco, USA



Thank You!

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

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

 • Follow us on Twitter: @t3rob (Robert) @k_fish (Karsten)

 • Give us feedback:

   • robert@typo3.org / karsten@typo3.org

   • http://joind.in/3535

More Related Content

Similar to Fluent Development with FLOW3 1.0

Getting Into FLOW3 (DPC12)
Getting Into FLOW3 (DPC12)Getting Into FLOW3 (DPC12)
Getting Into FLOW3 (DPC12)Robert Lemke
 
IPCSE12: Getting into FLOW3
IPCSE12: Getting into FLOW3IPCSE12: Getting into FLOW3
IPCSE12: Getting into FLOW3Robert Lemke
 
FLOW3 Tutorial - T3CON11 Frankfurt
FLOW3 Tutorial - T3CON11 FrankfurtFLOW3 Tutorial - T3CON11 Frankfurt
FLOW3 Tutorial - T3CON11 FrankfurtRobert Lemke
 
Getting Into FLOW3 (TYPO312CA)
Getting Into FLOW3 (TYPO312CA)Getting Into FLOW3 (TYPO312CA)
Getting Into FLOW3 (TYPO312CA)Robert Lemke
 
IPCSE12: Hands on FLOW3
IPCSE12: Hands on FLOW3IPCSE12: Hands on FLOW3
IPCSE12: Hands on FLOW3Robert Lemke
 
2012 08-11-flow3-northeast-php
2012 08-11-flow3-northeast-php2012 08-11-flow3-northeast-php
2012 08-11-flow3-northeast-phpJochen Rau
 
Hands on FLOW3 (DPC12)
Hands on FLOW3 (DPC12)Hands on FLOW3 (DPC12)
Hands on FLOW3 (DPC12)Robert Lemke
 
Fluent Development with FLOW3 1.0
Fluent Development with FLOW3 1.0Fluent Development with FLOW3 1.0
Fluent Development with FLOW3 1.0Robert Lemke
 
Gigigo Workshop - Create an iOS Framework, document it and not die trying
Gigigo Workshop - Create an iOS Framework, document it and not die tryingGigigo Workshop - Create an iOS Framework, document it and not die trying
Gigigo Workshop - Create an iOS Framework, document it and not die tryingAlex Rupérez
 
The Beauty And The Beast Php N W09
The Beauty And The Beast Php N W09The Beauty And The Beast Php N W09
The Beauty And The Beast Php N W09Bastian Feder
 
InspiringCon15: Bringing TYPO3 Legacy Applications into the Flow
InspiringCon15: Bringing TYPO3 Legacy Applications into the FlowInspiringCon15: Bringing TYPO3 Legacy Applications into the Flow
InspiringCon15: Bringing TYPO3 Legacy Applications into the Flowmhelmich
 
Speed up your developments with Symfony2
Speed up your developments with Symfony2Speed up your developments with Symfony2
Speed up your developments with Symfony2Hugo Hamon
 
Final Project Presentation
Final Project PresentationFinal Project Presentation
Final Project Presentationzroserie
 
The beautyandthebeast phpbat2010
The beautyandthebeast phpbat2010The beautyandthebeast phpbat2010
The beautyandthebeast phpbat2010Bastian Feder
 
The Beauty and the Beast
The Beauty and the BeastThe Beauty and the Beast
The Beauty and the BeastBastian Feder
 

Similar to Fluent Development with FLOW3 1.0 (20)

Getting Into FLOW3 (DPC12)
Getting Into FLOW3 (DPC12)Getting Into FLOW3 (DPC12)
Getting Into FLOW3 (DPC12)
 
IPCSE12: Getting into FLOW3
IPCSE12: Getting into FLOW3IPCSE12: Getting into FLOW3
IPCSE12: Getting into FLOW3
 
FLOW3 Tutorial - T3CON11 Frankfurt
FLOW3 Tutorial - T3CON11 FrankfurtFLOW3 Tutorial - T3CON11 Frankfurt
FLOW3 Tutorial - T3CON11 Frankfurt
 
Getting Into FLOW3 (TYPO312CA)
Getting Into FLOW3 (TYPO312CA)Getting Into FLOW3 (TYPO312CA)
Getting Into FLOW3 (TYPO312CA)
 
IPCSE12: Hands on FLOW3
IPCSE12: Hands on FLOW3IPCSE12: Hands on FLOW3
IPCSE12: Hands on FLOW3
 
2012 08-11-flow3-northeast-php
2012 08-11-flow3-northeast-php2012 08-11-flow3-northeast-php
2012 08-11-flow3-northeast-php
 
Hands on FLOW3 (DPC12)
Hands on FLOW3 (DPC12)Hands on FLOW3 (DPC12)
Hands on FLOW3 (DPC12)
 
Fluent Development with FLOW3 1.0
Fluent Development with FLOW3 1.0Fluent Development with FLOW3 1.0
Fluent Development with FLOW3 1.0
 
F3X12 FLOW3 Project Lifecycle
F3X12 FLOW3 Project LifecycleF3X12 FLOW3 Project Lifecycle
F3X12 FLOW3 Project Lifecycle
 
Ext 0523
Ext 0523Ext 0523
Ext 0523
 
Inside DocBlox
Inside DocBloxInside DocBlox
Inside DocBlox
 
Gigigo Workshop - Create an iOS Framework, document it and not die trying
Gigigo Workshop - Create an iOS Framework, document it and not die tryingGigigo Workshop - Create an iOS Framework, document it and not die trying
Gigigo Workshop - Create an iOS Framework, document it and not die trying
 
Demystifying Maven
Demystifying MavenDemystifying Maven
Demystifying Maven
 
The Beauty And The Beast Php N W09
The Beauty And The Beast Php N W09The Beauty And The Beast Php N W09
The Beauty And The Beast Php N W09
 
InspiringCon15: Bringing TYPO3 Legacy Applications into the Flow
InspiringCon15: Bringing TYPO3 Legacy Applications into the FlowInspiringCon15: Bringing TYPO3 Legacy Applications into the Flow
InspiringCon15: Bringing TYPO3 Legacy Applications into the Flow
 
Ant vs Phing
Ant vs PhingAnt vs Phing
Ant vs Phing
 
Speed up your developments with Symfony2
Speed up your developments with Symfony2Speed up your developments with Symfony2
Speed up your developments with Symfony2
 
Final Project Presentation
Final Project PresentationFinal Project Presentation
Final Project Presentation
 
The beautyandthebeast phpbat2010
The beautyandthebeast phpbat2010The beautyandthebeast phpbat2010
The beautyandthebeast phpbat2010
 
The Beauty and the Beast
The Beauty and the BeastThe Beauty and the Beast
The Beauty and the Beast
 

More from Robert Lemke

Neos Content Repository – Git for content
Neos Content Repository – Git for contentNeos Content Repository – Git for content
Neos Content Repository – Git for contentRobert Lemke
 
A General Purpose Docker Image for PHP
A General Purpose Docker Image for PHPA General Purpose Docker Image for PHP
A General Purpose Docker Image for PHPRobert Lemke
 
Scaleable PHP Applications in Kubernetes
Scaleable PHP Applications in KubernetesScaleable PHP Applications in Kubernetes
Scaleable PHP Applications in KubernetesRobert Lemke
 
Flownative Beach - Neos Meetup Hamburg 2022
Flownative Beach - Neos Meetup Hamburg 2022Flownative Beach - Neos Meetup Hamburg 2022
Flownative Beach - Neos Meetup Hamburg 2022Robert Lemke
 
GitOps with Flux - IPC Munich 2022
GitOps with Flux - IPC Munich 2022GitOps with Flux - IPC Munich 2022
GitOps with Flux - IPC Munich 2022Robert Lemke
 
OpenID Connect with Neos and Flow
OpenID Connect with Neos and FlowOpenID Connect with Neos and Flow
OpenID Connect with Neos and FlowRobert Lemke
 
Neos Conference 2019 Keynote
Neos Conference 2019 KeynoteNeos Conference 2019 Keynote
Neos Conference 2019 KeynoteRobert Lemke
 
A practical introduction to Kubernetes (IPC 2018)
A practical introduction to Kubernetes (IPC 2018)A practical introduction to Kubernetes (IPC 2018)
A practical introduction to Kubernetes (IPC 2018)Robert Lemke
 
Neos Conference 2018 Welcome Keynote
Neos Conference 2018 Welcome KeynoteNeos Conference 2018 Welcome Keynote
Neos Conference 2018 Welcome KeynoteRobert Lemke
 
A practical introduction to Event Sourcing and CQRS
A practical introduction to Event Sourcing and CQRSA practical introduction to Event Sourcing and CQRS
A practical introduction to Event Sourcing and CQRSRobert Lemke
 
Neos Conference 2017 Welcome Keynote
Neos Conference 2017 Welcome KeynoteNeos Conference 2017 Welcome Keynote
Neos Conference 2017 Welcome KeynoteRobert Lemke
 
IPC16: A Practical Introduction to Kubernetes
IPC16: A Practical Introduction to Kubernetes IPC16: A Practical Introduction to Kubernetes
IPC16: A Practical Introduction to Kubernetes Robert Lemke
 
IPC 2016: Content Strategy for Developers
IPC 2016: Content Strategy for DevelopersIPC 2016: Content Strategy for Developers
IPC 2016: Content Strategy for DevelopersRobert Lemke
 
Docker in Production - IPC 2016
Docker in Production - IPC 2016Docker in Production - IPC 2016
Docker in Production - IPC 2016Robert Lemke
 
Is this Open Source Thing Really Worth it? (IPC 2016 Berlin)
Is this Open Source Thing Really Worth it? (IPC 2016 Berlin)Is this Open Source Thing Really Worth it? (IPC 2016 Berlin)
Is this Open Source Thing Really Worth it? (IPC 2016 Berlin)Robert Lemke
 
The Neos Brand (Inspiring Conference 2016)
The Neos Brand (Inspiring Conference 2016)The Neos Brand (Inspiring Conference 2016)
The Neos Brand (Inspiring Conference 2016)Robert Lemke
 
Neos - past, present, future (Inspiring Conference 2016)
Neos - past, present, future (Inspiring Conference 2016)Neos - past, present, future (Inspiring Conference 2016)
Neos - past, present, future (Inspiring Conference 2016)Robert Lemke
 
Meet Neos Nürnberg 2016: Ja ich will!
Meet Neos Nürnberg 2016: Ja ich will!Meet Neos Nürnberg 2016: Ja ich will!
Meet Neos Nürnberg 2016: Ja ich will!Robert Lemke
 
Meet Neos Nürnberg 2016: Hallo Neos!
Meet Neos Nürnberg 2016: Hallo Neos!Meet Neos Nürnberg 2016: Hallo Neos!
Meet Neos Nürnberg 2016: Hallo Neos!Robert Lemke
 
Turning Neos inside out / React.js HH
Turning Neos inside out / React.js HHTurning Neos inside out / React.js HH
Turning Neos inside out / React.js HHRobert Lemke
 

More from Robert Lemke (20)

Neos Content Repository – Git for content
Neos Content Repository – Git for contentNeos Content Repository – Git for content
Neos Content Repository – Git for content
 
A General Purpose Docker Image for PHP
A General Purpose Docker Image for PHPA General Purpose Docker Image for PHP
A General Purpose Docker Image for PHP
 
Scaleable PHP Applications in Kubernetes
Scaleable PHP Applications in KubernetesScaleable PHP Applications in Kubernetes
Scaleable PHP Applications in Kubernetes
 
Flownative Beach - Neos Meetup Hamburg 2022
Flownative Beach - Neos Meetup Hamburg 2022Flownative Beach - Neos Meetup Hamburg 2022
Flownative Beach - Neos Meetup Hamburg 2022
 
GitOps with Flux - IPC Munich 2022
GitOps with Flux - IPC Munich 2022GitOps with Flux - IPC Munich 2022
GitOps with Flux - IPC Munich 2022
 
OpenID Connect with Neos and Flow
OpenID Connect with Neos and FlowOpenID Connect with Neos and Flow
OpenID Connect with Neos and Flow
 
Neos Conference 2019 Keynote
Neos Conference 2019 KeynoteNeos Conference 2019 Keynote
Neos Conference 2019 Keynote
 
A practical introduction to Kubernetes (IPC 2018)
A practical introduction to Kubernetes (IPC 2018)A practical introduction to Kubernetes (IPC 2018)
A practical introduction to Kubernetes (IPC 2018)
 
Neos Conference 2018 Welcome Keynote
Neos Conference 2018 Welcome KeynoteNeos Conference 2018 Welcome Keynote
Neos Conference 2018 Welcome Keynote
 
A practical introduction to Event Sourcing and CQRS
A practical introduction to Event Sourcing and CQRSA practical introduction to Event Sourcing and CQRS
A practical introduction to Event Sourcing and CQRS
 
Neos Conference 2017 Welcome Keynote
Neos Conference 2017 Welcome KeynoteNeos Conference 2017 Welcome Keynote
Neos Conference 2017 Welcome Keynote
 
IPC16: A Practical Introduction to Kubernetes
IPC16: A Practical Introduction to Kubernetes IPC16: A Practical Introduction to Kubernetes
IPC16: A Practical Introduction to Kubernetes
 
IPC 2016: Content Strategy for Developers
IPC 2016: Content Strategy for DevelopersIPC 2016: Content Strategy for Developers
IPC 2016: Content Strategy for Developers
 
Docker in Production - IPC 2016
Docker in Production - IPC 2016Docker in Production - IPC 2016
Docker in Production - IPC 2016
 
Is this Open Source Thing Really Worth it? (IPC 2016 Berlin)
Is this Open Source Thing Really Worth it? (IPC 2016 Berlin)Is this Open Source Thing Really Worth it? (IPC 2016 Berlin)
Is this Open Source Thing Really Worth it? (IPC 2016 Berlin)
 
The Neos Brand (Inspiring Conference 2016)
The Neos Brand (Inspiring Conference 2016)The Neos Brand (Inspiring Conference 2016)
The Neos Brand (Inspiring Conference 2016)
 
Neos - past, present, future (Inspiring Conference 2016)
Neos - past, present, future (Inspiring Conference 2016)Neos - past, present, future (Inspiring Conference 2016)
Neos - past, present, future (Inspiring Conference 2016)
 
Meet Neos Nürnberg 2016: Ja ich will!
Meet Neos Nürnberg 2016: Ja ich will!Meet Neos Nürnberg 2016: Ja ich will!
Meet Neos Nürnberg 2016: Ja ich will!
 
Meet Neos Nürnberg 2016: Hallo Neos!
Meet Neos Nürnberg 2016: Hallo Neos!Meet Neos Nürnberg 2016: Hallo Neos!
Meet Neos Nürnberg 2016: Hallo Neos!
 
Turning Neos inside out / React.js HH
Turning Neos inside out / React.js HHTurning Neos inside out / React.js HH
Turning Neos inside out / React.js HH
 

Recently uploaded

Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...
Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...
Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...panagenda
 
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxThe Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxLoriGlavin3
 
Time Series Foundation Models - current state and future directions
Time Series Foundation Models - current state and future directionsTime Series Foundation Models - current state and future directions
Time Series Foundation Models - current state and future directionsNathaniel Shimoni
 
Sample pptx for embedding into website for demo
Sample pptx for embedding into website for demoSample pptx for embedding into website for demo
Sample pptx for embedding into website for demoHarshalMandlekar2
 
Decarbonising Buildings: Making a net-zero built environment a reality
Decarbonising Buildings: Making a net-zero built environment a realityDecarbonising Buildings: Making a net-zero built environment a reality
Decarbonising Buildings: Making a net-zero built environment a realityIES VE
 
Genislab builds better products and faster go-to-market with Lean project man...
Genislab builds better products and faster go-to-market with Lean project man...Genislab builds better products and faster go-to-market with Lean project man...
Genislab builds better products and faster go-to-market with Lean project man...Farhan Tariq
 
From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .Alan Dix
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsSergiu Bodiu
 
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24Mark Goldstein
 
A Framework for Development in the AI Age
A Framework for Development in the AI AgeA Framework for Development in the AI Age
A Framework for Development in the AI AgeCprime
 
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...Alkin Tezuysal
 
Emixa Mendix Meetup 11 April 2024 about Mendix Native development
Emixa Mendix Meetup 11 April 2024 about Mendix Native developmentEmixa Mendix Meetup 11 April 2024 about Mendix Native development
Emixa Mendix Meetup 11 April 2024 about Mendix Native developmentPim van der Noll
 
Modern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
Modern Roaming for Notes and Nomad – Cheaper Faster Better StrongerModern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
Modern Roaming for Notes and Nomad – Cheaper Faster Better Strongerpanagenda
 
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptxPasskey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptxLoriGlavin3
 
So einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdfSo einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdfpanagenda
 
Generative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information DevelopersGenerative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information DevelopersRaghuram Pandurangan
 
TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024Lonnie McRorey
 
The State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptxThe State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptxLoriGlavin3
 
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc
 
How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.Curtis Poe
 

Recently uploaded (20)

Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...
Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...
Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...
 
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxThe Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
 
Time Series Foundation Models - current state and future directions
Time Series Foundation Models - current state and future directionsTime Series Foundation Models - current state and future directions
Time Series Foundation Models - current state and future directions
 
Sample pptx for embedding into website for demo
Sample pptx for embedding into website for demoSample pptx for embedding into website for demo
Sample pptx for embedding into website for demo
 
Decarbonising Buildings: Making a net-zero built environment a reality
Decarbonising Buildings: Making a net-zero built environment a realityDecarbonising Buildings: Making a net-zero built environment a reality
Decarbonising Buildings: Making a net-zero built environment a reality
 
Genislab builds better products and faster go-to-market with Lean project man...
Genislab builds better products and faster go-to-market with Lean project man...Genislab builds better products and faster go-to-market with Lean project man...
Genislab builds better products and faster go-to-market with Lean project man...
 
From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platforms
 
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
 
A Framework for Development in the AI Age
A Framework for Development in the AI AgeA Framework for Development in the AI Age
A Framework for Development in the AI Age
 
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...
 
Emixa Mendix Meetup 11 April 2024 about Mendix Native development
Emixa Mendix Meetup 11 April 2024 about Mendix Native developmentEmixa Mendix Meetup 11 April 2024 about Mendix Native development
Emixa Mendix Meetup 11 April 2024 about Mendix Native development
 
Modern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
Modern Roaming for Notes and Nomad – Cheaper Faster Better StrongerModern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
Modern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
 
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptxPasskey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptx
 
So einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdfSo einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdf
 
Generative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information DevelopersGenerative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information Developers
 
TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024
 
The State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptxThe State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptx
 
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
 
How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.
 

Fluent Development with FLOW3 1.0

  • 1. San Francisco, USA Karsten Dambekalns & Robert Lemke Fluent Development with FLOW3
  • 2. San Francisco, USA Karsten Dambekalns co-lead of TYPO3 5.0 and FLOW3 34 years old lives in Lübeck, Germany 1 wife, 3 sons, 1 espresso machine likes canoeing
  • 3. San Francisco, USA 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
  • 4. San Francisco, USA 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
  • 5. San Francisco, USA 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
  • 6. San Francisco, USA 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.
  • 7. San Francisco, USA Check Out from Git – Stable State $ git clone --recursive git://git.typo3.org/FLOW3/Distributions/Base.git . Cloning into .... remote: Counting objects: 3837, done. remote: Compressing objects: 100% (2023/2023), done. remote: Total 3837 (delta 2007), reused 2721 (delta 1465) Receiving objects: 100% (3837/3837), 3.49 MiB | 28 KiB/s, done. Resolving deltas: 100% (2007/2007), done.
  • 8. San Francisco, USA Set File Permissions $ ./Packages/Framework/FLOW3/Scripts/setfilepermissions.sh robert _www _www FLOW3 File Permission Script Checking permissions from here upwards ... (if a password prompt appears it's from sudo) Password: Making sure Data and Web/_Resources exist ... Setting file permissions, this might take a minute ... $
  • 9. San Francisco, USA Set Up Database Configuration/Settings.yaml # # # Global Settings # # # FLOW3: persistence: backendOptions: driver: 'pdo_mysql' dbname: 'blog' user: 'bloguser' password: 'blogpassword' host: '127.0.0.1' path: '127.0.0.1' port: 3306 doctrine: dbal: sessionInitialization: 'SET NAMES utf8 COLLATE utf8_unicode_ci'
  • 10. San Francisco, USA Set Up Virtual Host Apache Virtual Host <VirtualHost *:80> DocumentRoot /opt/local/apache2/htdocs/Talks/FLOW3/Web/ ServerName dev.flow3.rob SetEnv FLOW3_CONTEXT Development </VirtualHost> <VirtualHost *:80> DocumentRoot /opt/local/apache2/htdocs/Talks/FLOW3/Web/ ServerName flow3.rob SetEnv FLOW3_CONTEXT Production </VirtualHost>
  • 12. San Francisco, USA Update from Git to Latest State $ git submodule foreach "git checkout master" -✂-----✂-----✂-----✂-----✂-----✂-----✂-----✂-----✂-----✂-----✂-----✂- $ git submodule foreach "git pull --rebase" Entering 'Build/Common' First, rewinding head to replay your work on top of it... Fast-forwarded master to 6f27f1784240b414e966ce0e5a12e23cb2f7ab02. Entering 'Packages/Application/TYPO3' First, rewinding head to replay your work on top of it... Fast-forwarded master to 5187430ee44d579ae2bac825e2a069c4cd3f38a4. Entering 'Packages/Application/TYPO3CR' First, rewinding head to replay your work on top of it... Fast-forwarded master to b1f5331aa51d390fa3d973404f31b9fd773f7059. Entering 'Packages/Application/Twitter' Current branch master is up to date. …
  • 13. San Francisco, USA Hello World! Package.php <?php namespace F3Demo; use F3FLOW3PackagePackage as BasePackage; class Package extends BasePackage { } Today: $ ./flow3_dev flow3:package:create --package-key Demo Soon: $ ./flow3_dev flow3:package:create Demo
  • 14. L i ve H ac k ing 5 1 1 1 K. Damb ek aln s & R. Lem ke D.P. F l u x t r time ();
  • 15. San Francisco, USA 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!"; } } ?>
  • 16. San Francisco, USA Hello World! http://dev.flow3.rob/demo/standard/index?name=Robert Hello Robert!
  • 17. San Francisco, USA Tackling the Heart of Software Development /** Domain-Driven Design * Paper submitted 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;
  • 18. San Francisco, USA Domain-Driven Design Domain activity or business of the user Domain-Driven Design is about • focussing on the domain and domain logic • accurately mapping the concepts to software • forming a ubiquitous language among the project members
  • 19. San Francisco, USA Domain-Driven Design Ubiquitous Language • important prerequisite for successful collaboration • use the same words for • discussion • modeling • development • documentation
  • 21. Ex t re me Mo de li ng 5 2 1 1 K. Damb ek aln s & R. Lem ke D.P. F l u x t r time ();
  • 22. San Francisco, USA Example Model: Paper /** * A Paper * * @scope prototype * @entity */ class Paper { /** * @var F3ConferenceDomainModelAccountParticipant * @ManyToOne(cascade={"persist"}) * @validate NotEmpty */ protected $author; /** * @var string * @validate StringLength(minimum = 1, maximum = 50) */ protected $title;
  • 23. San Francisco, USA Example Model: Paper /** * @var string * @Column(type="text") * @validate StringLength(minimum = 30, maximum = 150) */ protected $shortAbstract; /** * @var string * @Column(type="text") * @validate StringLength(minimum = 100, maximum = 1000) */ protected $abstract; /** * @var F3ConferenceDomainModelConferenceSessionType * @ManyToOne(cascade={"persist"}) * @validate NotEmpty */ protected $proposedSessionType;
  • 24. San Francisco, USA Example Model: Paper /** * @var F3ConferenceDomainModelConferenceTrack * @ManyToOne(cascade={"persist"}) * @validate NotEmpty */ protected $proposedTrack; /** * @var DoctrineCommonCollectionsArrayCollection<F3ConferenceDomainModelComment> * @ManyToMany(cascade={"persist", "remove"}) */ protected $comments; /** * @var string */ protected $slideShareUrl; /** * @var string */ protected $tags;
  • 25. San Francisco, USA Example Model: Paper /** * @var string * @Column(type="text", nullable=true) */ protected $links; /** * @var DoctrineCommonCollectionsArrayCollection<F3ConferenceDomainModelAccount Participant> * @ManyToMany(cascade={"all"}) */ protected $speakers; /** * one of the STATUS_* constants * @var string */ protected $status = self::STATUS_DRAFT;
  • 26. San Francisco, USA Example Model: Paper /** * STATUS_* constants */ const STATUS_DRAFT = 'draft'; const STATUS_SUBMITTED = 'submitted'; const STATUS_REJECTED = 'rejected'; const STATUS_ACCEPTED = 'accepted'; const STATUS_SCHEDULED = 'scheduled'; public function __construct() { $this->comments = new DoctrineCommonCollectionsArrayCollection(); $this->speakers = new DoctrineCommonCollectionsArrayCollection(); } /** * @param F3ConferenceDomainModelAccountParticipant $author * @return void */ public function setAuthor(F3ConferenceDomainModelAccountParticipant $author) { $this->author = $author; } /** * @return F3ConferenceDomainModelAccountParticipant */ public function getAuthor() {
  • 28. San Francisco, USA 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
  • 29. San Francisco, USA 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);
  • 30. San Francisco, USA 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)); }
  • 31. San Francisco, USA 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
  • 32. San Francisco, USA 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
  • 33. San Francisco, USA 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; } ?>
  • 34. San Francisco, USA 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; } ?>
  • 35. San Francisco, USA 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
  • 36. San Francisco, USA 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 gathered automatically (autowiring) • intuitive use and no bad magical surprises • fast! (like hardcoded or faster)
  • 37. San Francisco, USA 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')); } }
  • 38. San Francisco, USA 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>
  • 39. San Francisco, USA 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; } }
  • 41. San Francisco, USA 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; } }
  • 42. San Francisco, USA 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; } }
  • 43. San Francisco, USA Objects.yaml F3FLOW3SecurityCryptographyRsaWalletServiceInterface: className: F3FLOW3SecurityCryptographyRsaWalletServicePhp scope: singleton properties: keystoreCache: object: factoryObjectName: F3FLOW3CacheCacheManager factoryMethodName: getCache arguments: 1: value: FLOW3_Security_Cryptography_RSAWallet
  • 44. San Francisco, USA 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)
  • 45. San Francisco, USA Object Management class Customer { /** * @inject * @var CustomerNumberGenerator */ protected $customerNumberGenerator; ... } $customer = new Customer(); $customer->getCustomerNumber();
  • 46. San Francisco, USA 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() {
  • 47. Birt h o f a Blo g 5 3 1 1 K. Damb ek aln s & R. Lem ke D.P. F l u x t r time ();
  • 48. San Francisco, USA The Zen of Templating FLOW3 comes with an elegant, flexible and secure templating engine: Fluid • templates are valid HTML • templates contain no PHP code • object access, control structures, loops ... • designer-friendly • extensible (view helpers, widgets)
  • 49. San Francisco, USA Fluid Example for assigning a string to a Fluid variable: // in the action controller: $this->view->assign('title', 'Welcome to Fluid'); <!-- in the Fluid template: --> <head> <title>{title}</title> </head>
  • 50. San Francisco, USA Fluid Variables can also be objects: // in the action controller: $this->view->assign('conference', $conference); <!-- in the Fluid template: --> <div class="venue"> <p>Venue Street: {conference.venue.street}</p> </div>
  • 51. San Francisco, USA Fluid if-then-else: // in the action controller: $this->view->assign('post', $blogPost); <!-- in the Fluid template: --> <f:if condition="{post.comments}"> <f:then>There are some comments.</f:then> <f:else>There are no comments.</f:else> </f:if>
  • 52. San Francisco, USA Fluid for-each: // in the action controller: $this->view->assign('ages', array("Karsten" => 34, "Robert" => 35)); <!-- in the Fluid template: --> <ul> <f:for each="{ages}" as="age" key="name"> <li>{name} is {age} year old.</li> </f:for> </ul>
  • 53. San Francisco, USA Fluid for-each: // in the action controller: $this->view->assign('post', $blogPost); <!-- in the Fluid template: --> <f:if condition="{post.comments}"> <ul> <f:for each="{post.comments}" as="comment" > <li>{post.title}</li> </f:for> </ul> </f:if>
  • 54. San Francisco, USA Fluid View helpers – in this case the link.action view helper: <!-- in the Fluid template: --> {namespace f=F3FluidViewHelpers} <f:link.action action="delete" arguments="{post: post, really: 'yes'}"> Delete this post </f:link.action>
  • 55. F lue n t F lu id 5 8 1 1 K. Damb ek aln s & R. Lem ke D.P. F l u x t r time ();
  • 56. San Francisco, USA 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;
  • 57. San Francisco, USA 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>
  • 58. San Francisco, USA 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'); }
  • 59. San Francisco, USA Karsten Dambekalns & Robert Lemke Fluent Development with FLOW3 (PART TWO)
  • 60.
  • 61. San Francisco, USA Validation Validation is about different things • incoming data needs to be validated for security reasons • no evil markup in submitted content • domain model integrity needs to be ensured • an email needs to be (syntactically) valid • credit card numbers should consist only of digits
  • 62. San Francisco, USA Validation Validation in FLOW3 • you do not want to code checks into your controllers • FLOW3 separates validation from your controller’s concerns • no PHP code needed for validation • declared through annotations
  • 63. San Francisco, USA Validation Validation Models • BaseProperties rules defining the minimum requirements on individual properties of a model • BaseModel rules or custom validators enforcing the minimum requirements on the combination of properties of a model • Supplemental rules defining additional requirements on a model for a specific situation (e.g. a certain action method)
  • 64. San Francisco, USA Validation Base Properties • Validation rules defined directly at the properties /** * @var string * @validate StringLength(minimum = 10, maximum = 100) */ protected $title; /** * @var string * @validate StringLength(minimum = 1, maximum = 50) */ protected $author;
  • 65. San Francisco, USA Validation Validators • validators provided by FLOW3 can be used through their short name • Count, Float, NotEmpty, RegularExpression, Uuid, DateTime, NumberRange, StringLength, Alphanumeric, Integer, Number, String, EmailAddress, Label, Raw, Text • custom validators need to implement the ValidatorInterface • use them by specifying the fully qualified class name /** * @var DambekalnsStuffDomainModelStuff * @validate DambekalnsStuffDomainValidatorStuffValidator */ protected $stuff;
  • 66. San Francisco, USA Schema Management Automatic database updates • when first running FLOW3 the schema will be created • when a model has changed, the schema is updated • be careful with existing data, updates can be destructive • for production you should manually manage schema changes
  • 67. San Francisco, USA Schema Management Manual database updates • for simple situations this can be good enough: $ ./flow3_dev flow3:doctrine:create $ ./flow3_dev flow3:doctrine:update • useful when • you need to use an existing database dump • using SQLite, due to limited schema change functionality
  • 68. San Francisco, USA Schema Management Doctrine 2 Migrations • Migrations allow schema versioning and change deployment • Migrations are the recommended way for DB updates • Tools to create and deploy migrations are integrated with FLOW3
  • 69. San Francisco, USA Schema Management Migrations Workflow • use schema auto update in early development until your model is ready for a first “freeze”, then switch off schema auto update and drop your tables • create migration diff and customize it $ ./flow3_dev flow3:doctrine:migrationdiff Generated new migration class to "…/Version20110608074324.php" from schema differences. $ vi …/Version20110608074324.php • migrate to create the tables $ ./flow3_dev flow3:doctrine:migrate
  • 70. San Francisco, USA Schema Management Migrations Workflow $ ./flow3_dev flow3:doctrine:migrationstatus == Configuration >> Name: Doctrine Database Migrations >> Database Driver: pdo_mysql >> Database Name: blog >> Configuration Source: manually configured >> Version Table Name: flow3_doctrine_migrationstatus >> Migrations Namespace: F3FLOW3PersistenceDoctrineMigrations >> Migrations Directory: /Users/karsten/Sites/blog/Configuration/Doctrine/Migrations >> Current Version: 2011-06-08 07:43:24 (20110608074324) >> Latest Version: 2011-06-08 07:43:24 (20110608074324) >> Executed Migrations: 1 >> Available Migrations: 1 >> New Migrations: 0 == Migration Versions >> 2011-06-08 07:43:24 (20110608074324) migrated
  • 71. San Francisco, USA Schema Management Migrations Workflow • rinse and repeat: from now on create a new migration whenever you changed your model classes • generated migrations most probably need to be adjusted • e.g. renaming a model means renaming a table, not dropping and creating • data migration needs to be added • remember: good migrations make your user’s day
  • 72. S ch e m at ic De mo 5 8 1 1 K. Damb ek aln s & R. Lem ke D.P. F l u x t r time ();
  • 74. Sh e b a ng! 5 8 1 1 K. Damb ek aln s & R. Lem ke D.P. F l u x t r time ();
  • 75. San Francisco, USA Command Line Support <?php namespace F3FLOW3Command; /** * Package command controller to handle packages from CLI (create/activate/deactivate packages) * * @scope singleton */ class PackageCommandController extends F3FLOW3MVCControllerCommandController { /** * @inject * @var F3FLOW3PackagePackageManagerInterface */ protected $packageManager; /** * Creates a new package * * Creates a new package with the given package key. The package key * should be the vendor namespace segments. * * @param string $packageKey The package key of the package to create * @return string */ public function createCommand($packageKey) { if (!$this->packageManager->isPackageKeyValid($packageKey)) { $this->response->appendContent('The package key "' . $packageKey . '" is not
  • 76. San Francisco, USA 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
  • 78. San Francisco, USA Security Cross-Site Request Forgery • enables an attacker to execute privileged operations without being authenticated • the risk lies in using malicious links or forms while still being authenticated • imagine a link coming in through an URL shortener...
  • 79. San Francisco, USA Security Avoiding Cross-Site Request Forgery • add a (truly!) random string token to each link or form • make sure this token is correct before executing anything • change the token as often as possible to make it impossible to send you a working malicious link while you’re logged in • in most cases, we can assume that it should be enough to generate one token when you log in – that’s the default
  • 80. San Francisco, USA Security CSRF Protection in FLOW3 • you must not forget to add that token to any link • FLOW3 automatically adds the CSRF token to each • link you generate • each form you create with Fluid • and checks it for every call to a protected action • the protection can be disabled using @skipCsrfProtection on an action
  • 81. Us e rs a n d L o g in 5 8 1 1 K. Damb ek aln s & R. Lem ke D.P. F l u x t r time ();
  • 82. San Francisco, USA 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
  • 83. San Francisco, USA 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
  • 84. Th e Wiz a rd o f AOP 5 8 1 1 K. Damb ek aln s & R. Lem ke D.P. F l u x t r time ();
  • 85. San Francisco, USA Signal-Slot Event Handling Signal • can be fired on any event • can be freely defined by the developer Slot • is invoked when a signal is emitted • any method can be used as a slot any signal can be wired to any slot
  • 86. San Francisco, USA Signal-Slot Event Handling /** * @param F3BlogDomainModelPost $post * @param F3BlogDomainModelComment $newComment * @return void */ public function createAction(F3BlogDomainModelPost $post, F3BlogDomainModelComment $newComment) { $post->addComment($newComment); $this->emitCommentCreated($newComment, $post); … } /** * @param F3BlogDomainModelComment $comment * @param F3BlogDomainModelPost $post * @return void * @signal */ protected function emitCommentCreated(F3BlogDomainModelComment $comment, F3BlogDomainModelPost $post) {}
  • 87. San Francisco, USA Signal-Slot Event Handling Signals are wired to Slots in a package’s bootstrap: /** * Invokes custom PHP code directly after the package manager has been * initialized. * * @param F3FLOW3CoreBootstrap $bootstrap The current bootstrap * @return void */ public function boot(F3FLOW3CoreBootstrap $bootstrap) { $dispatcher = $bootstrap->getSignalSlotDispatcher(); $dispatcher->connect( 'F3BlogControllerCommentController', 'commentCreated', 'F3BlogServiceNotification', 'sendNewCommentNotification' ); }
  • 88. San Francisco, USA Signal-Slot Event Handling Any method can be a slot: /** * @param F3BlogDomainModelComment $comment * @param F3BlogDomainModelPost $post * @return void */ public function sendNewCommentNotification(F3BlogDomainModelComment $comment, F3BlogDomainModelPost $post) { $mail = new F3SwiftMailerMessage(); $mail ->setFrom(array('john@doe.org ' => 'John Doe')) ->setTo(array('karsten@typo3.org ' => 'Karsten Dambekalns')) ->setSubject('New comment on blog post "' . $post->getTitle() . '"') ->setBody($comment->getContent()) ->send(); }
  • 89. San Francisco, USA 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 scalability
  • 90. San Francisco, USA More Features • Resource Management (CDNs, private resources, ...) • Logging • File Monitoring • Configuration Management • Routing • REST / SOAP • ...
  • 92. San Francisco, USA Discover the source code of the conference app git://git.typo3.org/TYPO3v5/Distributions/Conference.git
  • 93. San Francisco, USA Try out the blog app git://git.typo3.org/FLOW3/Applications/Blog.git
  • 94. San Francisco, USA Thank You! • These slides: http://slideshare.net/robertlemke • Download FLOW3: http://flow3.typo3.org • Follow us on Twitter: @t3rob (Robert) @k_fish (Karsten) • Give us feedback: • robert@typo3.org / karsten@typo3.org • http://joind.in/3535