SlideShare ist ein Scribd-Unternehmen logo
1 von 81
Downloaden Sie, um offline zu lesen
Bastian Waidelich & Robert Lemke

/**
 * Conference controller for the Acme.Demo package
 *
 * @scope singleton
 */
class ConferenceController extends ActionController {

	    /**
	     * @inject
	     * @var AcmeDemoDomainRepositoryConferenceRepository
	     */
	    protected $conferenceRepository;

	    /**
	      * Shows a list of conferences
	      *
	      * @return void
	      */
	    public function indexAction() {
	    	    $this->view->assign('conferences', $this->conferenceRepository->findAll());
	

	
    FLOW3 Tutorial
     }

     /**
	     * Shows a single conference object
	     *
Hanau, Germany



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, 2 daughters, 1 espresso machine

likes drumming
Hanau, Germany



Bastian Waidelich

FLOW3 core team member since 2008

co-creator of Fluid

30 years old

lives in Cologne, Germany

0 wifes, ? daughters, 1 cafetera

likes climbing & guitar playing
Hanau, Germany



This Workshop

Morning
 • Installation

 • Kickstart & Hello World!

 • Commands

 • Depencency Injection

 • Persistence, Doctrine and Domain-Driven Design

 • Modelling of an example App

 • Kickstarting the example App
Hanau, Germany



This Workshop

Afternoon
 • Routing

 • Validation

 • Property Mapper

 • Migrations

 • Security / Login

 • A Glimpse on TYPO3 Phoenix
Hanau, Germany



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
Hanau, Germany



 Foundation for the Next Generation CMS


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
Hanau, Germany



Git Clone




$ 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.
Hanau, Germany



 Set File Permissions

  $ sudo ./flow3 core:setfilepermissions robert _www _www
  FLOW3 File Permission Script

  Checking permissions from here upwards.
  Making sure Data and Web/_Resources exist.
  Setting file permissions, trying to set ACLs via chmod ...
  Done.



Linux:


  $ sudo usermod -a -G www-data robert


Mac OS X:

  $ sudo dscl . -append /Groups/_www GroupMembership robert
Hanau, Germany



Set Up Database Connection
Configuration/Settings.yaml



 #                                                                  #
 # Global Settings                                                  #
 #                                                                  #

 TYPO3:
   FLOW3:
     persistence:
        backendOptions:
          dbname: 'demo'
          user: 'demo'
          password: 'password'
          host: '127.0.0.1'

      # only on Windows:
      core:
        phpBinaryPathAndFilename: 'C:/path/to/php.exe'
Hanau, Germany



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>
Hanau, Germany



Final Check
Hanau, Germany



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 5187430ee44d579ae2bac825e2a069c4cd3Acme8a4.
Entering 'Packages/Application/TYPO3CR'
First, rewinding head to replay your work on top of it...
Fast-forwarded master to b1f5331aa51d390fa3d973404Acme1b9fd773f7059.
Entering 'Packages/Application/Twitter'
Current branch master is up to date.
…
Hanau, Germany



Command Line Use

$ ./flow3 help
FLOW3 1.0.0 ("Development" context)
usage: ./flow3 <command identifier>

The following commands are currently available:

PACKAGE "TYPO3.FLOW3":
-------------------------------------------------------------------------------
* flow3:cache:flush                        Flush all caches
  cache:warmup                             Warm up caches

* flow3:core:setfilepermissions            Adjust file permissions for CLI and
                                           web server access
* flow3:core:shell                         Run the interactive Shell

  doctrine:validate                        Validate the class/table mappings
  doctrine:create                          Create the database schema
  doctrine:update                          Update the database schema
  doctrine:entitystatus                    Show the current status of entities
                                           and mappings
  doctrine:dql                             Run arbitrary DQL and display
                                           results
  doctrine:migrationstatus                 Show the current migration status
  doctrine:migrate                         Migrate the database schema
  doctrine:migrationexecute                Execute a single migration
  doctrine:migrationversion                Mark/unmark a migration as migrated
  doctrine:migrationgenerate               Generate a new migration
Hanau, Germany



Command Line Use

$ ./flow3 help kickstart:package

Kickstart a new package

COMMAND:
  typo3.kickstart:kickstart:package

USAGE:
  ./flow3 kickstart:package <package key>

ARGUMENTS:
  --package-key           The package key, for example "MyCompany.MyPackageName"

DESCRIPTION:
  Creates a new package and creates a standard Action Controller and a sample
  template for its Index Action.

  For creating a new package without sample code use the package:create command.

SEE ALSO:
  typo3.flow3:package:create (Create a new package)
Hanau, Germany



Hello World!




               $ ./flow3 kickstart:package Acme.Demo
H e ll o Wo r ld !

 5         1                1   1
         Ro bert Lem ke
         D.P. F l u x t r
        time ();
Hanau, Germany



Hello World!

StandardController.php

   <?php
   namespace AcmeDemoController;

   use TYPO3FLOW3MVCControllerActionController;

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

   ?>
Hanau, Germany



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;
Hanau, Germany



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
Hanau, Germany



Domain-Driven Design

Ubiquitous Language
 • important prerequisite for successful
   collaboration

 • use the same words for

   • discussion

   • modeling

   • development

   • documentation
Hanau, Germany



Domain-Driven Design
Hanau, Germany



Domain: Conference
Hanau, Germany



Domain: Conference
Hanau, Germany



Domain: Conference
Hanau, Germany



Domain: Conference
K ic k s t a rt ing "C o n f e re n c e"

 5          1                1   1
         Ro bert Lem ke
          D.P. F l u x t r
        time ();
Hanau, Germany



Domain: Conference
Hanau, Germany



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
Hanau, Germany



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)
Hanau, Germany

                                                                             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 ' . $this->greeterService->greet($name), 200, array('Content-
Type' => 'text/plain'));
    }
Hanau, Germany

                                                                               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>
Hanau, Germany



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;
    }
}
Hanau, Germany



Constructor Injection
Hanau, Germany



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;
    }
}
Hanau, Germany



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;
    }
}
Hanau, Germany



Objects.yaml


   F3FLOW3SecurityCryptographyRsaWalletServiceInterface:
     className: F3FLOW3SecurityCryptographyRsaWalletServicePhp
     scope: singleton
     properties:
       keystoreCache:
         object:
           factoryObjectName: F3FLOW3CacheCacheManager
           factoryMethodName: getCache
           arguments:
             1:
                value: FLOW3_Security_Cryptography_RSAWallet
Hanau, Germany



Object Management

    class Customer {

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

	   ...
}

$customer = new Customer();
$customer->getCustomerNumber();
Hanau, Germany



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()    {
Hanau, Germany



Your Own Commands




      $ ./flow3 kickstart:commandcontroller Acme.Demo Test
Hanau, Germany



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
Hanau, Germany



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
Hanau, Germany



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)
Hanau, Germany



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;
Hanau, Germany



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;
Hanau, Germany



Property Mapper

Transfer properties from A to B
 • Allows for complete or partial copying of objects and object
   graphs

 • Is used by the MVC framework for the mapping of raw GET and
   POST data to Argument objects
Hanau, Germany



    Property Mapper




	   $articleArray = array(
	   	 'headline' => 'Hello World!',
	   	 'story' => 'Just a demo ...'
	   );

	   $article = $mapper->convert($sourceArray, 'Acme.DemoDomainModelArticle');
Hanau, Germany



 Resource Management

 Image Upload
 Resources are handled like other properties in a form:



	 <f:form method="blog" action="update" object="{blog}" name="blog"
enctype="multipart/form-data">
	 	 <f:if condition="{blog.authorPicture}">
	 	 	 <img src="{f:uri.resource(resource: blog.authorPicture)}" />
	 	 </f:if>
	 	 <label for="authorPicture">Author picture</label>
	 	 <f:form.upload property="authorPicture" id="authorPicture" />
	 	 <f:form.submit value="Update"/>
	 </f:form>
Hanau, Germany



    Property Mapper

    Allow nested object structures
    For security reasons the creation of nested structure through the
    property mapper is disabled by default

	   /**
	     * @return void
	     */
	   public function initializeUpdateAction() {
	   	 $this->arguments['article']->getPropertyMappingConfiguration()
            ->allowCreationForSubProperty('picture');
	   	 $this->arguments['article']->getPropertyMappingConfiguration()
            ->allowModificationForSubProperty('picture');
	   }
Hanau, Germany



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)

   • e.g. CouchDB, Solr
Hanau, Germany



    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);
Hanau, Germany



    Validation and Doctrine Annotations

namespace TYPO3BlogDomainModel;

/**
 * A Blog object
 *
 * @Entity
 */
class Blog {

    /**
     * @var string
     * @validate Text, StringLength(minimum = 1, maximum = 80)
     * @Column(length="80")
     */
    protected $title;

    /**
     * @var DoctrineCommonCollectionsCollection<TYPO3BlogDomainModelPost>
     * @OneToMany(mappedBy="blog")
     * @OrderBy({"date" = "DESC"})
     */
    protected $posts;

    ...

}
Hanau, Germany



Persistence-related Annotations


@Entity        Declares a class as "entity"

@Column        Controls the database column related to the class
               property. Very useful for longer text content
               (type="text" !)

@ManyToOne     Defines relations to other entities. Unlike with
@OneToMany     vanilla Doctrine targetEntity does not have to be
@ManyToMany    given but will be reused from the @var
@OneToOne      annotation.

               cascade can be used to cascade operation to
               related objects.
Hanau, Germany



Persistence-related Annotations




@var           Defines the type of a property, collections can be
               typed using angle brackets:
               DoctrineCommonCollectionsCollection<TYPO3ConferenceDomainModelComment>


@transient     The property will be ignored, it will neither be
               persisted nor reconstituted

@identity      Marks the property as part of an objects identity
Hanau, Germany



    Custom Queries using the Query Object Model
/**
 * A PostRepository
 */
class PostRepository extends TYPO3FLOW3PersistenceRepository {

    /**
      * Finds posts by the specified tag and blog
      *
      * @param TYPO3BlogDomainModelTag $tag
      * @param TYPO3BlogDomainModelBlog $blog The blog the post must refer to
      * @return TYPO3FLOW3PersistenceQueryResultInterface The posts
      */
    public function findByTagAndBlog(TYPO3BlogDomainModelTag $tag,
        TYPO3BlogDomainModelBlog $blog) {
          $query = $this->createQuery();
          return $query->matching(
              $query->logicalAnd(
                  $query->equals('blog', $blog),
                  $query->contains('tags', $tag)
              )
          )
          ->setOrderings(array(
              'date' => TYPO3FLOW3PersistenceQueryInterface::ORDER_DESCENDING)
          )
          ->execute();
    }
}
Hanau, Germany



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
Hanau, Germany



Schema Management

Running Migrations
• needed after installation or upgrade:


$ ./flow3 doctrine:migrate
Hanau, Germany



Schema Management

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


$ ./flow3 doctrine:create

$ ./flow3 doctrine:update




• useful when

 • you are just starting a project and have never released
Hanau, Germany



Schema Management

Generating migrations

$ ./flow3 doctrine:migrationgenerate
Generated new migration class to "…/Version20110608074324.php"
from schema differences.
$




• Generated migrations can contain errors and should be checked
  and adjusted as needed

• Migrations need to be moved to their “owning” package manually
M ig rat io n s

 5        8                1   1
        Ro bert Lem ke
        D.P. F l u x t r
       time ();
Hanau, Germany



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>
Hanau, Germany



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>
Hanau, Germany



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>
Hanau, Germany



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>
Hanau, Germany



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>
Hanau, Germany



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 ();
Hanau, Germany



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
Hanau, Germany



Security Policy
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 ();
Hanau, Germany



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
Hanau, Germany



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 ();
Hanau, Germany



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
Hanau, Germany



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) {}
Hanau, Germany



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'
      );
 }
Hanau, Germany



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();
  }
Hanau, Germany



Roadmap

http://forge.typo3.org/projects/flow3-distribution-base/roadmap
Hanau, Germany



Conference App

git://git.typo3.org/TYPO3v5/Distributions/Conference.git
Hanau, Germany



Blog App

git://git.typo3.org/FLOW3/Applications/Blog.git
Hanau, Germany



Thank You & Have Fun!

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

 • Blog: http://robertlemke.de/blog

 • Twitter: @robertlemke / @mrbasti

 • Feedback: robert@typo3.org / bastian@typo3.org

Weitere ähnliche Inhalte

Was ist angesagt?

第一回Cloudfoundry輪読会資料
第一回Cloudfoundry輪読会資料第一回Cloudfoundry輪読会資料
第一回Cloudfoundry輪読会資料
Toshihiko Ikeda
 
Apache Aries: A blueprint for developing with OSGi and JEE
Apache Aries: A blueprint for developing with OSGi and JEEApache Aries: A blueprint for developing with OSGi and JEE
Apache Aries: A blueprint for developing with OSGi and JEE
mahrwald
 

Was ist angesagt? (20)

Metasepi team meeting #8': Haskell apps on Android NDK
Metasepi team meeting #8': Haskell apps on Android NDKMetasepi team meeting #8': Haskell apps on Android NDK
Metasepi team meeting #8': Haskell apps on Android NDK
 
kubernetes-meetup-tokyo-20210624-kubevirt
kubernetes-meetup-tokyo-20210624-kubevirtkubernetes-meetup-tokyo-20210624-kubevirt
kubernetes-meetup-tokyo-20210624-kubevirt
 
猿でもわかる Helm
猿でもわかる Helm猿でもわかる Helm
猿でもわかる Helm
 
Cloud FoundryではじめるPaaSアプリケーション 開発入門講座
Cloud FoundryではじめるPaaSアプリケーション 開発入門講座 Cloud FoundryではじめるPaaSアプリケーション 開発入門講座
Cloud FoundryではじめるPaaSアプリケーション 開発入門講座
 
GMOインターネット様 発表「OpenStackのモデルの最適化とConoHa, Z.comとGMOアプリクラウドへの適用」 - OpenStack最新情...
GMOインターネット様 発表「OpenStackのモデルの最適化とConoHa, Z.comとGMOアプリクラウドへの適用」 - OpenStack最新情...GMOインターネット様 発表「OpenStackのモデルの最適化とConoHa, Z.comとGMOアプリクラウドへの適用」 - OpenStack最新情...
GMOインターネット様 発表「OpenStackのモデルの最適化とConoHa, Z.comとGMOアプリクラウドへの適用」 - OpenStack最新情...
 
Puppet devops wdec
Puppet devops wdecPuppet devops wdec
Puppet devops wdec
 
C# tutorial
C# tutorialC# tutorial
C# tutorial
 
第一回Cloudfoundry輪読会資料
第一回Cloudfoundry輪読会資料第一回Cloudfoundry輪読会資料
第一回Cloudfoundry輪読会資料
 
Jcconf 2015 Taipei -- Bluemix java liberty -auto-configration
Jcconf 2015 Taipei -- Bluemix java liberty -auto-configrationJcconf 2015 Taipei -- Bluemix java liberty -auto-configration
Jcconf 2015 Taipei -- Bluemix java liberty -auto-configration
 
Puppet and the Model-Driven Infrastructure
Puppet and the Model-Driven InfrastructurePuppet and the Model-Driven Infrastructure
Puppet and the Model-Driven Infrastructure
 
Introduction to Cloud Foundry #JJUG
Introduction to Cloud Foundry #JJUGIntroduction to Cloud Foundry #JJUG
Introduction to Cloud Foundry #JJUG
 
Go語言開發APM微服務在Kubernetes之經驗分享
Go語言開發APM微服務在Kubernetes之經驗分享Go語言開發APM微服務在Kubernetes之經驗分享
Go語言開發APM微服務在Kubernetes之經驗分享
 
I/O Extended (GDG Bogor) - Sidiq Permana
I/O Extended (GDG Bogor) - Sidiq PermanaI/O Extended (GDG Bogor) - Sidiq Permana
I/O Extended (GDG Bogor) - Sidiq Permana
 
Hands on Docker - Launch your own LEMP or LAMP stack - SunshinePHP
Hands on Docker - Launch your own LEMP or LAMP stack - SunshinePHPHands on Docker - Launch your own LEMP or LAMP stack - SunshinePHP
Hands on Docker - Launch your own LEMP or LAMP stack - SunshinePHP
 
Puppet evolutions
Puppet evolutionsPuppet evolutions
Puppet evolutions
 
20111018 1st lt_kom
20111018 1st lt_kom20111018 1st lt_kom
20111018 1st lt_kom
 
高レイテンシwebサーバのGKE構築と beta機能アレコレのハナシ
高レイテンシwebサーバのGKE構築と beta機能アレコレのハナシ高レイテンシwebサーバのGKE構築と beta機能アレコレのハナシ
高レイテンシwebサーバのGKE構築と beta機能アレコレのハナシ
 
Scalable TensorFlow Deep Learning as a Service with Docker, OpenPOWER, and GPUs
Scalable TensorFlow Deep Learning as a Service with Docker, OpenPOWER, and GPUsScalable TensorFlow Deep Learning as a Service with Docker, OpenPOWER, and GPUs
Scalable TensorFlow Deep Learning as a Service with Docker, OpenPOWER, and GPUs
 
Apache Aries: A blueprint for developing with OSGi and JEE
Apache Aries: A blueprint for developing with OSGi and JEEApache Aries: A blueprint for developing with OSGi and JEE
Apache Aries: A blueprint for developing with OSGi and JEE
 
PHP & JavaScript & CSS Coding style
PHP & JavaScript & CSS Coding stylePHP & JavaScript & CSS Coding style
PHP & JavaScript & CSS Coding style
 

Ähnlich wie FLOW3 Tutorial - T3CON11 Frankfurt

2012 08-11-flow3-northeast-php
2012 08-11-flow3-northeast-php2012 08-11-flow3-northeast-php
2012 08-11-flow3-northeast-php
Jochen Rau
 
Be a Happier Developer with Docker: Tricks of the Trade
Be a Happier Developer with Docker: Tricks of the TradeBe a Happier Developer with Docker: Tricks of the Trade
Be a Happier Developer with Docker: Tricks of the Trade
Docker, Inc.
 

Ähnlich wie FLOW3 Tutorial - T3CON11 Frankfurt (20)

IPCSE12: Getting into FLOW3
IPCSE12: Getting into FLOW3IPCSE12: Getting into FLOW3
IPCSE12: Getting into FLOW3
 
Getting Into FLOW3 (DPC12)
Getting Into FLOW3 (DPC12)Getting Into FLOW3 (DPC12)
Getting Into 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
 
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)
 
Getting Into FLOW3 (TYPO312CA)
Getting Into FLOW3 (TYPO312CA)Getting Into FLOW3 (TYPO312CA)
Getting Into FLOW3 (TYPO312CA)
 
Fluent Development with FLOW3 1.0
Fluent Development with FLOW3 1.0Fluent Development with FLOW3 1.0
Fluent Development with FLOW3 1.0
 
Php Documentor The Beauty And The Beast
Php Documentor The Beauty And The BeastPhp Documentor The Beauty And The Beast
Php Documentor The Beauty And The Beast
 
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
 
Command line for the beginner - Using the command line in developing for the...
Command line for the beginner -  Using the command line in developing for the...Command line for the beginner -  Using the command line in developing for the...
Command line for the beginner - Using the command line in developing for the...
 
Applications for the Enterprise with PHP (CPEurope)
Applications for the Enterprise with PHP (CPEurope)Applications for the Enterprise with PHP (CPEurope)
Applications for the Enterprise with PHP (CPEurope)
 
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
 
Be a happier developer with Docker: Tricks of the trade
Be a happier developer with Docker: Tricks of the tradeBe a happier developer with Docker: Tricks of the trade
Be a happier developer with Docker: Tricks of the trade
 
F3X12 FLOW3 Project Lifecycle
F3X12 FLOW3 Project LifecycleF3X12 FLOW3 Project Lifecycle
F3X12 FLOW3 Project Lifecycle
 
Presentation on Japanese doc sprint
Presentation on Japanese doc sprintPresentation on Japanese doc sprint
Presentation on Japanese doc sprint
 
The Beauty and the Beast
The Beauty and the BeastThe Beauty and the Beast
The Beauty and the Beast
 
Be a Happier Developer with Docker: Tricks of the Trade
Be a Happier Developer with Docker: Tricks of the TradeBe a Happier Developer with Docker: Tricks of the Trade
Be a Happier Developer with Docker: Tricks of the Trade
 
The beautyandthebeast phpbat2010
The beautyandthebeast phpbat2010The beautyandthebeast phpbat2010
The beautyandthebeast phpbat2010
 
Composer
ComposerComposer
Composer
 

Mehr von Robert Lemke

Mehr von 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
 

Kürzlich hochgeladen

IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI Solutions
Enterprise Knowledge
 

Kürzlich hochgeladen (20)

A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)
 
GenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdfGenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdf
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonets
 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
 
Evaluating the top large language models.pdf
Evaluating the top large language models.pdfEvaluating the top large language models.pdf
Evaluating the top large language models.pdf
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processors
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed texts
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organization
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI Solutions
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Script
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreter
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdf
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
 

FLOW3 Tutorial - T3CON11 Frankfurt

  • 1. Bastian Waidelich & Robert Lemke /** * Conference controller for the Acme.Demo package * * @scope singleton */ class ConferenceController extends ActionController { /** * @inject * @var AcmeDemoDomainRepositoryConferenceRepository */ protected $conferenceRepository; /** * Shows a list of conferences * * @return void */ public function indexAction() { $this->view->assign('conferences', $this->conferenceRepository->findAll()); FLOW3 Tutorial } /** * Shows a single conference object *
  • 2. Hanau, Germany 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, 2 daughters, 1 espresso machine likes drumming
  • 3. Hanau, Germany Bastian Waidelich FLOW3 core team member since 2008 co-creator of Fluid 30 years old lives in Cologne, Germany 0 wifes, ? daughters, 1 cafetera likes climbing & guitar playing
  • 4. Hanau, Germany This Workshop Morning • Installation • Kickstart & Hello World! • Commands • Depencency Injection • Persistence, Doctrine and Domain-Driven Design • Modelling of an example App • Kickstarting the example App
  • 5. Hanau, Germany This Workshop Afternoon • Routing • Validation • Property Mapper • Migrations • Security / Login • A Glimpse on TYPO3 Phoenix
  • 6. Hanau, Germany 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
  • 7. Hanau, Germany Foundation for the Next Generation CMS 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
  • 8. Hanau, Germany Git Clone $ 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.
  • 9. Hanau, Germany Set File Permissions $ sudo ./flow3 core:setfilepermissions robert _www _www FLOW3 File Permission Script Checking permissions from here upwards. Making sure Data and Web/_Resources exist. Setting file permissions, trying to set ACLs via chmod ... Done. Linux: $ sudo usermod -a -G www-data robert Mac OS X: $ sudo dscl . -append /Groups/_www GroupMembership robert
  • 10. Hanau, Germany Set Up Database Connection Configuration/Settings.yaml # # # Global Settings # # # TYPO3: FLOW3: persistence: backendOptions: dbname: 'demo' user: 'demo' password: 'password' host: '127.0.0.1' # only on Windows: core: phpBinaryPathAndFilename: 'C:/path/to/php.exe'
  • 11. Hanau, Germany 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>
  • 13. Hanau, Germany 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 5187430ee44d579ae2bac825e2a069c4cd3Acme8a4. Entering 'Packages/Application/TYPO3CR' First, rewinding head to replay your work on top of it... Fast-forwarded master to b1f5331aa51d390fa3d973404Acme1b9fd773f7059. Entering 'Packages/Application/Twitter' Current branch master is up to date. …
  • 14. Hanau, Germany Command Line Use $ ./flow3 help FLOW3 1.0.0 ("Development" context) usage: ./flow3 <command identifier> The following commands are currently available: PACKAGE "TYPO3.FLOW3": ------------------------------------------------------------------------------- * flow3:cache:flush Flush all caches cache:warmup Warm up caches * flow3:core:setfilepermissions Adjust file permissions for CLI and web server access * flow3:core:shell Run the interactive Shell doctrine:validate Validate the class/table mappings doctrine:create Create the database schema doctrine:update Update the database schema doctrine:entitystatus Show the current status of entities and mappings doctrine:dql Run arbitrary DQL and display results doctrine:migrationstatus Show the current migration status doctrine:migrate Migrate the database schema doctrine:migrationexecute Execute a single migration doctrine:migrationversion Mark/unmark a migration as migrated doctrine:migrationgenerate Generate a new migration
  • 15. Hanau, Germany Command Line Use $ ./flow3 help kickstart:package Kickstart a new package COMMAND: typo3.kickstart:kickstart:package USAGE: ./flow3 kickstart:package <package key> ARGUMENTS: --package-key The package key, for example "MyCompany.MyPackageName" DESCRIPTION: Creates a new package and creates a standard Action Controller and a sample template for its Index Action. For creating a new package without sample code use the package:create command. SEE ALSO: typo3.flow3:package:create (Create a new package)
  • 16. Hanau, Germany Hello World! $ ./flow3 kickstart:package Acme.Demo
  • 17. H e ll o Wo r ld ! 5 1 1 1 Ro bert Lem ke D.P. F l u x t r time ();
  • 18. Hanau, Germany Hello World! StandardController.php <?php namespace AcmeDemoController; use TYPO3FLOW3MVCControllerActionController; class StandardController extends ActionController { /** * @param string $name * @return string */ public function indexAction($name) { return "Hello $name!"; } } ?>
  • 19. Hanau, Germany 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;
  • 20. Hanau, Germany 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
  • 21. Hanau, Germany Domain-Driven Design Ubiquitous Language • important prerequisite for successful collaboration • use the same words for • discussion • modeling • development • documentation
  • 27. K ic k s t a rt ing "C o n f e re n c e" 5 1 1 1 Ro bert Lem ke D.P. F l u x t r time ();
  • 29. Hanau, Germany 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
  • 30. Hanau, Germany 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)
  • 31. Hanau, Germany 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 ' . $this->greeterService->greet($name), 200, array('Content- Type' => 'text/plain')); }
  • 32. Hanau, Germany 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>
  • 33. Hanau, Germany 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; } }
  • 35. Hanau, Germany 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; } }
  • 36. Hanau, Germany 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; } }
  • 37. Hanau, Germany Objects.yaml F3FLOW3SecurityCryptographyRsaWalletServiceInterface: className: F3FLOW3SecurityCryptographyRsaWalletServicePhp scope: singleton properties: keystoreCache: object: factoryObjectName: F3FLOW3CacheCacheManager factoryMethodName: getCache arguments: 1: value: FLOW3_Security_Cryptography_RSAWallet
  • 38. Hanau, Germany Object Management class Customer { /** * @inject * @var CustomerNumberGenerator */ protected $customerNumberGenerator; ... } $customer = new Customer(); $customer->getCustomerNumber();
  • 39. Hanau, Germany 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() {
  • 40. Hanau, Germany Your Own Commands $ ./flow3 kickstart:commandcontroller Acme.Demo Test
  • 41. Hanau, Germany 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
  • 42. Hanau, Germany 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
  • 43. Hanau, Germany 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)
  • 44. Hanau, Germany 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;
  • 45. Hanau, Germany 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;
  • 46. Hanau, Germany Property Mapper Transfer properties from A to B • Allows for complete or partial copying of objects and object graphs • Is used by the MVC framework for the mapping of raw GET and POST data to Argument objects
  • 47. Hanau, Germany Property Mapper $articleArray = array( 'headline' => 'Hello World!', 'story' => 'Just a demo ...' ); $article = $mapper->convert($sourceArray, 'Acme.DemoDomainModelArticle');
  • 48. Hanau, Germany Resource Management Image Upload Resources are handled like other properties in a form: <f:form method="blog" action="update" object="{blog}" name="blog" enctype="multipart/form-data"> <f:if condition="{blog.authorPicture}"> <img src="{f:uri.resource(resource: blog.authorPicture)}" /> </f:if> <label for="authorPicture">Author picture</label> <f:form.upload property="authorPicture" id="authorPicture" /> <f:form.submit value="Update"/> </f:form>
  • 49. Hanau, Germany Property Mapper Allow nested object structures For security reasons the creation of nested structure through the property mapper is disabled by default /** * @return void */ public function initializeUpdateAction() { $this->arguments['article']->getPropertyMappingConfiguration() ->allowCreationForSubProperty('picture'); $this->arguments['article']->getPropertyMappingConfiguration() ->allowModificationForSubProperty('picture'); }
  • 50. Hanau, Germany 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) • e.g. CouchDB, Solr
  • 51. Hanau, Germany 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);
  • 52. Hanau, Germany Validation and Doctrine Annotations namespace TYPO3BlogDomainModel; /** * A Blog object * * @Entity */ class Blog { /** * @var string * @validate Text, StringLength(minimum = 1, maximum = 80) * @Column(length="80") */ protected $title; /** * @var DoctrineCommonCollectionsCollection<TYPO3BlogDomainModelPost> * @OneToMany(mappedBy="blog") * @OrderBy({"date" = "DESC"}) */ protected $posts; ... }
  • 53. Hanau, Germany Persistence-related Annotations @Entity Declares a class as "entity" @Column Controls the database column related to the class property. Very useful for longer text content (type="text" !) @ManyToOne Defines relations to other entities. Unlike with @OneToMany vanilla Doctrine targetEntity does not have to be @ManyToMany given but will be reused from the @var @OneToOne annotation. cascade can be used to cascade operation to related objects.
  • 54. Hanau, Germany Persistence-related Annotations @var Defines the type of a property, collections can be typed using angle brackets: DoctrineCommonCollectionsCollection<TYPO3ConferenceDomainModelComment> @transient The property will be ignored, it will neither be persisted nor reconstituted @identity Marks the property as part of an objects identity
  • 55. Hanau, Germany Custom Queries using the Query Object Model /** * A PostRepository */ class PostRepository extends TYPO3FLOW3PersistenceRepository { /** * Finds posts by the specified tag and blog * * @param TYPO3BlogDomainModelTag $tag * @param TYPO3BlogDomainModelBlog $blog The blog the post must refer to * @return TYPO3FLOW3PersistenceQueryResultInterface The posts */ public function findByTagAndBlog(TYPO3BlogDomainModelTag $tag, TYPO3BlogDomainModelBlog $blog) { $query = $this->createQuery(); return $query->matching( $query->logicalAnd( $query->equals('blog', $blog), $query->contains('tags', $tag) ) ) ->setOrderings(array( 'date' => TYPO3FLOW3PersistenceQueryInterface::ORDER_DESCENDING) ) ->execute(); } }
  • 56. Hanau, Germany 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
  • 57. Hanau, Germany Schema Management Running Migrations • needed after installation or upgrade: $ ./flow3 doctrine:migrate
  • 58. Hanau, Germany Schema Management Manual database updates • for simple situations this can be good enough: $ ./flow3 doctrine:create $ ./flow3 doctrine:update • useful when • you are just starting a project and have never released
  • 59. Hanau, Germany Schema Management Generating migrations $ ./flow3 doctrine:migrationgenerate Generated new migration class to "…/Version20110608074324.php" from schema differences. $ • Generated migrations can contain errors and should be checked and adjusted as needed • Migrations need to be moved to their “owning” package manually
  • 60. M ig rat io n s 5 8 1 1 Ro bert Lem ke D.P. F l u x t r time ();
  • 61. Hanau, Germany 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>
  • 62. Hanau, Germany 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>
  • 63. Hanau, Germany 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>
  • 64. Hanau, Germany 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>
  • 65. Hanau, Germany 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>
  • 66. Hanau, Germany 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>
  • 67. 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 ();
  • 68. Hanau, Germany 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
  • 70. 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 ();
  • 71. Hanau, Germany 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
  • 72. Hanau, Germany 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
  • 73. 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 ();
  • 74. Hanau, Germany 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
  • 75. Hanau, Germany 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) {}
  • 76. Hanau, Germany 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' ); }
  • 77. Hanau, Germany 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(); }
  • 81. Hanau, Germany Thank You & Have Fun! • FLOW3: http://flow3.typo3.org • Blog: http://robertlemke.de/blog • Twitter: @robertlemke / @mrbasti • Feedback: robert@typo3.org / bastian@typo3.org