FLOW3 1.0 – scheduled for the 2nd quarter of 2011 – is an application framework aiming to back up developers with security and infrastructure while they focus on the application logic. With Domain-Driven Design as its major underlying concept, FLOW3 is easy to learn but flexible enough for complex projects.
This session from the International PHP Conference 2011 (Spring) provides a comprehensive overview of the main strengths of FLOW3.
2. Robert Lemke
chief "architect" of TYPO3 5.0 and FLOW3
co-founder of the TYPO3 Association
35 years old
lives in Lübeck, Germany
1 wife, 1 daughter, 1 espresso machine
likes drumming
3. At a Glance
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
4. 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
5. Work in Progress
WARNING
The current documen
tation of FLOW3 does
cover the version in not
our Git master – a lo
changed since the la t has
st alpha release!
We are currently upd
ating the manuals an
tutorials for the 1.0 b d
eta release though.
6. Hello World!
Package.php
<?php
namespace F3Demo;
use F3FLOW3PackagePackage as BasePackage;
class Package extends BasePackage {
}
$ ./flow3_dev flow3:package:create Demo
7. Hello World!
StandardController.php
<?php
namespace F3DemoController;
use F3FLOW3MVCControllerActionController;
class StandardController extends ActionController {
/**
* @param string $name
* @return string
*/
public function indexAction($name) {
return "Hello $name!";
}
}
?>
9. Tackling the Heart of Software Development
/**
Domain-Driven Design * Paper submmited by
*
a speaker
* @scope prototype
* @entity
A methodology which ... */
class Paper {
• results in rich domain models /**
* @var Participant
*/
• provides a common language protected $author;
across the project team /**
* @var string
*/
• simplify the design of complex protected $title;
applications /**
* @var string
*/
protected $shortAbstra
ct;
FLOW3 is the first PHP framework
/**
tailored to Domain-Driven Design * @var string
*/
protected $abstract;
11. 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
12. Basic Object Persistence
// Create a new customer and persist it:
$customer = new Customer("Robert");
$this->customerRepository->add($customer);
// Find an existing customer:
$otherCustomer = $this->customerRepository->findByFirstName("Karsten");
// and delete it:
$this->customerRepository->remove($otherCustomer);
13. Advanced Queries
PostRepository.php
/**
* Finds most recent posts excluding the given post
*
* @param F3BlogDomainModelPost $post Post to exclude from result
* @param integer $limit The number of posts to return at max
* @return array All posts of the $post's blog except for $post
*/
public function findRecentExceptThis(F3BlogDomainModelPost $post, $limit = 20) {
$query = $this->createQuery();
$posts = $query->matching($query->equals('blog', $post->getBlog()))
->setOrderings(array('date' => F3FLOW3PersistenceQueryInterface::ORDER_DESCENDING))
->setLimit($limit)
->execute()
->toArray();
unset($posts[array_search($post, $posts)]);
return $posts;
// this is an alternative way of doing this when extending the Doctrine 2
// specific repository and using DQL.
return $this->entityManager
->createQuery('SELECT p FROM F3BlogDomainModelPost p WHERE p.blog = :blog' .
'AND NOT p = :excludedPost ORDER BY p.date DESC')
->setMaxResults($limit)
->execute(array('blog' => $post->getBlog(), 'excludedPost' => $post));
}
18. Object Management
Dependency Injection
• a class doesn't create or retrieve the instance
of another class but get's it injected
• fosters loosely-coupling and high cohesion
‣ more stable, reusable code
19. Object Management
FLOW3's 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)
20. 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'));
}
}
21. 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>
22. Constructor Injection
<?php
namespace F3DemoController;
use F3FLOW3MVCControllerActionController;
use F3DemoServiceGreeterService;
class DemoController extends ActionController {
/**
* @var F3DemoServiceGreeterService
*/
protected $greeterService;
/**
* @param F3DemoServiceGreeterService
*/
public function __construct(F3DemoServiceGreeterService $greeterService) {
$this->greeterService = $greeterService;
}
/**
* @param string $name
*/
public function helloAction($name) {
return 'Hello ' . $name;
}
}
27. 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)
29. Object Management
<?php
declare(ENCODING = 'u
tf-8');
namespace F3Confere
nceDomain ModelConference;
/**
FLOW3 creates proxy classes * Autogenerated Prox
y Class
for realizing DI and AOP magic * @scope prototype
* @entity
*/
class Paper extends
• new operator is supported F3FLOW3Persistenc
Paper_Original implem
eAspectPersistence
ents F3FLOW3Object
MagicInterface {
Pr
/**
• proxy classes are created
* @var string
* @Id
on the fly
* @Column(length="40
")
* introduced by F3F
LOW3PersistenceAsp
*/ ectPersistenceMagic
• in production context all protected $FLOW3_Per
sistence_Identifier
= NULL;
code is static private $FLOW3_AOP_P
roxy_targetMethodsAn
dGroupedAdvices = ar
ra
private $FLOW3_AOP_P
roxy_groupedAdviceCh
ains = array();
private $FLOW3_AOP_P
roxy_methodIsInAdvic
eMode = array();
/**
* Autogenerated Prox
y Method
*/
public function __co
nstruct() {
30. AOP
Aspect-Oriented Programming
• programming paradigm
• separates concerns to improve modularization
• OOP modularizes concerns into objects
• AOP modularizes cross-cutting concerns into aspects
• FLOW3 makes it easy (and possible at all) to use AOP in PHP
31. AOP
/**
* @aspect
FLOW3 uses AOP for ... * @introduce
*/
F3FLOW3Pers
istenceAspec
tPersistence
class Persist MagicInterfac
enceMagicAspe e, F3FLO
ct {
• persistence magic
/**
* @pointcut c
lassTaggedWit
*/ h(entity) ||
classTaggedWi
th(valueobjec
• logging public functi
on isEntityOr
ValueObject()
{}
t)
/**
* @var string
• debugging
* @Id
* @Column(len
gth="40")
* @introduce
F3FLOW3Pers
*/ istenceAspec
tPersistence
• security protected $FL
OW3_Persisten
ce_Identifier
;
MagicAspect->
isEnti
/**
* After retur
ning advice,
* making sure w
e have an UUI
* @param F3 D for each an
FLOW3AOPJoi d every
* @return voi nPointInterfa
d ce $joinPoint
* @before cla The current j
ssTaggedWith( oin po
*/ entity) && me
thod(.*->__co
public functi nstruct())
on generateUU
$proxy = $joi ID(F3FLOW3
nPoint->getPr AOPJoinPoint
oxy(); Interface $jo
F3FLOW3Ref inPoint)
lectionObjec
} tAccess::setP
roperty($prox
y , 'FLOW3_Per
siste
32. Security
Touchless Security, Flow-Style
• security is handled at a central place (through AOP)
• third-party code is as secure as possible by default
• modeled after our experiences in the TYPO3 project and
Spring Security (Java framework)
• provides authentication, authorization, validation, filtering ...
• can intercept arbitrary method calls
• transparently filters content through query-rewriting
• extensible for new authentication or authorization mechanisms
34. The Zen of Templating
FLOW3 comes with an elegant, flexible and secure
templating engine: Fluid
• templates are valid HTML
• templates contain no PHP
• object access, control structures, loops ...
• designer-friendly
• extensible (view helpers, widgets)
35. The Zen of Templating
...
<body>
<h1>Latest Blog Posts</h1>
<f:if condition="{posts}">
<f:then>
<ol>
<f:for each="{posts}" as="post">
<li class="post">
<h2>
<f:link.action action="show" controller="Post" arguments="{post: post}">{post.title}
<f:security.ifHasRole role="Editor">
<f:link.action action="edit" arguments="{post: post}" controller="Post"><img src
<f:link.action onclick="return confirm('Really delete this post?');" action="del
</f:security.ifHasRole>
</h2>
<f:render partial="PostMetaData" arguments="{post: post}"/>
<f:link.action action='show' arguments='{post: post}'>Read more</f:link.action></p>
</li>
</f:for>
</ol>
</f:then>
<f:else>
<p>This blog currently doesn't contain any posts.
<f:link.action action="new" controller="Post">Create the first post</f:link.action>
</p>
</f:else>
</f:if>
</f:section>
36. 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;
38. 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');
}
39. Speed and Performance
For the snappy user experience:
• multi-layered, tagged caches
• various cache backends (file, Memcached, APC, Redis, PDO, ...)
• reverse-proxy support (Varnish, ESI) in the works
• code compilation
• regular benchmarks
• focus on good scalibility
44. Thank You!
• These slides: http://slideshare.net/robertlemke
• Download FLOW3: http://flow3.typo3.org
• Follow me on Twitter: @t3rob
• Give me feedback:
• robert@typo3.org
• http://joind.in/3492