Download - Fluent Development with FLOW3 1.0
![Page 1: Fluent Development with FLOW3 1.0](https://reader035.vdocuments.us/reader035/viewer/2022070313/554a06c1b4c905557a8b5595/html5/thumbnails/1.jpg)
San Francisco, USA
Fluent Development with FLOW3
Karsten Dambekalns & Robert Lemke
![Page 2: Fluent Development with FLOW3 1.0](https://reader035.vdocuments.us/reader035/viewer/2022070313/554a06c1b4c905557a8b5595/html5/thumbnails/2.jpg)
San Francisco, USA
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
Karsten Dambekalns
![Page 3: Fluent Development with FLOW3 1.0](https://reader035.vdocuments.us/reader035/viewer/2022070313/554a06c1b4c905557a8b5595/html5/thumbnails/3.jpg)
San Francisco, USA
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
Robert Lemke
![Page 4: Fluent Development with FLOW3 1.0](https://reader035.vdocuments.us/reader035/viewer/2022070313/554a06c1b4c905557a8b5595/html5/thumbnails/4.jpg)
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
![Page 5: Fluent Development with FLOW3 1.0](https://reader035.vdocuments.us/reader035/viewer/2022070313/554a06c1b4c905557a8b5595/html5/thumbnails/5.jpg)
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
![Page 6: Fluent Development with FLOW3 1.0](https://reader035.vdocuments.us/reader035/viewer/2022070313/554a06c1b4c905557a8b5595/html5/thumbnails/6.jpg)
San Francisco, USA
Work in Progress
WARNING
The current documentation of FLOW3 does not cover the version in our Git master – a lot has changed since the last alpha release!
We are currently updating the manuals and tutorials for the 1.0 beta release though.
![Page 7: Fluent Development with FLOW3 1.0](https://reader035.vdocuments.us/reader035/viewer/2022070313/554a06c1b4c905557a8b5595/html5/thumbnails/7.jpg)
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.
![Page 8: Fluent Development with FLOW3 1.0](https://reader035.vdocuments.us/reader035/viewer/2022070313/554a06c1b4c905557a8b5595/html5/thumbnails/8.jpg)
San Francisco, USA
Set File Permissions
$ ./Packages/Framework/FLOW3/Scripts/setfilepermissions.sh robert _www _wwwFLOW3 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 ...
$
![Page 9: Fluent Development with FLOW3 1.0](https://reader035.vdocuments.us/reader035/viewer/2022070313/554a06c1b4c905557a8b5595/html5/thumbnails/9.jpg)
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'
![Page 10: Fluent Development with FLOW3 1.0](https://reader035.vdocuments.us/reader035/viewer/2022070313/554a06c1b4c905557a8b5595/html5/thumbnails/10.jpg)
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>
![Page 11: Fluent Development with FLOW3 1.0](https://reader035.vdocuments.us/reader035/viewer/2022070313/554a06c1b4c905557a8b5595/html5/thumbnails/11.jpg)
San Francisco, USA
Final Check
![Page 12: Fluent Development with FLOW3 1.0](https://reader035.vdocuments.us/reader035/viewer/2022070313/554a06c1b4c905557a8b5595/html5/thumbnails/12.jpg)
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.…
![Page 13: Fluent Development with FLOW3 1.0](https://reader035.vdocuments.us/reader035/viewer/2022070313/554a06c1b4c905557a8b5595/html5/thumbnails/13.jpg)
San Francisco, USA
Hello World!
Package.php
<?phpnamespace F3\Demo;
use \F3\FLOW3\Package\Package as BasePackage;
class Package extends BasePackage {}
$ ./flow3_dev flow3:package:create --package-key Demo
$ ./flow3_dev flow3:package:create Demo
Soon:
Today:
![Page 14: Fluent Development with FLOW3 1.0](https://reader035.vdocuments.us/reader035/viewer/2022070313/554a06c1b4c905557a8b5595/html5/thumbnails/14.jpg)
K. Dambekalns & R. LemkeD.P. Fluxtr
time();
5 1 11
Live Hacking
![Page 15: Fluent Development with FLOW3 1.0](https://reader035.vdocuments.us/reader035/viewer/2022070313/554a06c1b4c905557a8b5595/html5/thumbnails/15.jpg)
San Francisco, USA
Hello World!
<?phpnamespace F3\Demo\Controller;
use \F3\FLOW3\MVC\Controller\ActionController;
class StandardController extends ActionController { /** * @param string $name * @return string */ public function indexAction($name) { return "Hello $name!"; }}
?>
StandardController.php
![Page 16: Fluent Development with FLOW3 1.0](https://reader035.vdocuments.us/reader035/viewer/2022070313/554a06c1b4c905557a8b5595/html5/thumbnails/16.jpg)
San Francisco, USA
Hello World!
http://dev.flow3.rob/demo/standard/index?name=Robert
Hello Robert!
![Page 17: Fluent Development with FLOW3 1.0](https://reader035.vdocuments.us/reader035/viewer/2022070313/554a06c1b4c905557a8b5595/html5/thumbnails/17.jpg)
San Francisco, USA
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
/** * Paper submitted by a speaker * * @scope prototype * @entity */class Paper {
/** * @var Participant */ protected $author;
/** * @var string */ protected $title;
/** * @var string */ protected $shortAbstract;
/** * @var string */ protected $abstract;
/** * @var \SplObjectStorage */ protected $materials;
/** * @var \F3\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 \F3\Conference\Domain\Model\Participant $author * @return void * @author Robert Lemke <[email protected]> */ public function setAuthor(\F3\Conference\Domain\Model\Participant $author) { $this->author = $author; }
/** * Getter for the author of this paper * * @return \F3\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 \F3\Conference\Domain\Model\SessionType $proposedSessionType The proposed session type * @return void * @author Robert Lemke <[email protected]> */ public function setProposedSessionType(\F3\Conference\Domain\Model\SessionType $proposedSessionType) { $this->proposedSessionType = $proposedSessionType; }
/** * Getter for the proposed session type * * @return \F3\Conference\Domain\Model\SessionType The proposed session type * @author Robert Lemke <[email protected]> */ public function getProposedSessionType() { return $this->proposedSessionType; }}?>
![Page 18: Fluent Development with FLOW3 1.0](https://reader035.vdocuments.us/reader035/viewer/2022070313/554a06c1b4c905557a8b5595/html5/thumbnails/18.jpg)
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
![Page 19: Fluent Development with FLOW3 1.0](https://reader035.vdocuments.us/reader035/viewer/2022070313/554a06c1b4c905557a8b5595/html5/thumbnails/19.jpg)
San Francisco, USA
Domain-Driven Design
Ubiquitous Language
• important prerequisite for successful collaboration
• use the same words for
• discussion
• modeling
• development
• documentation
![Page 20: Fluent Development with FLOW3 1.0](https://reader035.vdocuments.us/reader035/viewer/2022070313/554a06c1b4c905557a8b5595/html5/thumbnails/20.jpg)
San Francisco, USA
Domain: Conference
![Page 21: Fluent Development with FLOW3 1.0](https://reader035.vdocuments.us/reader035/viewer/2022070313/554a06c1b4c905557a8b5595/html5/thumbnails/21.jpg)
K. Dambekalns & R. LemkeD.P. Fluxtr
time();
5 1 12
Extreme Modeling
![Page 22: Fluent Development with FLOW3 1.0](https://reader035.vdocuments.us/reader035/viewer/2022070313/554a06c1b4c905557a8b5595/html5/thumbnails/22.jpg)
San Francisco, USA
Example Model: Paper
/** * A Paper * * @scope prototype * @entity */class Paper {
/** * @var \F3\Conference\Domain\Model\Account\Participant * @ManyToOne(cascade={"persist"}) * @validate NotEmpty */ protected $author;
/** * @var string * @validate StringLength(minimum = 1, maximum = 50) */ protected $title;
![Page 23: Fluent Development with FLOW3 1.0](https://reader035.vdocuments.us/reader035/viewer/2022070313/554a06c1b4c905557a8b5595/html5/thumbnails/23.jpg)
San Francisco, USA
Example Model: Paper
/** * @var string * @Column(type="text") * @validate StringLength(minimum = 30, maximum = 150) */ protected $shortAbstract;
/** * @var string * @Column(type="text") * @validate StringLength(minimum = 100, maximum = 1000) */ protected $abstract;
/** * @var \F3\Conference\Domain\Model\Conference\SessionType * @ManyToOne(cascade={"persist"}) * @validate NotEmpty */ protected $proposedSessionType;
![Page 24: Fluent Development with FLOW3 1.0](https://reader035.vdocuments.us/reader035/viewer/2022070313/554a06c1b4c905557a8b5595/html5/thumbnails/24.jpg)
San Francisco, USA
Example Model: Paper
/** * @var \F3\Conference\Domain\Model\Conference\Track * @ManyToOne(cascade={"persist"}) * @validate NotEmpty */ protected $proposedTrack;
/** * @var \Doctrine\Common\Collections\ArrayCollection<\F3\Conference\Domain\Model\Comment> * @ManyToMany(cascade={"persist", "remove"}) */ protected $comments;
/** * @var string */ protected $slideShareUrl;
/** * @var string */ protected $tags;
![Page 25: Fluent Development with FLOW3 1.0](https://reader035.vdocuments.us/reader035/viewer/2022070313/554a06c1b4c905557a8b5595/html5/thumbnails/25.jpg)
San Francisco, USA
Example Model: Paper
/** * @var string * @Column(type="text", nullable=true) */ protected $links;
/** * @var \Doctrine\Common\Collections\ArrayCollection<\F3\Conference\Domain\Model\Account\Participant> * @ManyToMany(cascade={"all"}) */ protected $speakers;
/** * one of the STATUS_* constants * @var string */ protected $status = self::STATUS_DRAFT;
![Page 26: Fluent Development with FLOW3 1.0](https://reader035.vdocuments.us/reader035/viewer/2022070313/554a06c1b4c905557a8b5595/html5/thumbnails/26.jpg)
San Francisco, USA
Example Model: Paper
/** * STATUS_* constants */ const STATUS_DRAFT = 'draft'; const STATUS_SUBMITTED = 'submitted'; const STATUS_REJECTED = 'rejected'; const STATUS_ACCEPTED = 'accepted'; const STATUS_SCHEDULED = 'scheduled';
public function __construct() { $this->comments = new \Doctrine\Common\Collections\ArrayCollection(); $this->speakers = new \Doctrine\Common\Collections\ArrayCollection(); }
/** * @param \F3\Conference\Domain\Model\Account\Participant $author * @return void */ public function setAuthor(\F3\Conference\Domain\Model\Account\Participant $author) { $this->author = $author; }
/** * @return \F3\Conference\Domain\Model\Account\Participant */ public function getAuthor() {
![Page 27: Fluent Development with FLOW3 1.0](https://reader035.vdocuments.us/reader035/viewer/2022070313/554a06c1b4c905557a8b5595/html5/thumbnails/27.jpg)
San Francisco, USA
Domain-Driven Design
![Page 28: Fluent Development with FLOW3 1.0](https://reader035.vdocuments.us/reader035/viewer/2022070313/554a06c1b4c905557a8b5595/html5/thumbnails/28.jpg)
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
![Page 29: Fluent Development with FLOW3 1.0](https://reader035.vdocuments.us/reader035/viewer/2022070313/554a06c1b4c905557a8b5595/html5/thumbnails/29.jpg)
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);
![Page 30: Fluent Development with FLOW3 1.0](https://reader035.vdocuments.us/reader035/viewer/2022070313/554a06c1b4c905557a8b5595/html5/thumbnails/30.jpg)
San Francisco, USA
Advanced Queries
/** * Finds most recent posts excluding the given post * * @param \F3\Blog\Domain\Model\Post $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(\F3\Blog\Domain\Model\Post $post, $limit = 20) { $query = $this->createQuery(); $posts = $query->matching($query->equals('blog', $post->getBlog())) ->setOrderings(array('date' => \F3\FLOW3\Persistence\QueryInterface::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 \F3\Blog\Domain\Model\Post p WHERE p.blog = :blog' .
'AND NOT p = :excludedPost ORDER BY p.date DESC') ->setMaxResults($limit) ->execute(array('blog' => $post->getBlog(), 'excludedPost' => $post)); }
PostRepository.php
![Page 31: Fluent Development with FLOW3 1.0](https://reader035.vdocuments.us/reader035/viewer/2022070313/554a06c1b4c905557a8b5595/html5/thumbnails/31.jpg)
San Francisco, USA
Purely Doctrine 2
<?phpnamespace My\Example;
/** * @Entity(repositoryClass="BugRepository") */class Bug {
/** * @var integer * @Id * @Column(type="integer") * @GeneratedValue */ public $id;
/** * @var string * @Column(type="string") */ public $description;
/** * @var \DateTime * @Column(type="datetime") */ public $created;
/** * @var User * @ManyToOne(targetEntity="User", inversedBy="assignedBugs") */ private $engineer;
/** * @var \Doctrine\Common\Collections\ArrayCollection<Product> * @ManyToMany(targetEntity="Product") */ private $products;}
?>
![Page 32: Fluent Development with FLOW3 1.0](https://reader035.vdocuments.us/reader035/viewer/2022070313/554a06c1b4c905557a8b5595/html5/thumbnails/32.jpg)
San Francisco, USA
Doctrine 2 in FLOW3
<?phpnamespace My\Example;
/** * @Entity(repositoryClass="BugRepository") */class Bug {
/** * @var integer * @Id * @Column(type="integer") * @GeneratedValue */ public $id;
/** * @var string * @Column(type="string") */ public $description;
/** * @var \DateTime * @Column(type="datetime") */ public $created;
/** * @var User * @ManyToOne(targetEntity="User", inversedBy="assignedBugs") */ private $engineer;
/** * @var \Doctrine\Common\Collections\ArrayCollection<Product> * @ManyToMany(targetEntity="Product") */ private $products;}
?>
![Page 33: Fluent Development with FLOW3 1.0](https://reader035.vdocuments.us/reader035/viewer/2022070313/554a06c1b4c905557a8b5595/html5/thumbnails/33.jpg)
San Francisco, USA
Purely Doctrine 2
/** * @var \DateTime * @Column(type="datetime") */ public $created;
/** * @var User * @ManyToOne(targetEntity="User", inversedBy="assignedBugs") */ private $engineer;
/** * @var \Doctrine\Common\Collections\ArrayCollection<Product> * @ManyToMany(targetEntity="Product") */ private $products;}
?>
![Page 34: Fluent Development with FLOW3 1.0](https://reader035.vdocuments.us/reader035/viewer/2022070313/554a06c1b4c905557a8b5595/html5/thumbnails/34.jpg)
San Francisco, USA
Doctrine 2 in FLOW3
/** * @var \DateTime * @Column(type="datetime") */ public $created;
/** * @var User * @ManyToOne(targetEntity="User", inversedBy="assignedBugs") */ private $engineer;
/** * @var \Doctrine\Common\Collections\ArrayCollection<Product> * @ManyToMany(targetEntity="Product") */ private $products;}
?>
![Page 35: Fluent Development with FLOW3 1.0](https://reader035.vdocuments.us/reader035/viewer/2022070313/554a06c1b4c905557a8b5595/html5/thumbnails/35.jpg)
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
![Page 36: Fluent Development with FLOW3 1.0](https://reader035.vdocuments.us/reader035/viewer/2022070313/554a06c1b4c905557a8b5595/html5/thumbnails/36.jpg)
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)
![Page 37: Fluent Development with FLOW3 1.0](https://reader035.vdocuments.us/reader035/viewer/2022070313/554a06c1b4c905557a8b5595/html5/thumbnails/37.jpg)
San Francisco, USA
<?phpnamespace Acme\DemoBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;use Symfony\Component\HttpFoundation\RedirectResponse;use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;use Acme\DemoBundle\GreeterService;
class DemoController extends Controller { /** * @var \Acme\DemoBundle\GreeterService */ protected $greeterService;
/** * @param \Acme\DemoBundle\GreeterService */ 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')); }}
Constructor Injection: Symfony 2Warning: might contain errors
(I'm no Symfony expert ...)
![Page 38: Fluent Development with FLOW3 1.0](https://reader035.vdocuments.us/reader035/viewer/2022070313/554a06c1b4c905557a8b5595/html5/thumbnails/38.jpg)
San Francisco, USA
<?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="Acme\DemoBundle\GreeterService" public="false" /> <service id="acme.demo.democontroller" class="Acme\DemoBundle\Controller\DemoController"> <argument type="service" id="acme.demo.greeterservice" /> </service> </services></container>
Constructor Injection: Symfony 2Warning: might contain errors
(I'm no Symfony expert ...)
![Page 39: Fluent Development with FLOW3 1.0](https://reader035.vdocuments.us/reader035/viewer/2022070313/554a06c1b4c905557a8b5595/html5/thumbnails/39.jpg)
San Francisco, USA
<?php namespace F3\Demo\Controller;
use F3\FLOW3\MVC\Controller\ActionController;use F3\Demo\Service\GreeterService;
class DemoController extends ActionController { /** * @var \F3\Demo\Service\GreeterService */ protected $greeterService;
/** * @param \F3\Demo\Service\GreeterService */ public function __construct(\F3\Demo\Service\GreeterService $greeterService) { $this->greeterService = $greeterService; } /** * @param string $name */ public function helloAction($name) { return 'Hello ' . $name; }}
Constructor Injection
![Page 40: Fluent Development with FLOW3 1.0](https://reader035.vdocuments.us/reader035/viewer/2022070313/554a06c1b4c905557a8b5595/html5/thumbnails/40.jpg)
San Francisco, USA
Constructor Injection
![Page 41: Fluent Development with FLOW3 1.0](https://reader035.vdocuments.us/reader035/viewer/2022070313/554a06c1b4c905557a8b5595/html5/thumbnails/41.jpg)
San Francisco, USA
<?php namespace F3\Demo\Controller;
use F3\FLOW3\MVC\Controller\ActionController;use F3\Demo\Service\GreeterService;
class DemoController extends ActionController { /** * @var \F3\Demo\Service\GreeterService */ protected $greeterService;
/** * @param \F3\Demo\Service\GreeterService */ public function injectGreeterService(\F3\Demo\Service\GreeterService $greeterService) { $this->greeterService = $greeterService; } /** * @param string $name */ public function helloAction($name) { return 'Hello ' . $name; }}
Setter Injection
![Page 42: Fluent Development with FLOW3 1.0](https://reader035.vdocuments.us/reader035/viewer/2022070313/554a06c1b4c905557a8b5595/html5/thumbnails/42.jpg)
San Francisco, USA
<?php namespace F3\Demo\Controller;
use F3\FLOW3\MVC\Controller\ActionController;use F3\Demo\Service\GreeterService;
class DemoController extends ActionController { /** * @var \F3\Demo\Service\GreeterService * @inject */ protected $greeterService; /** * @param string $name */ public function helloAction($name) { return 'Hello ' . $name; }}
Property Injection
![Page 43: Fluent Development with FLOW3 1.0](https://reader035.vdocuments.us/reader035/viewer/2022070313/554a06c1b4c905557a8b5595/html5/thumbnails/43.jpg)
San Francisco, USA
F3\FLOW3\Security\Cryptography\RsaWalletServiceInterface: className: F3\FLOW3\Security\Cryptography\RsaWalletServicePhp scope: singleton properties: keystoreCache: object: factoryObjectName: F3\FLOW3\Cache\CacheManager factoryMethodName: getCache arguments: 1: value: FLOW3_Security_Cryptography_RSAWallet
Objects.yaml
![Page 44: Fluent Development with FLOW3 1.0](https://reader035.vdocuments.us/reader035/viewer/2022070313/554a06c1b4c905557a8b5595/html5/thumbnails/44.jpg)
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)
![Page 45: Fluent Development with FLOW3 1.0](https://reader035.vdocuments.us/reader035/viewer/2022070313/554a06c1b4c905557a8b5595/html5/thumbnails/45.jpg)
San Francisco, USA
class Customer {
/** * @inject * @var CustomerNumberGenerator */ protected $customerNumberGenerator;
...}
$customer = new Customer();$customer->getCustomerNumber();
Object Management
![Page 46: Fluent Development with FLOW3 1.0](https://reader035.vdocuments.us/reader035/viewer/2022070313/554a06c1b4c905557a8b5595/html5/thumbnails/46.jpg)
San Francisco, USA
Object Management
<?phpdeclare(ENCODING = 'utf-8');namespace F3\Conference\Domain\Model\Conference;/** * Autogenerated Proxy Class * @scope prototype * @entity */class Paper extends Paper_Original implements \F3\FLOW3\Object\Proxy\ProxyInterface, \F3\FLOW3\Persistence\Aspect\PersistenceMagicInterface { /** * @var string * @Id * @Column(length="40") * introduced by F3\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 47: Fluent Development with FLOW3 1.0](https://reader035.vdocuments.us/reader035/viewer/2022070313/554a06c1b4c905557a8b5595/html5/thumbnails/47.jpg)
K. Dambekalns & R. LemkeD.P. Fluxtr
time();
5 1 13
Birth of a Blog
![Page 48: Fluent Development with FLOW3 1.0](https://reader035.vdocuments.us/reader035/viewer/2022070313/554a06c1b4c905557a8b5595/html5/thumbnails/48.jpg)
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)
![Page 49: Fluent Development with FLOW3 1.0](https://reader035.vdocuments.us/reader035/viewer/2022070313/554a06c1b4c905557a8b5595/html5/thumbnails/49.jpg)
San Francisco, USA
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 50: Fluent Development with FLOW3 1.0](https://reader035.vdocuments.us/reader035/viewer/2022070313/554a06c1b4c905557a8b5595/html5/thumbnails/50.jpg)
San Francisco, USA
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 51: Fluent Development with FLOW3 1.0](https://reader035.vdocuments.us/reader035/viewer/2022070313/554a06c1b4c905557a8b5595/html5/thumbnails/51.jpg)
San Francisco, USA
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 52: Fluent Development with FLOW3 1.0](https://reader035.vdocuments.us/reader035/viewer/2022070313/554a06c1b4c905557a8b5595/html5/thumbnails/52.jpg)
San Francisco, USA
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 53: Fluent Development with FLOW3 1.0](https://reader035.vdocuments.us/reader035/viewer/2022070313/554a06c1b4c905557a8b5595/html5/thumbnails/53.jpg)
San Francisco, USA
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 54: Fluent Development with FLOW3 1.0](https://reader035.vdocuments.us/reader035/viewer/2022070313/554a06c1b4c905557a8b5595/html5/thumbnails/54.jpg)
San Francisco, USA
Fluid
View helpers – in this case the link.action view helper:
<!-- in the Fluid template: --> {namespace f=F3\Fluid\ViewHelpers}
<f:link.action action="delete" arguments="{post: post, really: 'yes'}"> Delete this post </f:link.action>
![Page 55: Fluent Development with FLOW3 1.0](https://reader035.vdocuments.us/reader035/viewer/2022070313/554a06c1b4c905557a8b5595/html5/thumbnails/55.jpg)
K. Dambekalns & R. LemkeD.P. Fluxtr
time();
5 1 18
Fluent Fluid
![Page 56: Fluent Development with FLOW3 1.0](https://reader035.vdocuments.us/reader035/viewer/2022070313/554a06c1b4c905557a8b5595/html5/thumbnails/56.jpg)
San Francisco, USA
Forms
<?phpnamespace F3\Blog\Domain\Model;
/** * 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;
/** * @var string * @validate Html */ protected $content;
/** * @var F3\Blog\Domain\Model\Image */ protected $image;
![Page 57: Fluent Development with FLOW3 1.0](https://reader035.vdocuments.us/reader035/viewer/2022070313/554a06c1b4c905557a8b5595/html5/thumbnails/57.jpg)
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>
![Page 58: Fluent Development with FLOW3 1.0](https://reader035.vdocuments.us/reader035/viewer/2022070313/554a06c1b4c905557a8b5595/html5/thumbnails/58.jpg)
San Francisco, USA
Forms
<?phpnamespace F3\Blog\Controller;use \F3\FLOW3\MVC\Controller\ActionController;
class PostController extends ActionController {
/** * @inject * @var \F3\Blog\Domain\Repository\PostRepository */ protected $postRepository;
/** * Creates a new post * * @param \F3\Blog\Domain\Model\Post $newPostadded to the repository * @return void */ public function createAction(\F3\Blog\Domain\Model\Post $newPost) { $this->blog->addPost($newPost); $this->flashMessageContainer->add('Your new post was created.'); $this->redirect('index'); }
}?>
![Page 59: Fluent Development with FLOW3 1.0](https://reader035.vdocuments.us/reader035/viewer/2022070313/554a06c1b4c905557a8b5595/html5/thumbnails/59.jpg)
San Francisco, USA
Fluent Development with FLOW3 (PART TWO)
Karsten Dambekalns & Robert Lemke
![Page 60: Fluent Development with FLOW3 1.0](https://reader035.vdocuments.us/reader035/viewer/2022070313/554a06c1b4c905557a8b5595/html5/thumbnails/60.jpg)
![Page 61: Fluent Development with FLOW3 1.0](https://reader035.vdocuments.us/reader035/viewer/2022070313/554a06c1b4c905557a8b5595/html5/thumbnails/61.jpg)
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
![Page 62: Fluent Development with FLOW3 1.0](https://reader035.vdocuments.us/reader035/viewer/2022070313/554a06c1b4c905557a8b5595/html5/thumbnails/62.jpg)
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
![Page 63: Fluent Development with FLOW3 1.0](https://reader035.vdocuments.us/reader035/viewer/2022070313/554a06c1b4c905557a8b5595/html5/thumbnails/63.jpg)
San Francisco, USA
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 64: Fluent Development with FLOW3 1.0](https://reader035.vdocuments.us/reader035/viewer/2022070313/554a06c1b4c905557a8b5595/html5/thumbnails/64.jpg)
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;
![Page 65: Fluent Development with FLOW3 1.0](https://reader035.vdocuments.us/reader035/viewer/2022070313/554a06c1b4c905557a8b5595/html5/thumbnails/65.jpg)
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 \Dambekalns\Stuff\Domain\Model\Stuff * @validate \Dambekalns\Stuff\Domain\Validator\StuffValidator */ protected $stuff;
![Page 66: Fluent Development with FLOW3 1.0](https://reader035.vdocuments.us/reader035/viewer/2022070313/554a06c1b4c905557a8b5595/html5/thumbnails/66.jpg)
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
![Page 67: Fluent Development with FLOW3 1.0](https://reader035.vdocuments.us/reader035/viewer/2022070313/554a06c1b4c905557a8b5595/html5/thumbnails/67.jpg)
San Francisco, USA
Schema Management
Manual database updates
• for simple situations this can be good enough:
• useful when
• you need to use an existing database dump
• using SQLite, due to limited schema change functionality
$ ./flow3_dev flow3:doctrine:create
$ ./flow3_dev flow3:doctrine:update
![Page 68: Fluent Development with FLOW3 1.0](https://reader035.vdocuments.us/reader035/viewer/2022070313/554a06c1b4c905557a8b5595/html5/thumbnails/68.jpg)
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
![Page 69: Fluent Development with FLOW3 1.0](https://reader035.vdocuments.us/reader035/viewer/2022070313/554a06c1b4c905557a8b5595/html5/thumbnails/69.jpg)
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
• migrate to create the tables
$ ./flow3_dev flow3:doctrine:migrationdiffGenerated new migration class to "…/Version20110608074324.php" from schema differences.$ vi …/Version20110608074324.php
$ ./flow3_dev flow3:doctrine:migrate
![Page 70: Fluent Development with FLOW3 1.0](https://reader035.vdocuments.us/reader035/viewer/2022070313/554a06c1b4c905557a8b5595/html5/thumbnails/70.jpg)
San Francisco, USA
Schema Management
Migrations Workflow
$ ./flow3_dev flow3:doctrine:migrationstatus
== Configuration >> Name: Doctrine Database Migrations >> Database Driver: pdo_mysql >> Database Name: blog >> Configuration Source: manually configured >> Version Table Name: flow3_doctrine_migrationstatus >> Migrations Namespace: F3\FLOW3\Persistence\Doctrine\Migrations >> Migrations Directory: /Users/karsten/Sites/blog/Configuration/Doctrine/Migrations >> Current Version: 2011-06-08 07:43:24 (20110608074324) >> Latest Version: 2011-06-08 07:43:24 (20110608074324) >> Executed Migrations: 1 >> Available Migrations: 1 >> New Migrations: 0
== Migration Versions >> 2011-06-08 07:43:24 (20110608074324) migrated
![Page 71: Fluent Development with FLOW3 1.0](https://reader035.vdocuments.us/reader035/viewer/2022070313/554a06c1b4c905557a8b5595/html5/thumbnails/71.jpg)
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
![Page 72: Fluent Development with FLOW3 1.0](https://reader035.vdocuments.us/reader035/viewer/2022070313/554a06c1b4c905557a8b5595/html5/thumbnails/72.jpg)
K. Dambekalns & R. LemkeD.P. Fluxtr
time();
5 1 18
Schematic Demo
![Page 73: Fluent Development with FLOW3 1.0](https://reader035.vdocuments.us/reader035/viewer/2022070313/554a06c1b4c905557a8b5595/html5/thumbnails/73.jpg)
San Francisco, USA
Command Line Support
![Page 74: Fluent Development with FLOW3 1.0](https://reader035.vdocuments.us/reader035/viewer/2022070313/554a06c1b4c905557a8b5595/html5/thumbnails/74.jpg)
K. Dambekalns & R. LemkeD.P. Fluxtr
time();
5 1 18
Shebang!
![Page 75: Fluent Development with FLOW3 1.0](https://reader035.vdocuments.us/reader035/viewer/2022070313/554a06c1b4c905557a8b5595/html5/thumbnails/75.jpg)
San Francisco, USA
Command Line Support
<?phpnamespace F3\FLOW3\Command;
/** * Package command controller to handle packages from CLI (create/activate/deactivate packages) * * @scope singleton */class PackageCommandController extends \F3\FLOW3\MVC\Controller\CommandController {
/** * @inject * @var F3\FLOW3\Package\PackageManagerInterface */ 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 valid.');
![Page 76: Fluent Development with FLOW3 1.0](https://reader035.vdocuments.us/reader035/viewer/2022070313/554a06c1b4c905557a8b5595/html5/thumbnails/76.jpg)
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
![Page 77: Fluent Development with FLOW3 1.0](https://reader035.vdocuments.us/reader035/viewer/2022070313/554a06c1b4c905557a8b5595/html5/thumbnails/77.jpg)
San Francisco, USA
Security Policy
![Page 78: Fluent Development with FLOW3 1.0](https://reader035.vdocuments.us/reader035/viewer/2022070313/554a06c1b4c905557a8b5595/html5/thumbnails/78.jpg)
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...
![Page 79: Fluent Development with FLOW3 1.0](https://reader035.vdocuments.us/reader035/viewer/2022070313/554a06c1b4c905557a8b5595/html5/thumbnails/79.jpg)
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
![Page 80: Fluent Development with FLOW3 1.0](https://reader035.vdocuments.us/reader035/viewer/2022070313/554a06c1b4c905557a8b5595/html5/thumbnails/80.jpg)
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
![Page 81: Fluent Development with FLOW3 1.0](https://reader035.vdocuments.us/reader035/viewer/2022070313/554a06c1b4c905557a8b5595/html5/thumbnails/81.jpg)
K. Dambekalns & R. LemkeD.P. Fluxtr
time();
5 1 18
Users and Login
![Page 82: Fluent Development with FLOW3 1.0](https://reader035.vdocuments.us/reader035/viewer/2022070313/554a06c1b4c905557a8b5595/html5/thumbnails/82.jpg)
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
![Page 83: Fluent Development with FLOW3 1.0](https://reader035.vdocuments.us/reader035/viewer/2022070313/554a06c1b4c905557a8b5595/html5/thumbnails/83.jpg)
San Francisco, USA
AOP
FLOW3 uses AOP for ...
• persistence magic
• logging
• debugging
• security
/** * @aspect * @introduce F3\FLOW3\Persistence\Aspect\PersistenceMagicInterface, F3\FLOW3\Persistence\Aspect\
*/class PersistenceMagicAspect { /** * @pointcut classTaggedWith(entity) || classTaggedWith(valueobject) */ public function isEntityOrValueObject() {} /** * @var string * @Id * @Column(length="40") * @introduce F3\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 \F3\FLOW3\AOP\JoinPointInterface $joinPoint The current join point
* @return void * @before classTaggedWith(entity) && method(.*->__construct()) */ public function generateUUID(\F3\FLOW3\AOP\JoinPointInterface $joinPoint) {
$proxy = $joinPoint->getProxy(); \F3\FLOW3\Reflection\ObjectAccess::setProperty($proxy, 'FLOW3_Persistence_Identifier',
}
![Page 84: Fluent Development with FLOW3 1.0](https://reader035.vdocuments.us/reader035/viewer/2022070313/554a06c1b4c905557a8b5595/html5/thumbnails/84.jpg)
K. Dambekalns & R. LemkeD.P. Fluxtr
time();
5 1 18
The Wizard of AOP
![Page 85: Fluent Development with FLOW3 1.0](https://reader035.vdocuments.us/reader035/viewer/2022070313/554a06c1b4c905557a8b5595/html5/thumbnails/85.jpg)
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
![Page 86: Fluent Development with FLOW3 1.0](https://reader035.vdocuments.us/reader035/viewer/2022070313/554a06c1b4c905557a8b5595/html5/thumbnails/86.jpg)
San Francisco, USA
Signal-Slot Event Handling
/** * @param \F3\Blog\Domain\Model\Post $post * @param \F3\Blog\Domain\Model\Comment $newComment * @return void */ public function createAction(\F3\Blog\Domain\Model\Post $post, \F3\Blog\Domain\Model\Comment $newComment) { $post->addComment($newComment); $this->emitCommentCreated($newComment, $post); … }
/** * @param \F3\Blog\Domain\Model\Comment $comment * @param \F3\Blog\Domain\Model\Post $post * @return void * @signal */ protected function emitCommentCreated(\F3\Blog\Domain\Model\Comment $comment, \F3\Blog\Domain\Model\Post $post) {}
![Page 87: Fluent Development with FLOW3 1.0](https://reader035.vdocuments.us/reader035/viewer/2022070313/554a06c1b4c905557a8b5595/html5/thumbnails/87.jpg)
San Francisco, USA
Signal-Slot Event Handling
/** * Invokes custom PHP code directly after the package manager has been * initialized. * * @param \F3\FLOW3\Core\Bootstrap $bootstrap The current bootstrap * @return void */ public function boot(\F3\FLOW3\Core\Bootstrap $bootstrap) { $dispatcher = $bootstrap->getSignalSlotDispatcher(); $dispatcher->connect( 'F3\Blog\Controller\CommentController', 'commentCreated', 'F3\Blog\Service\Notification', 'sendNewCommentNotification' ); }
Signals are wired to Slots in a package’s bootstrap:
![Page 88: Fluent Development with FLOW3 1.0](https://reader035.vdocuments.us/reader035/viewer/2022070313/554a06c1b4c905557a8b5595/html5/thumbnails/88.jpg)
San Francisco, USA
Signal-Slot Event Handling
/** * @param \F3\Blog\Domain\Model\Comment $comment * @param \F3\Blog\Domain\Model\Post $post * @return void */ public function sendNewCommentNotification(\F3\Blog\Domain\Model\Comment $comment, \F3\Blog\Domain\Model\Post $post) { $mail = new \F3\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 89: Fluent Development with FLOW3 1.0](https://reader035.vdocuments.us/reader035/viewer/2022070313/554a06c1b4c905557a8b5595/html5/thumbnails/89.jpg)
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
![Page 90: Fluent Development with FLOW3 1.0](https://reader035.vdocuments.us/reader035/viewer/2022070313/554a06c1b4c905557a8b5595/html5/thumbnails/90.jpg)
San Francisco, USA
More Features
• Resource Management (CDNs, private resources, ...)
• Logging
• File Monitoring
• Configuration Management
• Routing
• REST / SOAP
• ...
![Page 91: Fluent Development with FLOW3 1.0](https://reader035.vdocuments.us/reader035/viewer/2022070313/554a06c1b4c905557a8b5595/html5/thumbnails/91.jpg)
San Francisco, USA
Roadmap
http://forge.typo3.org/projects/flow3-distribution-base/roadmap
![Page 92: Fluent Development with FLOW3 1.0](https://reader035.vdocuments.us/reader035/viewer/2022070313/554a06c1b4c905557a8b5595/html5/thumbnails/92.jpg)
San Francisco, USA
Discover the source code of the conference app
git://git.typo3.org/TYPO3v5/Distributions/Conference.git
![Page 93: Fluent Development with FLOW3 1.0](https://reader035.vdocuments.us/reader035/viewer/2022070313/554a06c1b4c905557a8b5595/html5/thumbnails/93.jpg)
San Francisco, USA
Try out the blog app
git://git.typo3.org/FLOW3/Applications/Blog.git
![Page 94: Fluent Development with FLOW3 1.0](https://reader035.vdocuments.us/reader035/viewer/2022070313/554a06c1b4c905557a8b5595/html5/thumbnails/94.jpg)
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:
• [email protected] / [email protected]
• http://joind.in/3535