FLOW3 is an application framework which will change the way you code PHP. It aims to back up developers with security and infrastructure while they focus on the application logic.
FLOW3 is one of the first application frameworks to choose Domain-Driven Design as its major underlying concept. This approach makes FLOW3 easy to learn and at the same time clean and flexible for even complex projects. Built with PHP 5.3 in mind from the beginning, it features namespaces and has an emphasis on clean, object-oriented code.
Thanks to its Doctrine 2 integration, FLOW3 gives you access to a wide range of databases while letting you forget the fact that you're using a database at all (think objects, not tables). FLOW3's unique way of supporting Dependency Injection (no configuration necessary) lets you truly enjoy creating a stable and easy-to-test application architecture. 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 provides a comprehensive overview of the main features of FLOW3 and how you can get started with your first app.
2. San Francisco, USA
Karsten Dambekalns
co-lead of TYPO3 5.0 and FLOW3
34 years old
lives in Lübeck, Germany
1 wife, 3 sons, 1 espresso machine
likes canoeing
3. San Francisco, USA
Robert Lemke
chief "architect" of TYPO3 5.0 and FLOW3
co-founder of the TYPO3 Association
35 years old
lives in Lübeck, Germany
1 wife, 1 daughter, 1 espresso machine
likes drumming
4. San Francisco, USA
At a Glance
FLOW3 is a web application framework
• brings PHP development to a new level
• made for PHP 5.3, full namespaces support
• modular, extensible, package based
• free & Open Source (LGPL v3)
• backed by one of the largest Open Source projects
with 6000+ contributors
5. San Francisco, USA
Foundation for the Next Generation
TYPO3 5.0 is the all-new
Enterprise CMS
• content repository, workspaces,
versions, i18n, ExtJS based UI ...
• powered by FLOW3
• compatible code base
• use TYPO3 features in FLOW3
standalone apps as you like
6. San Francisco, USA
Work in Progress
WARNING
The current documen
tation of FLOW3 does
cover the version in not
our Git master – a lo
changed since the la t has
st alpha release!
We are currently upd
ating the manuals an
tutorials for the 1.0 b d
eta release though.
7. San Francisco, USA
Check Out from Git – Stable State
$ git clone --recursive git://git.typo3.org/FLOW3/Distributions/Base.git .
Cloning into ....
remote: Counting objects: 3837, done.
remote: Compressing objects: 100% (2023/2023), done.
remote: Total 3837 (delta 2007), reused 2721 (delta 1465)
Receiving objects: 100% (3837/3837), 3.49 MiB | 28 KiB/s, done.
Resolving deltas: 100% (2007/2007), done.
8. San Francisco, USA
Set File Permissions
$ ./Packages/Framework/FLOW3/Scripts/setfilepermissions.sh robert _www _www
FLOW3 File Permission Script
Checking permissions from here upwards ...
(if a password prompt appears it's from sudo)
Password:
Making sure Data and Web/_Resources exist ...
Setting file permissions, this might take a minute ...
$
9. San Francisco, USA
Set Up Database
Configuration/Settings.yaml
# #
# Global Settings #
# #
FLOW3:
persistence:
backendOptions:
driver: 'pdo_mysql'
dbname: 'blog'
user: 'bloguser'
password: 'blogpassword'
host: '127.0.0.1'
path: '127.0.0.1'
port: 3306
doctrine:
dbal:
sessionInitialization: 'SET NAMES utf8 COLLATE utf8_unicode_ci'
10. San Francisco, USA
Set Up Virtual Host
Apache Virtual Host
<VirtualHost *:80>
DocumentRoot /opt/local/apache2/htdocs/Talks/FLOW3/Web/
ServerName dev.flow3.rob
SetEnv FLOW3_CONTEXT Development
</VirtualHost>
<VirtualHost *:80>
DocumentRoot /opt/local/apache2/htdocs/Talks/FLOW3/Web/
ServerName flow3.rob
SetEnv FLOW3_CONTEXT Production
</VirtualHost>
12. San Francisco, USA
Update from Git to Latest State
$ git submodule foreach "git checkout master"
-✂-----✂-----✂-----✂-----✂-----✂-----✂-----✂-----✂-----✂-----✂-----✂-
$ git submodule foreach "git pull --rebase"
Entering 'Build/Common'
First, rewinding head to replay your work on top of it...
Fast-forwarded master to 6f27f1784240b414e966ce0e5a12e23cb2f7ab02.
Entering 'Packages/Application/TYPO3'
First, rewinding head to replay your work on top of it...
Fast-forwarded master to 5187430ee44d579ae2bac825e2a069c4cd3f38a4.
Entering 'Packages/Application/TYPO3CR'
First, rewinding head to replay your work on top of it...
Fast-forwarded master to b1f5331aa51d390fa3d973404f31b9fd773f7059.
Entering 'Packages/Application/Twitter'
Current branch master is up to date.
…
13. San Francisco, USA
Hello World!
Package.php
<?php
namespace F3Demo;
use F3FLOW3PackagePackage as BasePackage;
class Package extends BasePackage {
}
Today:
$ ./flow3_dev flow3:package:create --package-key Demo
Soon:
$ ./flow3_dev flow3:package:create Demo
14. L i ve H ac k ing
5 1 1 1
K. Damb ek aln s & R. Lem ke
D.P. F l u x t r
time ();
15. San Francisco, USA
Hello World!
StandardController.php
<?php
namespace F3DemoController;
use F3FLOW3MVCControllerActionController;
class StandardController extends ActionController {
/**
* @param string $name
* @return string
*/
public function indexAction($name) {
return "Hello $name!";
}
}
?>
16. San Francisco, USA
Hello World!
http://dev.flow3.rob/demo/standard/index?name=Robert
Hello Robert!
17. San Francisco, USA
Tackling the Heart of Software Development
/**
Domain-Driven Design * Paper submitted by
*
a speaker
* @scope prototype
* @entity
A methodology which ... */
class Paper {
• results in rich domain models /**
* @var Participant
*/
• provides a common language protected $author;
across the project team /**
* @var string
*/
• simplify the design of complex protected $title;
applications /**
* @var string
*/
protected $shortAbstra
ct;
FLOW3 is the first PHP framework
/**
tailored to Domain-Driven Design * @var string
*/
protected $abstract;
18. San Francisco, USA
Domain-Driven Design
Domain
activity or business of the user
Domain-Driven Design
is about
• focussing on the domain and domain logic
• accurately mapping the concepts to software
• forming a ubiquitous language among the
project members
19. San Francisco, USA
Domain-Driven Design
Ubiquitous Language
• important prerequisite for successful
collaboration
• use the same words for
• discussion
• modeling
• development
• documentation
28. San Francisco, USA
Persistence
Object Persistence in the Flow
• based on Doctrine 2
• seamless integration into FLOW3
• provides all the great Doctrine 2 features
• uses UUIDs
• low level persistence API:
• allows for own, custom persistence
backends (instead of Doctrine 2)
• CouchDB is supported natively
29. San Francisco, USA
Basic Object Persistence
// Create a new customer and persist it:
$customer = new Customer("Robert");
$this->customerRepository->add($customer);
// Find an existing customer:
$otherCustomer = $this->customerRepository->findByFirstName("Karsten");
// and delete it:
$this->customerRepository->remove($otherCustomer);
30. San Francisco, USA
Advanced Queries
PostRepository.php
/**
* Finds most recent posts excluding the given post
*
* @param F3BlogDomainModelPost $post Post to exclude from result
* @param integer $limit The number of posts to return at max
* @return array All posts of the $post's blog except for $post
*/
public function findRecentExceptThis(F3BlogDomainModelPost $post, $limit = 20) {
$query = $this->createQuery();
$posts = $query->matching($query->equals('blog', $post->getBlog()))
->setOrderings(array('date' => F3FLOW3PersistenceQueryInterface::ORDER_DESCENDING))
->setLimit($limit)
->execute()
->toArray();
unset($posts[array_search($post, $posts)]);
return $posts;
// this is an alternative way of doing this when extending the Doctrine 2
// specific repository and using DQL.
return $this->entityManager
->createQuery('SELECT p FROM F3BlogDomainModelPost p WHERE p.blog = :blog' .
'AND NOT p = :excludedPost ORDER BY p.date DESC')
->setMaxResults($limit)
->execute(array('blog' => $post->getBlog(), 'excludedPost' => $post));
}
31. San Francisco, USA
Purely Doctrine 2
<?php
namespace MyExample;
/**
* @Entity(repositoryClass="BugRepository")
*/
class Bug {
/**
* @var integer
* @Id
* @Column(type="integer")
* @GeneratedValue
*/
public $id;
/**
* @var string
* @Column(type="string")
*/
public $description;
/**
* @var DateTime
32. San Francisco, USA
Doctrine 2 in FLOW3
<?php
namespace MyExample;
/**
* @Entity(repositoryClass="BugRepository")
*/
class Bug {
/**
* @var integer
* @Id
* @Column(type="integer")
* @GeneratedValue
*/
public $id;
/**
* @var string
* @Column(type="string")
*/
public $description;
/**
* @var DateTime
33. San Francisco, USA
Purely Doctrine 2
/**
* @var DateTime
* @Column(type="datetime")
*/
public $created;
/**
* @var User
* @ManyToOne(targetEntity="User", inversedBy="assignedBugs")
*/
private $engineer;
/**
* @var DoctrineCommonCollectionsArrayCollection<Product>
* @ManyToMany(targetEntity="Product")
*/
private $products;
}
?>
34. San Francisco, USA
Doctrine 2 in FLOW3
/**
* @var DateTime
* @Column(type="datetime")
*/
public $created;
/**
* @var User
* @ManyToOne(targetEntity="User", inversedBy="assignedBugs")
*/
private $engineer;
/**
* @var DoctrineCommonCollectionsArrayCollection<Product>
* @ManyToMany(targetEntity="Product")
*/
private $products;
}
?>
35. San Francisco, USA
Object Management
Dependency Injection
• a class doesn't create or retrieve the instance
of another class but get's it injected
• fosters loosely-coupling and high cohesion
‣ more stable, reusable code
36. San Francisco, USA
Object Management
FLOW3's take on Dependency Injection
• one of the first PHP implementations
(started in 2006, improved ever since)
• object management for the whole lifecycle of all objects
• no unnecessary configuration if information can be
gathered automatically (autowiring)
• intuitive use and no bad magical surprises
• fast! (like hardcoded or faster)
37. San Francisco, USA
War
Constructor Injection: Symfony 2 nin
g
(I'm
:m
igh
no t co
Sym
f nta
ony
exp in erro
<?php ert ..
.) rs
namespace AcmeDemoBundleController;
use SymfonyBundleFrameworkBundleControllerController;
use SymfonyComponentHttpFoundationRedirectResponse;
use SensioBundleFrameworkExtraBundleConfigurationRoute;
use SensioBundleFrameworkExtraBundleConfigurationTemplate;
use AcmeDemoBundleGreeterService;
class DemoController extends Controller {
/**
* @var AcmeDemoBundleGreeterService
*/
protected $greeterService;
/**
* @param AcmeDemoBundleGreeterService
*/
public function __construct($greeterService = NULL) {
$this->greeterService = $greeterService;
}
/**
* @Route("/hello/{name}", name="_demo_hello")
*/
public function helloAction($name) {
return new Response('Hello ' . $name, 200, array('Content-Type' => 'text/plain'));
}
}
38. San Francisco, USA
War
Constructor Injection: Symfony 2 nin
g
(I'm
:m
igh
no t co
Sym
f nta
ony
exp in erro
ert ..
.) rs
<?xml version="1.0" ?>
<container xmlns="http://symfony.com/schema/dic/services"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/
services-1.0.xsd">
<services>
<service id="acme.demo.greeterservice" class="AcmeDemoBundleGreeterService" public="false" />
<service id="acme.demo.democontroller" class="AcmeDemoBundleControllerDemoController">
<argument type="service" id="acme.demo.greeterservice" />
</service>
</services>
</container>
39. San Francisco, USA
Constructor Injection
<?php
namespace F3DemoController;
use F3FLOW3MVCControllerActionController;
use F3DemoServiceGreeterService;
class DemoController extends ActionController {
/**
* @var F3DemoServiceGreeterService
*/
protected $greeterService;
/**
* @param F3DemoServiceGreeterService
*/
public function __construct(F3DemoServiceGreeterService $greeterService) {
$this->greeterService = $greeterService;
}
/**
* @param string $name
*/
public function helloAction($name) {
return 'Hello ' . $name;
}
}
44. San Francisco, USA
Object Management
FLOW3's take on Dependency Injection
• one of the first PHP implementations
(started in 2006, improved ever since)
• object management for the whole lifecycle of all objects
• no unnecessary configuration if information can be
gatered automatically (autowiring)
• intuitive use and no bad magical surprises
• fast! (like hardcoded or faster)
45. San Francisco, USA
Object Management
class Customer {
/**
* @inject
* @var CustomerNumberGenerator
*/
protected $customerNumberGenerator;
...
}
$customer = new Customer();
$customer->getCustomerNumber();
46. San Francisco, USA
Object Management
<?php
declare(ENCODING = 'u
tf-8');
namespace F3Confere
nceDomain ModelConference;
/**
FLOW3 creates proxy classes * Autogenerated Prox
y Class
for realizing DI and AOP magic * @scope prototype
* @entity
*/
class Paper extends
• new operator is supported F3FLOW3Persistenc
Paper_Original implem
eAspectPersistence
ents F3FLOW3Object
MagicInterface {
Pr
/**
• proxy classes are created
* @var string
* @Id
on the fly
* @Column(length="40
")
* introduced by F3F
LOW3PersistenceAsp
*/ ectPersistenceMagic
• in production context all protected $FLOW3_Per
sistence_Identifier
= NULL;
code is static private $FLOW3_AOP_P
roxy_targetMethodsAn
dGroupedAdvices = ar
ra
private $FLOW3_AOP_P
roxy_groupedAdviceCh
ains = array();
private $FLOW3_AOP_P
roxy_methodIsInAdvic
eMode = array();
/**
* Autogenerated Prox
y Method
*/
public function __co
nstruct() {
47. Birt h o f a Blo g
5 3 1 1
K. Damb ek aln s & R. Lem ke
D.P. F l u x t r
time ();
48. San Francisco, USA
The Zen of Templating
FLOW3 comes with an elegant, flexible and secure
templating engine: Fluid
• templates are valid HTML
• templates contain no PHP code
• object access, control structures, loops ...
• designer-friendly
• extensible (view helpers, widgets)
49. San Francisco, USA
Fluid
Example for assigning a string to a Fluid variable:
// in the action controller:
$this->view->assign('title', 'Welcome to Fluid');
<!-- in the Fluid template: -->
<head>
<title>{title}</title>
</head>
50. San Francisco, USA
Fluid
Variables can also be objects:
// in the action controller:
$this->view->assign('conference', $conference);
<!-- in the Fluid template: -->
<div class="venue">
<p>Venue Street: {conference.venue.street}</p>
</div>
51. San Francisco, USA
Fluid
if-then-else:
// in the action controller:
$this->view->assign('post', $blogPost);
<!-- in the Fluid template: -->
<f:if condition="{post.comments}">
<f:then>There are some comments.</f:then>
<f:else>There are no comments.</f:else>
</f:if>
52. San Francisco, USA
Fluid
for-each:
// in the action controller:
$this->view->assign('ages', array("Karsten" => 34, "Robert" => 35));
<!-- in the Fluid template: -->
<ul>
<f:for each="{ages}" as="age" key="name">
<li>{name} is {age} year old.</li>
</f:for>
</ul>
53. San Francisco, USA
Fluid
for-each:
// in the action controller:
$this->view->assign('post', $blogPost);
<!-- in the Fluid template: -->
<f:if condition="{post.comments}">
<ul>
<f:for each="{post.comments}" as="comment" >
<li>{post.title}</li>
</f:for>
</ul>
</f:if>
54. San Francisco, USA
Fluid
View helpers – in this case the link.action view helper:
<!-- in the Fluid template: -->
{namespace f=F3FluidViewHelpers}
<f:link.action action="delete" arguments="{post: post, really: 'yes'}">
Delete this post
</f:link.action>
55. F lue n t F lu id
5 8 1 1
K. Damb ek aln s & R. Lem ke
D.P. F l u x t r
time ();
56. San Francisco, USA
Forms
<?php
namespace F3BlogDomainModel;
/**
* A blog post
*
* @scope prototype
* @entity
*/
class Post {
/**
* @var string
* @validate StringLength(minimum = 1, maximum = 100)
*/
protected $title;
/**
* @var string
* @validate StringLength(minimum = 1, maximum = 50)
*/
protected $author;
57. San Francisco, USA
Forms
<h2>Create a new post</h2>
<f:form action="create" object="{newPost}" name="newPost" enctype="multipart/form-data">
<label for="title">Title</label><br />
<f:form.textbox property="title" id="title" /><br />
<label for="content">Content</label><br />
<f:form.textarea property="content" rows="5" cols="40" id="content" /><br />
<label for="image">Image resource</label><br />
<f:form.textbox property="image.title" value="My image title" />
<f:form.upload property="image.originalResource" />
</f:form>
58. San Francisco, USA
Forms
<?php
namespace F3BlogController;
use F3FLOW3MVCControllerActionController;
class PostController extends ActionController {
/**
* @inject
* @var F3BlogDomainRepositoryPostRepository
*/
protected $postRepository;
/**
* Creates a new post
*
* @param F3BlogDomainModelPost $newPostadded to the repository
* @return void
*/
public function createAction(F3BlogDomainModelPost $newPost) {
$this->blog->addPost($newPost);
$this->flashMessageContainer->add('Your new post was created.');
$this->redirect('index');
}
61. San Francisco, USA
Validation
Validation is about different things
• incoming data needs to be validated for security reasons
• no evil markup in submitted content
• domain model integrity needs to be ensured
• an email needs to be (syntactically) valid
• credit card numbers should consist only of digits
62. San Francisco, USA
Validation
Validation in FLOW3
• you do not want to code checks into your controllers
• FLOW3 separates validation from your controller’s concerns
• no PHP code needed for validation
• declared through annotations
63. San Francisco, USA
Validation
Validation Models
• BaseProperties
rules defining the minimum requirements on individual properties of a
model
• BaseModel
rules or custom validators enforcing the minimum requirements on the
combination of properties of a model
• Supplemental
rules defining additional requirements on a model for a specific
situation (e.g. a certain action method)
64. San Francisco, USA
Validation
Base Properties
• Validation rules defined directly at the properties
/**
* @var string
* @validate StringLength(minimum = 10, maximum = 100)
*/
protected $title;
/**
* @var string
* @validate StringLength(minimum = 1, maximum = 50)
*/
protected $author;
65. San Francisco, USA
Validation
Validators
• validators provided by FLOW3 can be used through their short name
• Count, Float, NotEmpty, RegularExpression, Uuid, DateTime,
NumberRange, StringLength, Alphanumeric, Integer, Number, String,
EmailAddress, Label, Raw, Text
• custom validators need to implement the ValidatorInterface
• use them by specifying the fully qualified class name
/**
* @var DambekalnsStuffDomainModelStuff
* @validate DambekalnsStuffDomainValidatorStuffValidator
*/
protected $stuff;
66. San Francisco, USA
Schema Management
Automatic database updates
• when first running FLOW3 the schema will be created
• when a model has changed, the schema is updated
• be careful with existing data, updates can be destructive
• for production you should manually manage schema changes
67. San Francisco, USA
Schema Management
Manual database updates
• for simple situations this can be good enough:
$ ./flow3_dev flow3:doctrine:create
$ ./flow3_dev flow3:doctrine:update
• useful when
• you need to use an existing database dump
• using SQLite, due to limited schema change functionality
68. San Francisco, USA
Schema Management
Doctrine 2 Migrations
• Migrations allow schema versioning and
change deployment
• Migrations are the recommended way for
DB updates
• Tools to create and deploy migrations are
integrated with FLOW3
69. San Francisco, USA
Schema Management
Migrations Workflow
• use schema auto update in early development until your model is
ready for a first “freeze”, then switch off schema auto update and
drop your tables
• create migration diff and customize it
$ ./flow3_dev flow3:doctrine:migrationdiff
Generated new migration class to "…/Version20110608074324.php" from schema differences.
$ vi …/Version20110608074324.php
• migrate to create the tables
$ ./flow3_dev flow3:doctrine:migrate
71. San Francisco, USA
Schema Management
Migrations Workflow
• rinse and repeat: from now on create a new migration whenever
you changed your model classes
• generated migrations most probably need to be adjusted
• e.g. renaming a model means renaming a table, not dropping
and creating
• data migration needs to be added
• remember: good migrations make your user’s day
72. S ch e m at ic De mo
5 8 1 1
K. Damb ek aln s & R. Lem ke
D.P. F l u x t r
time ();
74. Sh e b a ng!
5 8 1 1
K. Damb ek aln s & R. Lem ke
D.P. F l u x t r
time ();
75. San Francisco, USA
Command Line Support
<?php
namespace F3FLOW3Command;
/**
* Package command controller to handle packages from CLI (create/activate/deactivate packages)
*
* @scope singleton
*/
class PackageCommandController extends F3FLOW3MVCControllerCommandController {
/**
* @inject
* @var F3FLOW3PackagePackageManagerInterface
*/
protected $packageManager;
/**
* Creates a new package
*
* Creates a new package with the given package key. The package key
* should be the vendor namespace segments.
*
* @param string $packageKey The package key of the package to create
* @return string
*/
public function createCommand($packageKey) {
if (!$this->packageManager->isPackageKeyValid($packageKey)) {
$this->response->appendContent('The package key "' . $packageKey . '" is not
76. San Francisco, USA
Security
Touchless Security, Flow-Style
• security is handled at a central place (through AOP)
• third-party code is as secure as possible by default
• modeled after our experiences in the TYPO3 project and
Spring Security (Java framework)
• provides authentication, authorization, validation, filtering ...
• can intercept arbitrary method calls
• transparently filters content through query-rewriting
• extensible for new authentication or authorization mechanisms
78. San Francisco, USA
Security
Cross-Site Request Forgery
• enables an attacker to execute privileged operations without being
authenticated
• the risk lies in using malicious links or forms while still being
authenticated
• imagine a link coming in through an URL shortener...
79. San Francisco, USA
Security
Avoiding Cross-Site Request Forgery
• add a (truly!) random string token to each link or form
• make sure this token is correct before executing anything
• change the token as often as possible to make it impossible to send
you a working malicious link while you’re logged in
• in most cases, we can assume that it should be enough to generate
one token when you log in – that’s the default
80. San Francisco, USA
Security
CSRF Protection in FLOW3
• you must not forget to add that token to any link
• FLOW3 automatically adds the CSRF token to each
• link you generate
• each form you create with Fluid
• and checks it for every call to a protected action
• the protection can be disabled using
@skipCsrfProtection on an action
81. Us e rs a n d L o g in
5 8 1 1
K. Damb ek aln s & R. Lem ke
D.P. F l u x t r
time ();
82. San Francisco, USA
AOP
Aspect-Oriented Programming
• programming paradigm
• separates concerns to improve modularization
• OOP modularizes concerns into objects
• AOP modularizes cross-cutting concerns into aspects
• FLOW3 makes it easy (and possible at all) to use AOP in PHP
83. San Francisco, USA
AOP
/**
* @aspect
FLOW3 uses AOP for ... * @introduce
*/
F3FLOW3Pers
istenceAspec
tPersistence
class Persist MagicInterfac
enceMagicAspe e, F3FLO
ct {
• persistence magic
/**
* @pointcut c
lassTaggedWit
*/ h(entity) ||
classTaggedWi
th(valueobjec
• logging public functi
on isEntityOr
ValueObject()
{}
t)
/**
* @var string
• debugging
* @Id
* @Column(len
gth="40")
* @introduce
F3FLOW3Pers
*/ istenceAspec
tPersistence
• security protected $FL
OW3_Persisten
ce_Identifier
;
MagicAspect->
isEnti
/**
* After retur
ning advice,
* making sure w
e have an UUI
* @param F3 D for each an
FLOW3AOPJoi d every
* @return voi nPointInterfa
d ce $joinPoint
* @before cla The current j
ssTaggedWith( oin po
*/ entity) && me
thod(.*->__co
public functi nstruct())
on generateUU
$proxy = $joi ID(F3FLOW3
nPoint->getPr AOPJoinPoint
oxy(); Interface $jo
F3FLOW3Ref inPoint)
lectionObjec
} tAccess::setP
roperty($prox
y , 'FLOW3_Per
siste
84. Th e Wiz a rd o f AOP
5 8 1 1
K. Damb ek aln s & R. Lem ke
D.P. F l u x t r
time ();
85. San Francisco, USA
Signal-Slot Event Handling
Signal
• can be fired on any event
• can be freely defined by the developer
Slot
• is invoked when a signal is emitted
• any method can be used as a slot
any signal can be wired to any slot
87. San Francisco, USA
Signal-Slot Event Handling
Signals are wired to Slots in a package’s bootstrap:
/**
* Invokes custom PHP code directly after the package manager has been
* initialized.
*
* @param F3FLOW3CoreBootstrap $bootstrap The current bootstrap
* @return void
*/
public function boot(F3FLOW3CoreBootstrap $bootstrap) {
$dispatcher = $bootstrap->getSignalSlotDispatcher();
$dispatcher->connect(
'F3BlogControllerCommentController', 'commentCreated',
'F3BlogServiceNotification', 'sendNewCommentNotification'
);
}
88. San Francisco, USA
Signal-Slot Event Handling
Any method can be a slot:
/**
* @param F3BlogDomainModelComment $comment
* @param F3BlogDomainModelPost $post
* @return void
*/
public function sendNewCommentNotification(F3BlogDomainModelComment $comment,
F3BlogDomainModelPost $post) {
$mail = new F3SwiftMailerMessage();
$mail
->setFrom(array('john@doe.org ' => 'John Doe'))
->setTo(array('karsten@typo3.org ' => 'Karsten Dambekalns'))
->setSubject('New comment on blog post "' . $post->getTitle() . '"')
->setBody($comment->getContent())
->send();
}
89. San Francisco, USA
Speed and Performance
For the snappy user experience:
• multi-layered, tagged caches
• various cache backends (file, Memcached, APC, Redis, PDO, ...)
• reverse-proxy support (Varnish, ESI) in the works
• code compilation
• regular benchmarks
• focus on good scalability
90. San Francisco, USA
More Features
• Resource Management (CDNs, private resources, ...)
• Logging
• File Monitoring
• Configuration Management
• Routing
• REST / SOAP
• ...
94. San Francisco, USA
Thank You!
• These slides: http://slideshare.net/robertlemke
• Download FLOW3: http://flow3.typo3.org
• Follow us on Twitter: @t3rob (Robert) @k_fish (Karsten)
• Give us feedback:
• robert@typo3.org / karsten@typo3.org
• http://joind.in/3535