84
Robert Lemke Getting into FLOW3

IPCSE12: Getting into FLOW3

Embed Size (px)

DESCRIPTION

From the International PHP Conference (Spring Edition) 2012, in Berlin, Germany. FLOW3 is a web application platform which uses Domain-Driven Design as its major underlying concept. This approach makes FLOW3 easy to learn and at the same time clean and flexible for complex projects. It features namespaces, has an emphasis on clean, object-oriented code and provides a seemless Doctrine 2 integration. FLOW3 incorporates Dependency Injection in a way which lets you truly enjoy creating a stable and easy-to-test application architecture (no configuration necessary). Being the only Aspect-Oriented Programming capable PHP framework, FLOW3 allows you to cleanly separate cross-cutting concerns like security from your main application logic. This tutorial takes you through an imaginary project from scratch. During the journey we’ll visit all important areas of the framework.

Citation preview

Page 1: IPCSE12: Getting into FLOW3

Robert Lemke

Getting into FLOW3

Page 2: IPCSE12: Getting into FLOW3

chief architect of FLOW3 and TYPO3 “Phoenix”

co-founder of the TYPO3 Association

coach, coder, consultant

36 years old

lives in Lübeck, Germany

1 wife, 2 daughters, 1 espresso machine

likes drumming

Robert Lemke

Page 3: IPCSE12: Getting into FLOW3

StartersInstallation

Kickstart & Hello World!

Controller, Actions, Arguments & HTTP

Domain-Driven Design

Doctrine

Forms, Validation

Page 4: IPCSE12: Getting into FLOW3

Main Dishes

Resources, Image Upload

Session Handling

User, Account, Authentication

Authorization

Page 5: IPCSE12: Getting into FLOW3

DesertsCaching

Logging

Signal-Slot

Routing

Testing

Deployment

I18n

Espresso

Page 6: IPCSE12: Getting into FLOW3

?

Page 7: IPCSE12: Getting into FLOW3
Page 8: IPCSE12: Getting into FLOW3

At a Glance

FLOW3 is a web application platform

• 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

Page 9: IPCSE12: Getting into FLOW3

Foundation for the Next Generation CMS

TYPO3 “Phoenix” is the all-new Enterprise CMS

• content repository, workspaces, versions, i18n, modular UI ...

• powered by FLOW3

• compatible code base

• use TYPO3 features in FLOW3 standalone apps as you like

Page 10: IPCSE12: Getting into FLOW3

FLOW3 Website and Download

#

Page 11: IPCSE12: Getting into FLOW3

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.

Page 12: IPCSE12: Getting into FLOW3

Set File Permissions

$ sudo ./flow3 core:setfilepermissions robert _www _wwwFLOW3 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.

$ sudo usermod -a -G www-data robert

$ sudo dscl . -append /Groups/_www GroupMembership robert

Linux:

Mac OS X:

Page 13: IPCSE12: Getting into FLOW3

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'

Page 14: IPCSE12: Getting into FLOW3

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>

Page 15: IPCSE12: Getting into FLOW3

Final Check

Page 16: IPCSE12: Getting into FLOW3

Robert LemkeD.P. Fluxtr

time();

5 1 11

Clone the Beast

Page 17: IPCSE12: Getting into FLOW3

Biggest Book Store: Amazon

Page 18: IPCSE12: Getting into FLOW3

Biggest River: Amazon River

© Google

Page 19: IPCSE12: Getting into FLOW3

Smallest River: Roe River

© Google

Page 20: IPCSE12: Getting into FLOW3

Smallest River: Roe River

© Google

Page 21: IPCSE12: Getting into FLOW3

Smallest River: Roe River

© Google

Page 22: IPCSE12: Getting into FLOW3

Smallest Book Store: Roe Books

Page 23: IPCSE12: Getting into FLOW3

Sketchy Model

Page 24: IPCSE12: Getting into FLOW3

Robert LemkeD.P. Fluxtr

time();

5 1 12

Just Code a Shop

Page 25: IPCSE12: Getting into FLOW3

Tackling the Heart of Software Development

Domain-Driven DesignA methodology which ...

• results in rich domain models

• provides a common language across the project team

• simplify the design of complex applications

FLOW3 is the first PHP framework tailored to Domain-Driven Design

/** * A Book * * @FLOW3\Scope(“prototype”) * @FLOW3\Entity */class Book {

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

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

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

/** * @var integer */ protected $price;

/** * @var \SplObjectStorage */ protected $materials;

/** * @var \Acme\Conference\Domain\Model\SessionType * @validate NotEmpty */ protected $proposedSessionType;

/** * Constructs a new Paper * * @author Robert Lemke <[email protected]> */ public function __construct() { $this->materials = new \SplObjectStorage; }

/** * Sets the author of this paper * * @param \Acme\Conference\Domain\Model\Participant $author * @return void * @author Robert Lemke <[email protected]> */ public function setAuthor(\Acme\Conference\Domain\Model\Participant $author) { $this->author = $author; }

/** * Getter for the author of this paper * * @return \Acme\Conference\Domain\Model\Participant * @author Robert Lemke <[email protected]> */ public function getAuthor() { return $this->author; }

/** * Setter for title * * @param string $title The title of this paper * @return void * @author Robert Lemke <[email protected]> */ public function setTitle($title) { $this->title = $title; }

/** * Getter for title * * @return string The title of this paper * @author Robert Lemke <[email protected]> */ public function getTitle() { return $this->title; }

/** * Setter for the short abstract * * @param string $shortAbstract The short abstract for this paper * @return void * @author Robert Lemke <[email protected]> */ public function setShortAbstract($shortAbstract) { $this->shortAbstract = $shortAbstract; }

/** * Getter for the short abstract * * @return string The short abstract * @author Robert Lemke <[email protected]> */ public function getShortAbstract() { return $this->shortAbstract; }

/** * Setter for abstract * * @param string $abstract The abstract of this paper * @return void * @author Robert Lemke <[email protected]> */ public function setAbstract($abstract) { $this->abstract = $abstract; }

/** * Getter for abstract * * @return string The abstract * @author Robert Lemke <[email protected]> */ public function getAbstract() { return $this->abstract; }

/** * Returns the materials attached to this paper * * @return \SplObjectStorage The materials * @author Robert Lemke <[email protected]> */ public function getMaterials() { return $this->materials; }

/** * Setter for the proposed session type * * @param \Acme\Conference\Domain\Model\SessionType $proposedSessionType The proposed session type * @return void * @author Robert Lemke <[email protected]> */ public function setProposedSessionType(\Acme\Conference\Domain\Model\SessionType $proposedSessionType) { $this->proposedSessionType = $proposedSessionType; }

/** * Getter for the proposed session type * * @return \Acme\Conference\Domain\Model\SessionType The proposed session type * @author Robert Lemke <[email protected]> */ public function getProposedSessionType() { return $this->proposedSessionType; }}?>

Page 26: IPCSE12: Getting into FLOW3

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

Page 27: IPCSE12: Getting into FLOW3

Domain-Driven Design

Ubiquitous Language

• important prerequisite for successful collaboration

• use the same words for

• discussion

• modeling

• development

• documentation

Page 28: IPCSE12: Getting into FLOW3

Domain-Driven Design

Building Blocks

• Entity: An object that is not defined by its attributes, but rather by a thread of continuity and its identity.

• Value Object: An object that contains attributes but has no conceptual identity. They should be treated as immutable.

• Aggregate: A collection of objects that are bound together by a root entity, otherwise known as an aggregate root. The aggregate root guarantees the consistency of changes being made within the aggregate by forbidding external objects from holding references to its members.

Page 29: IPCSE12: Getting into FLOW3

Domain-Driven Design

Building Blocks

• Service: When an operation does not conceptually belong to any object. Following the natural contours of the problem, you can implement these operations in services.

• Repository: methods for retrieving domain objects should delegate to a specialized Repository object such that alternative storage implementations may be easily interchanged.

Page 30: IPCSE12: Getting into FLOW3

Domain-Driven Design

Page 31: IPCSE12: Getting into FLOW3

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)

Page 32: IPCSE12: Getting into FLOW3

namespace Acme\Demo\Controller;

use TYPO3\FLOW3\Mvc\Controller\ActionController;use Acme\Demo\Service\GreeterService;

class DemoController extends ActionController { /** * @var \Acme\Demo\Service\GreeterService */ protected $greeterService;

/** * @param \Acme\Demo\Service\GreeterService */ public function __construct(GreeterService $greeterService) { $this->greeterService = $greeterService; } /** * @param string $name */ public function helloAction($name) { return $this->greeterService->greet($name); }}

Constructor Injection

Page 33: IPCSE12: Getting into FLOW3

namespace Acme\Demo\Controller;

use TYPO3\FLOW3\MVC\Controller\ActionController;use Acme\Demo\Service\GreeterService;

class DemoController extends ActionController { /** * @var \Acme\Demo\Service\GreeterService */ protected $greeterService;

/** * @param \Acme\Demo\Service\GreeterService */ public function injectGreeterService(GreeterService $greeterService) { $this->greeterService = $greeterService; } /** * @param string $name */ public function helloAction($name) { return $this->greeterService->greet($name); }}

Setter Injection

Page 34: IPCSE12: Getting into FLOW3

namespace TYPO3\Demo\Controller;

use TYPO3\FLOW3\Annotations as FLOW3;use TYPO3\FLOW3\MVC\Controller\ActionController;use Acme\Demo\Service\GreeterService;

class DemoController extends ActionController { /** * @var \TYPO3\Demo\Service\GreeterService * @FLOW3\Inject */ protected $greeterService; /** * @param string $name */ public function helloAction($name) { return $this->greeterService->greet($name); }}

Property Injection

Page 35: IPCSE12: Getting into FLOW3

TYPO3\FLOW3\Security\Cryptography\RsaWalletServiceInterface: className: TYPO3\FLOW3\Security\Cryptography\RsaWalletServicePhp scope: singleton properties: keystoreCache: object: factoryObjectName: TYPO3\FLOW3\Cache\CacheManager factoryMethodName: getCache arguments: 1: value: FLOW3_Security_Cryptography_RSAWallet

Objects.yaml

Page 36: IPCSE12: Getting into FLOW3

class Customer {

/** * @FLOW3\Inject * @var \Acme\CustomerNumberGenerator */ protected $customerNumberGenerator; ...}

$customer = new Customer();$customer->getCustomerNumber();

Object Management

Page 37: IPCSE12: Getting into FLOW3

Object Management<?phpdeclare(ENCODING = 'utf-8');namespace TYPO3\Conference\Domain\Model\Conference;use TYPO3\FLOW3\Annotations as FLOW3;/** * Autogenerated Proxy Class * @FLOW3\Scope(“prototype”) * @FLOW3\Entity */class Paper extends Paper_Original implements \TYPO3\FLOW3\Object\Proxy\ProxyInterface, \TYPO3\FLOW3\Persistence\Aspect\PersistenceMagicInterface { /** * @var string * @ORM\Id * @ORM\Column(length="40") * introduced by TYPO3\FLOW3\Persistence\Aspect\PersistenceMagicAspect */ protected $FLOW3_Persistence_Identifier = NULL; private $FLOW3_AOP_Proxy_targetMethodsAndGroupedAdvices = array(); private $FLOW3_AOP_Proxy_groupedAdviceChains = array(); private $FLOW3_AOP_Proxy_methodIsInAdviceMode = array();

/** * Autogenerated Proxy Method */ public function __construct() { $this->FLOW3_AOP_Proxy_buildMethodsAndAdvicesArray(); if (isset($this->FLOW3_AOP_Proxy_methodIsInAdviceMode['__construct'])) { parent::__construct(); } else {

FLOW3 creates proxy classesfor realizing DI and AOP magic

• new operator is supported

• proxy classes are created on the fly

• in production context all code is static

Page 38: IPCSE12: Getting into FLOW3

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

Page 39: IPCSE12: Getting into FLOW3

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

Page 40: IPCSE12: Getting into FLOW3

Validation and Doctrine Annotations

namespace TYPO3\Blog\Domain\Model;

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

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

/** * @var \Doctrine\Common\Collections\Collection<\TYPO3\Blog\Domain\Model\Post> * @OneToMany(mappedBy="blog") * @OrderBy({"date" = "DESC"}) */ protected $posts;

...

}

Page 41: IPCSE12: Getting into FLOW3

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 @OneToMany @ManyToMany@OneToOne

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

cascade can be used to cascade operation to related objects.

Page 42: IPCSE12: Getting into FLOW3

@var Defines the type of a property, collections can be typed using angle brackets:\Doctrine\Common\Collections\Collection<\TYPO3\Conference\Domain\Model\Comment>

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

@identity Marks the property as part of an objects identity

Persistence-related Annotations

Page 43: IPCSE12: Getting into FLOW3

Custom Queries using the Query Object Model

/** * A PostRepository */class PostRepository extends \TYPO3\FLOW3\Persistence\Repository {

/** * Finds posts by the specified tag and blog * * @param \TYPO3\Blog\Domain\Model\Tag $tag * @param \TYPO3\Blog\Domain\Model\Blog $blog The blog the post must refer to * @return \TYPO3\FLOW3\Persistence\QueryResultInterface The posts */ public function findByTagAndBlog(\TYPO3\Blog\Domain\Model\Tag $tag, \TYPO3\Blog\Domain\Model\Blog $blog) { $query = $this->createQuery(); return $query->matching( $query->logicalAnd( $query->equals('blog', $blog), $query->contains('tags', $tag) ) ) ->setOrderings(array( 'date' => \TYPO3\FLOW3\Persistence\QueryInterface::ORDER_DESCENDING) ) ->execute(); }}

Page 44: IPCSE12: Getting into FLOW3

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

Page 45: IPCSE12: Getting into FLOW3

Schema Management

Running Migrations

• needed after installation or upgrade:

$ ./flow3 doctrine:migrate

Page 46: IPCSE12: Getting into FLOW3

Schema Management

$ ./flow3 doctrine:create

$ ./flow3 doctrine:update

Manual database updates

• for simple situations this can be good enough:

• useful when

• you are just starting a project and have never released

Page 47: IPCSE12: Getting into FLOW3

Schema Management

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

Generating migrations

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

• Migrations need to be moved to their “owning” package manually

Page 48: IPCSE12: Getting into FLOW3

Validation

Validation is about various …

• 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

Page 49: IPCSE12: Getting into FLOW3

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

Page 50: IPCSE12: Getting into FLOW3

Validation

Validation Models

• BasePropertiesrules defining the minimum requirements on individual properties of a model

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

• Supplementalrules defining additional requirements on a model for a specific situation (e.g. a certain action method)

Page 51: IPCSE12: Getting into FLOW3

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;

Page 52: IPCSE12: Getting into FLOW3

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 \Dambekalns\Stuff\Domain\Model\Stuff * @validate \Dambekalns\Stuff\Domain\Validator\StuffValidator */ protected $stuff;

Page 53: IPCSE12: Getting into FLOW3

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

Page 54: IPCSE12: Getting into FLOW3

Property Mapper

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

$article = $mapper->convert($sourceArray, 'Acme.Demo\Domain\Model\Article');

Page 55: IPCSE12: Getting into FLOW3

Resource Management

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

Image Upload

Resources are handled like other properties in a form:

Page 56: IPCSE12: Getting into FLOW3

Property Mapper

/** * @return void */ public function initializeUpdateAction() { $this->arguments['article']->getPropertyMappingConfiguration()

->allowCreationForSubProperty('picture'); $this->arguments['article']->getPropertyMappingConfiguration()

->allowModificationForSubProperty('picture'); }

Allow nested object structures

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

Page 57: IPCSE12: Getting into FLOW3

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)

Page 58: IPCSE12: Getting into FLOW3

Fluid

Example for assigning a string to a Fluid variable:

<!-- in the Fluid template: --> <head> <title>{title}</title> </head>

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

Page 59: IPCSE12: Getting into FLOW3

Fluid

Variables can also be objects:

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

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

Page 60: IPCSE12: Getting into FLOW3

Fluid

if-then-else:

<!-- 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>

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

Page 61: IPCSE12: Getting into FLOW3

Fluid

for-each:

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

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

Page 62: IPCSE12: Getting into FLOW3

Fluid

for-each:

<!-- 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>

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

Page 63: IPCSE12: Getting into FLOW3

Fluid

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

<!-- in the Fluid template: --> {namespace f=TYPO3\Fluid\ViewHelpers}

<f:link.action action="delete" arguments="{post: post, really: 'yes'}"> Delete this post </f:link.action>

Page 64: IPCSE12: Getting into FLOW3

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

Page 65: IPCSE12: Getting into FLOW3

Security Policy

Page 66: IPCSE12: Getting into FLOW3

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...

Page 67: IPCSE12: Getting into FLOW3

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

Page 68: IPCSE12: Getting into FLOW3

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

Page 69: IPCSE12: Getting into FLOW3

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

Page 70: IPCSE12: Getting into FLOW3

AOP

FLOW3 uses AOP for ...

• persistence magic

• logging

• debugging

• security

/** * @aspect * @introduce TYPO3\FLOW3\Persistence\Aspect\PersistenceMagicInterface, TYPO3\FLOW3\Persistence\Aspect\

*/class PersistenceMagicAspect { /** * @pointcut classTaggedWith(entity) || classTaggedWith(valueobject) */ public function isEntityOrValueObject() {} /** * @var string * @Id * @Column(length="40") * @introduce TYPO3\FLOW3\Persistence\Aspect\PersistenceMagicAspect->isEntityOrValueObject && filter

*/ protected $FLOW3_Persistence_Identifier; /** * After returning advice, making sure we have an UUID for each and every entity.

* * @param \TYPO3\FLOW3\AOP\JoinPointInterface $joinPoint The current join point

* @return void * @before classTaggedWith(entity) && method(.*->__construct()) */ public function generateUUID(\TYPO3\FLOW3\AOP\JoinPointInterface $joinPoint) {

$proxy = $joinPoint->getProxy(); \TYPO3\FLOW3\Reflection\ObjectAccess::setProperty($proxy, 'FLOW3_Persistence_Identifier',

}

Page 71: IPCSE12: Getting into FLOW3

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

Page 72: IPCSE12: Getting into FLOW3

Signal-Slot Event Handling

/** * @param \TYPO3\Blog\Domain\Model\Post $post * @param \TYPO3\Blog\Domain\Model\Comment $newComment * @return void */ public function createAction(\TYPO3\Blog\Domain\Model\Post $post, \TYPO3\Blog\Domain\Model\Comment $newComment) { $post->addComment($newComment); $this->emitCommentCreated($newComment, $post); … }

/** * @param \TYPO3\Blog\Domain\Model\Comment $comment * @param \TYPO3\Blog\Domain\Model\Post $post * @return void * @signal */ protected function emitCommentCreated(\TYPO3\Blog\Domain\Model\Comment $comment, \TYPO3\Blog\Domain\Model\Post $post) {}

Page 73: IPCSE12: Getting into FLOW3

Signal-Slot Event Handling

/** * Invokes custom PHP code directly after the package manager has been * initialized. * * @param \TYPO3\FLOW3\Core\Bootstrap $bootstrap The current bootstrap * @return void */ public function boot(\TYPO3\FLOW3\Core\Bootstrap $bootstrap) { $dispatcher = $bootstrap->getSignalSlotDispatcher(); $dispatcher->connect( 'TYPO3\Blog\Controller\CommentController', 'commentCreated', 'TYPO3\Blog\Service\Notification', 'sendNewCommentNotification' ); }

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

Page 74: IPCSE12: Getting into FLOW3

Signal-Slot Event Handling

/** * @param \TYPO3\Blog\Domain\Model\Comment $comment * @param \TYPO3\Blog\Domain\Model\Post $post * @return void */ public function sendNewCommentNotification(\TYPO3\Blog\Domain\Model\Comment $comment, \TYPO3\Blog\Domain\Model\Post $post) { $mail = new \TYPO3\SwiftMailer\Message(); $mail ->setFrom(array('[email protected] ' => 'John Doe')) ->setTo(array('[email protected] ' => 'Karsten Dambekalns')) ->setSubject('New comment on blog post "' . $post->getTitle() . '"') ->setBody($comment->getContent()) ->send(); }

Any method can be a slot:

Page 75: IPCSE12: Getting into FLOW3

Roadmap

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

Page 76: IPCSE12: Getting into FLOW3

Conference App

git://git.typo3.org/TYPO3v5/Distributions/Conference.git

Page 77: IPCSE12: Getting into FLOW3

Blog App

git://git.typo3.org/FLOW3/Applications/Blog.git

Page 78: IPCSE12: Getting into FLOW3

Rossmann

• second biggest drug store in Germany

• 5,13 billion ! turnover

• 31,000 employees

Page 79: IPCSE12: Getting into FLOW3

Customer Database

• custom persistence with CouchDB

• SOAP support

• continuous delivery

• cluster setup

by networkteam, Kiel

Page 80: IPCSE12: Getting into FLOW3

Amadeus

• world’s biggest e-ticket provider

• 217 markets

• 948 million billable transactions / year

• 2,7 billion ! revenue

Page 81: IPCSE12: Getting into FLOW3

Social Media Suite

• central hub for social media activities for potentially thousands of travel agencies

• advanced form engine

• various detail improvements

• uses an early version of TYPO3 Phoenix

by AKOM360, Munich

Page 82: IPCSE12: Getting into FLOW3

“Our senior developers are extremely happy with FLOW3 –

it is definitely the most capable PHP framework we have come across so far.”

Fabian PfützeProject Lead

Page 83: IPCSE12: Getting into FLOW3

?