Full video of this presentation: http://www.youtube.com/watch?v=iocO70tE-B4&feature=youtube_gdata_player
For a long time PHP was not really considered for enterprise projects with a complex business logic. Other programming languages and their respective frameworks have a much longer history in tackling extensive domains in a reliable manner. With the release of PHP 5 and its successor versions the game changed significantly. True object-orientation and design patterns became en vogue among PHP developers. Shortly before that time, the TYPO3 Open Source project decided to start over and develop FLOW3, a new application framework which introduces successful patterns and techniques from other programming language into PHP.
In this session you'll learn about FLOW3's approach is to deliver a whole-in-one concept for modern programming techniques and guiding developers to write excellent code. It introduces programming techniques such as Aspect-Oriented Programming and Domain-Driven Design to PHP, which were previously unseen in PHP projects. Finally you'll get an overview of FLOW3's key features and a good idea about if FLOW3 might be suitable for your next project.
Applications for the Enterprise with PHP (CPEurope)
1. Applications for the
Enterprise with PHP
Solve complex problems with excellence
and get back the joy of software development.
2. @robertlemke
project founder of FLOW3 / 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
24. Network Working Group R. Fielding
Request for Comments: 2616 UC Irvine
Obsoletes: 2068 J. Gettys
Category: Standards Track Compaq/W3C
J. Mogul
Compaq
H. Frystyk
W3C/MIT
L. Masinter
Xerox
P. Leach
Microsoft
T. Berners-Lee
W3C/MIT
June 1999
Hypertext Transfer Protocol -- HTTP/1.1
Status of this Memo
This document specifies an Internet standards track protocol for the
Internet community, and requests discussion and suggestions for
improvements. Please refer to the current edition of the "Internet
25. HTTP/1.1 has been designed to allow implementations of applications
/**
that do not depend on knowledge of ranges.
* Represents a HTTP request
*/
4 HTTP Message
class Request extends Message {
4.1 Message Types
/**
* @var string
HTTP messages consist of requests from client to server and responses
*/
from server to client.
protected $method = 'GET';
HTTP-message = Request | Response ; HTTP/1.1 messages
/**
* @var TYPO3FLOW3HttpUri
Request (section 5) and Response (section 6) messages use the generic
*/
message format of RFC 822 [9] for transferring entities (the payload
protected $uri;
of the message). Both types of message consist of a start-line, zero
or more header fields (also known as "headers"), an empty line (i.e.,
/**
a line with nothing preceding the CRLF) indicating the end of the
* @var TYPO3FLOW3HttpUri
header fields, and possibly a message-body.
*/
protected $baseUri;
generic-message = start-line
*(message-header CRLF)
/**
CRLF
* @var array
[ message-body ]
*/
start-line = Request-Line | Status-Line
protected $arguments;
29. # set cookie in response:
$response->setCookie(new Cookie('counter', 1));
# retrieve cookie on next request:
$cookie = $request->getCookie('counter');
34. <?php
namespace AcmeDemoController;
use TYPO3FLOW3MvcControllerActionController;
use AcmeDemoDomainModelBook;
class BookController extends ActionController {
/**
* @return void
*/
public function indexAction() {
$book = new Book();
$book->setTitle('Manual del Guerrero de la Luz');
$books = array($book);
$this->view->assign('books', $books);
}
}
37. public function createAction(Book $book) {
if (!$this->securityManager->hasRole('BookAdmin')) {
throw new Exception('Not allowed.');
}
$statementHandle = $this->databaseHandle->prepare(
'INSERT INTO "books" ("identifier", "title", "isbn") ' .
'VALUES (?, ?, ?)'
);
$result = $statementHandle->execute(
array($book->getId(), $book->getTitle(), $book->getIsbn())
);
if ($result === FALSE) {
throw new Exception('Could not create book.');
}
}
38. class Book extends BaseModel {
protected $id;
protected $title;
protected $isbn;
…
public function __construct() {
$this->id = TYPO3FLOW3UtilityAlgorithms::generateUUID();
}
…
public function getSalesVolume() {
if (!$this->securityManager->hasRole('Management')) {
throw new Exception('Access Denied');
}
$statementHandle = $this->databaseHandle->prepare(
'SELECT "identifier" FROM "orders" WHERE "date">? AND "
$result = $statementHandle->execute(array(time() - 604800));
if ($result === FALSE) {
39. Tackling the Heart of Software Development
/**
Domain-Driven Design * A Book
*
* @FLOW3Scope(“protot
ype”)
* @FLOW3Entity
A methodology which ... */
class Book {
• results in rich domain models /**
* @var string
*/
• provides a common language protected $title;
across the project team /**
* @var string
*/
• simplify the design of complex protected $isbn;
applications /**
* @var string
*/
protected $description
;
FLOW3 is the first PHP framework
/**
tailored to Domain-Driven Design * @var integer
*/
protected $price;
41. /**
* Get the Book's title
*
* @return string The Book's title
*/
public function getTitle() {
return $this->title;
}
/**
* Sets this Book's title
*
* @param string $title The Book's title
* @return void
*/
public function setTitle($title) {
$this->title = $title;
}
42. /**
* Get the Book's Sales Volume
*
* @return integer The Book's sales volume
*/
public function getSalesVolume() {
$time = new DateTime('last month');
$total = $this->bookRepository->calculateTotalSalesSince($time);
return $total;
}
43. interface RepositoryInterface {
/**
* Adds an object to this repository.
* @param object $object The object to add
* @return void
*/
public function add($object);
/**
* Removes an object from this repository.
* @param object $object The object to remove
* @return void
*/
public function remove($object);
/**
* Returns all objects of this repository.
* @return TYPO3FLOW3PersistenceQueryResultInterface The que
*/
public function findAll();
44. /**
* A repository for Books
*
* @FLOW3Scope("singleton")
*/
class BookRepository extends Repository {
/**
* Returns the total sales volume
*
* @param DateTime $time
*/
public function calculateTotalSalesSince(DateTime $time) {
# implementation …
}
}
45. /**
* Adds the given new book object to the book repository
*
* @param AcmeDemoDomainModelBook $newBook A new book to ad
* @return void
*/
public function createAction(Book $newBook) {
$this->bookRepository->add($newBook);
$this->redirect('index');
}
54. class Foo {
protected static $instance;
public function getInstance() {
if (self::$instance === NULL) {
self::$instance = new self;
}
return self::$instance;
}
}
class Bar {
public function action() {
$foo = Foo::getInstance();
}
}
55. class ServiceLocator {
protected static $services = array();
public function get($serviceName) {
return self::$services[$serviceName];
}
}
class Bar {
public function action() {
$foo = ServiceLocator::get('Foo');
}
}
56. class Bar {
/**
* @var Foo
*/
protected $foo;
/**
* @param Foo $foo
*/
public function __construct(Foo $foo) {
$this->foo = $foo;
}
/**
* @return string
*/
public function action() {
$this->foo->doSomething();
}
}
57. class Bar {
/**
* @var Foo
* @FLOW3Inject
*/
protected $foo;
/**
* @return string
*/
public function action() {
$this->foo->doSomething();
}
}
59. Object Management
FLOW3's take on Dependency Injection
• one of the first PHP implementations
(started in 2006, improved ever since)
60. 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
61. 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)
62. 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
63. 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)
67. namespace AcmeDemoAspect;
use TYPO3FLOW3AopJoinPoint;
use TYPO3FLOW3AnnotationsAround;
class BetterWorldAspect {
/**
* Advice which tweaks the HelloWorld controller
*
* @param JoinPoint $joinPoint
* @Around("method(.*Controller->greetAction())")
*/
public function someAdvice(JoinPoint $joinPoint) {
$name = $joinPoint->getMethodArgument('name');
return sprintf("%s, you're running out of time!", $name);
}
}
83. /**
* Kickstart a new action controller
*
* Generates an Action Controller with the given name in the specified package.
* In its default mode it will create just the controller containing a sample
* indexAction.
*
* By specifying the --generate-actions flag, this command will also create a
* set of actions. If no model or repository exists which matches the
* controller name (for example "CoffeeRepository" for "CoffeeController"),
* an error will be shown.
*
* Likewise the command exits with an error if the specified package does not
* exist. By using the --generate-related flag, a missing package, model or
* repository can be created alongside, avoiding such an error.
*
* By specifying the --generate-templates flag, this command will also create
* matching Fluid templates for the actions created. This option can only be
* used in combination with --generate-actions.
*
* The default behavior is to not overwrite any existing code. This can be
* overridden by specifying the --force flag.
84. * By specifying the --generate-templates flag, this command will also create
* matching Fluid templates for the actions created. This option can only be
* used in combination with --generate-actions.
*
* The default behavior is to not overwrite any existing code. This can be
* overridden by specifying the --force flag.
*
* @param string $packageKey The package key of the package for the new controller with
* @param string $controllerName The name for the new controller. This may also be a com
* @param boolean $generateActions Also generate index, show, new, create, edit, update
* @param boolean $generateTemplates Also generate the templates for each action.
* @param boolean $generateRelated Also create the mentioned package, related model and
* @param boolean $force Overwrite any existing controller or template code. Regardless
* @return string
* @see typo3.kickstart:kickstart:commandcontroller
*/
public function actionControllerCommand($packageKey, $controllerName, $generateActions =
$subpackageName = '';
if (strpos('/', $packageKey) !== FALSE) {
list($packageKey, $subpackageName) = explode('/', $packageKey, 2);
}
if (!$this->packageManager->isPackageKeyValid($packageKey)) {
85.
86. Rossmann
• second biggest drug store
in Germany
• 5,13 billion € turnover
• 31,000 employees
Customer Database
87. Amadeus
• world’s biggest
e-ticket provider
• 217 markets
• 948 million billable
transactions / year
• 2,7 billion € revenue
Social Media Suite
88. At a Glance
FLOW3 is a web application platform
• holistic concept for your apps
• modular, extensible, package based
• pedantically clean with focus on quality
• puts a smile on developer’s faces
• free & Open Source (LGPL v3)
• backed by one of the largest Open Source projects
89. 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