$30 off During Our Annual Pro Sale. View Details »

FLOW3-Workshop F3X12

FLOW3-Workshop F3X12

Folien zum FLOW3-Workshop zur FLOW3 Experience 2012

Karsten Dambekalns

April 01, 2012
Tweet

More Decks by Karsten Dambekalns

Other Decks in Technology

Transcript

  1. Einführung in
    FLOW3
    FLOW3 Experience 2012
    Karsten Dambekalns
    1

    View Slide

  2. Co-Lead von TYPO3 Phoenix und FLOW3
    34 Jahre alt
    lebt in Lübeck
    1 Frau, 3 Söhne, 1 Espressomaschine
    fährt gern Kanadier und klettert
    Karsten Dambekalns
    2

    View Slide

  3. Auf einen Blick
    FLOW3 ist eine Web Application Platform
    • ermöglicht eine neue Art von PHP-Entwicklung
    • basiert auf PHP 5.3, vollständiger Namespaces Support
    • modular, erweiterbar, paket-basiert
    • frei & Open Source (LGPL v3)
    • unterstützt von einem der größten Open Source
    Projekte, mit mehr als 6000 Entwicklern
    3

    View Slide

  4. Grundlage für das Next-Generation CMS
    TYPO3 Phoenix ist das komplett
    neue Enterprise CMS
    • Content Repository, Workspaces,
    Versionierung, i18n, neues UI ...
    • powered by FLOW3
    • FLOW3 kompatible Code-Basis
    • benutze TYPO3 Features in
    eigenen FLOW3 Applikationen
    4

    View Slide

  5. Git Clone
    $ git clone --recursive git://git.typo3.org/FLOW3/Distributions/Base.git .
    Cloning into ....
    remote: Counting objects: 3837, done.
    remote: Compressing objects: 100% (2023/2023), done.
    remote: Total 3837 (delta 2007), reused 2721 (delta 1465)
    Receiving objects: 100% (3837/3837), 3.49 MiB | 28 KiB/s, done.
    Resolving deltas: 100% (2007/2007), done.
    5

    View Slide

  6. Zugriffsrechte einrichten
    $ sudo ./flow3 core:setfilepermissions karsten _www _www
    FLOW3 File Permission Script
    Checking permissions from here upwards.
    Making sure Data and Web/_Resources exist.
    Setting file permissions, trying to set ACLs via chmod ...
    Done.
    $ sudo usermod -a -G www-data karsten
    $ sudo dscl . -append /Groups/_www GroupMembership karsten
    Linux:
    Mac OS X:
    6

    View Slide

  7. Datenbankverbindung einrichten
    Configuration/Settings.yaml
    TYPO3:
    FLOW3:
    persistence:
    backendOptions:
    dbname: 'demo'
    user: 'demo'
    password: 'password'
    host: '127.0.0.1'
    # doctrine:
    # sqlLogger: 'TYPO3\FLOW3\Persistence\Doctrine\Logging\SqlLogger'
    7

    View Slide

  8. Konfiguration per Kontext
    • FLOW3 bietet verschiedene Kontexte für Entwicklung, Test und
    Produktivbetrieb
    • je nach Kontext konfigurieren: Datenbank, Logging, …
    • Unterscheidung per Umgebungsvariable im Virtual Host und auf der
    Konsole:
    $ ./flow3 help
    FLOW3 1.1.0-dev ("Development" context)
    usage: ./flow3

    $ FLOW3_CONTEXT=Production ./flow3 help
    FLOW3 1.1.0-dev ("Production" context)
    usage: ./flow3

    8

    View Slide

  9. Virtual Host einrichten
    Apache Virtual Host

    DocumentRoot /opt/local/apache2/htdocs/Talks/FLOW3/Web/
    ServerName dev.flow3.kmac


    DocumentRoot /opt/local/apache2/htdocs/Talks/FLOW3/Web/
    ServerName flow3.kmac
    SetEnv FLOW3_CONTEXT Production

    9

    View Slide

  10. Funktioniert's?
    10

    View Slide

  11. Git Submodule aktualisieren (bleeding edge)
    $ 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 5187430ee44d579ae2bac825e2a069c4cd3Acme8a4.
    Entering 'Packages/Application/TYPO3CR'
    First, rewinding head to replay your work on top of it...
    Fast-forwarded master to b1f5331aa51d390fa3d973404Acme1b9fd773f7059.
    Entering 'Packages/Application/Twitter'
    Current branch master is up to date.

    11

    View Slide

  12. Kommandozeile
    $ ./flow3 help
    FLOW3 1.1.0-dev ("Development" context)
    usage: ./flow3
    The following commands are currently available:
    PACKAGE "TYPO3.FLOW3":
    -------------------------------------------------------------------------------
    * flow3:cache:flush Flush all caches
    cache:warmup Warm up caches
    configuration:show Show the active configuration
    settings
    * flow3:core:setfilepermissions Adjust file permissions for CLI and
    web server access
    * flow3:core:shell Run the interactive Shell
    doctrine:validate Validate the class/table mappings
    doctrine:create Create the database schema
    doctrine:update Update the database schema
    doctrine:entitystatus Show the current status of entities
    and mappings
    doctrine:dql Run arbitrary DQL and display
    results
    doctrine:migrationstatus Show the current migration status
    doctrine:migrate Migrate the database schema
    doctrine:migrationexecute Execute a single migration
    doctrine:migrationversion Mark/unmark a migration as migrated 12

    View Slide

  13. Kommandozeile
    $ ./flow3 help kickstart:package
    Kickstart a new package
    COMMAND:
    typo3.kickstart:kickstart:package
    USAGE:
    ./flow3 kickstart:package
    ARGUMENTS:
    --package-key The package key, for example "MyCompany.MyPackageName"
    DESCRIPTION:
    Creates a new package and creates a standard Action Controller and a sample
    template for its Index Action.
    For creating a new package without sample code use the package:create command.
    SEE ALSO:
    typo3.flow3:package:create (Create a new package)
    13

    View Slide

  14. Hallo Welt!
    $ ./flow3 kickstart:package Acme.Demo
    14

    View Slide

  15. Hallo Welt!
    namespace Acme\Demo\Controller;
    use TYPO3\FLOW3\Mvc\Controller\ActionController;
    class StandardController extends ActionController {
    /**
    * @param string $name
    * @return string
    */
    public function indexAction($name) {
    return "Hello $name!";
    }
    }
    ?>
    StandardController.php
    15

    View Slide

  16. Controller Kickstart
    $ ./flow3 help kickstart:actioncontroller
    Kickstart a new action controller
    COMMAND:
    typo3.kickstart:kickstart:actioncontroller
    USAGE:
    ./flow3 kickstart:actioncontroller []
    ARGUMENTS:
    --package-key The package key of the package for the new controller
    with an optional subpackage, (e.g.
    "MyCompany.MyPackage/Admin").
    --controller-name The name for the new controller. This may also be a
    comma separated list of controller names.
    OPTIONS:
    --generate-actions Also generate index, new, create, edit, update and
    delete actions.
    --generate-templates Also generate the templates for each action.
    --generate-related Also create the mentioned package, related model and
    repository if neccessary.
    --force Overwrite any existing controller or template code.
    Regardless of this flag, the package, model and
    repository will never be overwritten.
    DESCRIPTION:
    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
    16

    View Slide

  17. Eigene Commands
    $ ./flow3 kickstart:commandcontroller Acme.Demo Test
    namespace Acme\Demo\Controller;
    use TYPO3\FLOW3\Mvc\Controller\CommandController;
    class TestCommandController extends CommandController {
    /**
    * An example command
    *
    * @param string $requiredArgument This argument is required
    * @param string $optionalArgument This argument is optional
    * @return void
    */
    public function exampleCommand($name) {
    $this->outputLine("Hello %s!", array($name));
    }
    }
    17

    View Slide

  18. Das Wesentliche im Blick
    Domain-Driven Design
    Eine Methode die ...
    • zu aussagekräftigen Modellen
    verhilft
    • eine gemeinsames Vokabular
    etabliert
    • das Design von komplexen
    Anwendungen erleichtert
    /**
    * 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;
    18

    View Slide

  19. Domain-Driven Design
    Domain
    Aktivität oder Geschäftsdomäne des Nutzers
    Domain-Driven Design
    bedeutet
    • Fokus auf die Domäne und Domänen-Logik
    • sorgfältiges Mapping der Konzepte auf das Model
    • etablieren einer gemeinsamen Sprache innerhalb
    des gesamten Projekt-Teams
    19

    View Slide

  20. Domain-Driven Design
    Ubiquitous Language
    • allgemeingegenwärtige Begriffe sind wichtig für
    die Kommunitation aller Beteiligten
    • benutze dieselben Begriffe für
    • Diskussionen
    • Modeling
    • Entwicklung
    • Dokumentation
    20

    View Slide

  21. Domain-Driven Design
    Standardwerk
    Spannend und
    unterhaltsam
    21

    View Slide

  22. Object Management
    Dependency Injection
    • anstatt eine Instanz einer Klasse zu erzeugen
    oder sie aktiv zu holen, wird sie injected
    • fördert lose Kopplung und starke Kohäsion
    ‣ stabilerer, wiederverwendbarer Code
    22

    View Slide

  23. Object Management
    FLOW3's Ansatz für Dependency Injection
    • eine der ersten PHP Implementierungen
    (2006 begonnen, seitdem ständig verbessert)
    • Object Management für den gesamten Lebenszyklus
    aller Objekte
    • keine unnötige Konfiguration wenn die Informationen
    automatisch ermittelt werden können (Autowiring)
    • intuitive Nutzung ohne böse (magische) Überraschungen
    • schnell! (wie selbstgemacht oder schneller)
    23

    View Slide

  24. namespace Acme\Demo\Controller;
    use TYPO3\FLOW3\MVC\Controller\ActionController;
    use Acme\Demo\Service\GreeterService;
    class DemoController extends ActionController {
    /**
    * @var \Acme\Demo\Service\GreeterService
    */
    protected $greeterService;
    /**
    * @param \Acme\Demo\Service\GreeterService
    */
    public function __construct(\Acme\Demo\Service\GreeterService $greeterService) {
    $this->greeterService = $greeterService;
    }
    /**
    * @param string $name
    */
    public function helloAction($name) {
    return $this->greeterService->hello($name);
    }
    }
    Constructor Injection
    24

    View Slide

  25. Setter Injection
    namespace Acme\Demo\Controller;
    use TYPO3\FLOW3\MVC\Controller\ActionController;
    use Acme\Demo\Service\GreeterService;
    class DemoController extends ActionController {
    /**
    * @var \Acme\Demo\Service\GreeterService
    */
    protected $greeterService;
    /**
    * @param \Acme\Demo\Service\GreeterService
    */
    public function injectGreeterService(\Acme\Demo\Service\GreeterService $greeterService) {
    $this->greeterService = $greeterService;
    }
    /**
    * @param string $name
    */
    public function helloAction($name) {
    return $this->greeterService->hello($name);
    }
    }
    25

    View Slide

  26. namespace Acme\Demo\Controller;
    use TYPO3\FLOW3\Annotations as FLOW3;
    use TYPO3\FLOW3\MVC\Controller\ActionController;
    use Acme\Demo\Service\GreeterService;
    class DemoController extends ActionController {
    /**
    * @var \Acme\Demo\Service\GreeterService
    * @FLOW3\Inject
    */
    protected $greeterService;
    /**
    * @param string $name
    */
    public function helloAction($name) {
    return $this->greeterService->hello($name);
    }
    }
    Property Injection
    26

    View Slide

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

    View Slide

  28. class Customer {
    /**
    * @FLOW3\Inject
    * @var CustomerNumberGenerator
    */
    protected $customerNumberGenerator;
    ...
    }
    $customer = new Customer();
    $customer->getCustomerNumber();
    Object Management
    28

    View Slide

  29. Object Management
    declare(ENCODING = 'utf-8');
    namespace Acme\Conference\Domain\Model\Conference;
    /**
    * Autogenerated Proxy Class
    * @TYPO3\FLOW3\Annotations\Scope(“prototype”)
    * @ TYPO3\FLOW3\Annotations\Entity
    */
    class Paper extends Paper_Original implements \TYPO3\FLOW3\Object
    \FLOW3\Persistence\Aspect\PersistenceMagicInterface {
    /**
    * @var string
    * @Doctrine\ORM\Mapping\Id
    * @Doctrine\ORM\Mapping\Column(length="40")
    * introduced by TYPO3\FLOW3\Persistence\Aspect\PersistenceMa
    */
    protected $FLOW3_Persistence_Identifier = NULL;
    private $FLOW3_Aop_Proxy_targetMethodsAndGroupedAdvices = arra
    private $FLOW3_Aop_Proxy_groupedAdviceChains = array();
    private $FLOW3_Aop_Proxy_methodIsInAdviceMode = array();
    /**
    * Autogenerated Proxy Method
    */
    public function __construct() {
    FLOW3 erzeugt Proxy Klassen
    um DI und AOP zu ermöglichen
    • new Operator wird
    unterstützt
    • Proxy Klassen werden on-
    the-fly erzeugt
    • im Production Kontext ist
    sämtlicher Code statisch
    29

    View Slide

  30. Persistenz
    Objekt Persistenz im Fluss
    • basiert auf Doctrine 2
    • nahtlose Integration in FLOW3
    • bietet alle Doctrine 2 Features
    • nutzt UUIDs
    • Low Level Persistence API:
    • ermöglichte eingene Persistenz
    Mechanismen (anstelle von Doctrine 2)
    • CouchDB
    30

    View Slide

  31. Persistenz Basics
    // Create a new customer and persist it:
    $customer = new Customer("Robert");
    $this->customerRepository->add($customer);
    // Update a customer:
    $customer->setName("I, Robot");
    $this->customerRepository->update($customer);
    // Find an existing customer:
    $otherCustomer = $this->customerRepository->findByFirstName("Karsten");
    // … and delete it:
    $this->customerRepository->remove($otherCustomer);
    • Repository von FLOW3 per DI geben lassen
    • Domänenobjekte (fast) wie ohne Framework behandeln
    31

    View Slide

  32. Doctrine und Validierung mit Annotations
    namespace TYPO3\Blog\Domain\Model;
    use TYPO3\FLOW3\Annotations as FLOW3;
    use Doctrine\ORM\Mapping as ORM;
    /**
    * @FLOW3\Entity
    */
    class Blog {
    /**
    * @var string
    * @FLOW3\Validate(“Text”)
    * @FLOW3\Validate(type=”StringLength”, options={“minimum” = 1, “maximum” = 80})
    * @ORM\Column(length=80)
    */
    protected $title;
    /**
    * @var \Doctrine\Common\Collections\Collection<\TYPO3\Blog\Domain\Model\Post>
    * @ORM\OneToMany(mappedBy="blog")
    * @ORM\OrderBy({"date" = "DESC"})
    */
    protected $posts;
    ...
    }
    32

    View Slide

  33. Persistenz-relevante Annotations
    FLOW3\Entity Deklariert eine Klasse als "Entity"
    ORM\Column Nimmt Einfluss auf das Datenbankfeld das mit der
    Class Property zusammenhängt. Besonders sinnvoll
    bei Text-Inhalten (type="text").
    ORM\ManyToOne
    ORM\ OneToMany
    ORM\ ManyToMany
    ORM\ OneToOne
    Definiert Relationen zu Class-Properties anderer
    Entities. Im Gegensatz zu reinem Doctrine muss
    targetEntity nicht angegeben werden sondern wird
    aus der @var Annotation übernommen.
    cascade kaskadiert Operationen auf alle
    zusammengehörigen Objekte innerhalb des
    Aggregates. Wird ebenfalls automatisch gesetzt.
    33

    View Slide

  34. Persistenz-relevante Annotations
    var Definiert den Typ, Collections werden in spitzen
    Klammern definiert:
    \Doctrine\Common\Collections\Collection<\TYPO3\Conference\Domain\Model\Comment>
    FLOW3\Transient Die Property wird ignoriert – also weder
    persistiert noch wiederhergstellt
    FLOW3\Identity Markiert die Property als Teil der Identität
    ORM\Id Definiert die Property, die als Primärschlüssel in
    der Datenbank dient. In FLOW3 wird dies
    automatisch im Hintergrund definiert.
    34

    View Slide

  35. Nutzung von Repositories
    Das generische Basis-Repository unterstützt jedes Backend, das
    Doctrine-Basis-Repository bietet Zugriff auf Doctrine-Spezifika.
    Die Nutzung der Basis-Repositories von FLOW3
    • Stellt grundlegende Methoden breit:
    findAll(), countAll(), remove(), removeAll()
    • Bietet automatische Methoden um nach Properties zu suchen:
    findByPropertyName($value), findOneByPropertyName($value)
    Eigene, spezialisierte Finder-Methoden werden einfach dem eigenen
    Repository hinzugefügt.
    35

    View Slide

  36. Eigene Abfragen mit dem QOM
    class PostRepository extends \FLOW3\Persistence\Repository {
    /**
    * Finds most recent posts excluding the given post
    *
    * @param \TYPO3\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(\TYPO3\Blog\Domain\Model\Post $post, $limit = 20) {
    $query = $this->createQuery();
    $posts = $query->matching($query->equals('blog', $post->getBlog()))
    ->setOrderings(array(
    'date' => \TYPO3\FLOW3\Persistence\QueryInterface::ORDER_DESCENDING
    ))
    ->setLimit($limit)
    ->execute()
    ->toArray();
    unset($posts[array_search($post, $posts)]);
    return $posts;
    }
    }
    PostRepository.php
    36

    View Slide

  37. Eigene Abfragen mit DQL
    class PostRepository extends \FLOW3\Persistence\Doctrine\Repository {
    /**
    * Finds most recent posts excluding the given post
    *
    * @param \TYPO3\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(\TYPO3\Blog\Domain\Model\Post $post, $limit = 20) {
    // this is an alternative way of doing this when extending the Doctrine 2
    // specific repository and using DQL.
    $query = $this->entityManager->createQuery(
    'SELECT p FROM \TYPO3\Blog\Domain\Model\Post p WHERE p.blog = :blog AND NOT p
    = :excludedPost ORDER BY p.date DESC'
    );
    return $query
    ->setMaxResults($limit)
    ->execute(array('blog' => $post->getBlog(), 'excludedPost' => $post));
    }
    }
    PostRepository.php
    37

    View Slide

  38. Schema Management
    Doctrine 2 Migrations
    • Migrationen ermöglichen Schema
    Versionierung und das Deployment von
    Änderungen
    • Migrationen sind der empfohlene Weg für
    Datanbank Anpassungen
    • Kann auch zum Deplyoment und Update
    bestehender Daten genutzt werden
    • Tools für das Erstellen und Deployen von
    Migrationen sind in FLOW3 enthalten
    38

    View Slide

  39. Schema Management
    Ausführen von Migrationen
    • notwendig nach Neuinstallation oder Upgrades:
    $ ./flow3 doctrine:migrate
    39

    View Slide

  40. Schema Management
    Migrations-Status prüfen
    $ ./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: TYPO3\FLOW3\Persistence\Doctrine\Migrations
    >> Migrations Directory: /…/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
    40

    View Slide

  41. Schema Management
    Migrationen erstellen
    $ ./flow3 doctrine:migrationgenerate
    Generated new migration class!
    Next Steps:
    - Move …/Version20120329190824.php to YourPackage/Migrations/Mysql/
    - Review and adjust the generated migration.
    - (optional) execute the migration using ./flow3 doctrine:migrate
    41

    View Slide

  42. Schema Management
    /**
    * Rename FLOW3 tables to follow FQCN
    */
    class Version20110824124835 extends AbstractMigration {
    /**
    * @param Schema $schema
    * @return void
    */
    public function up(Schema $schema) {
    $this->abortIf($this->connection->getDatabasePlatform()->getName() != "mysql");
    $this->addSql("RENAME TABLE flow3_policy_role TO typo3_flow3_security_policy_role");
    $this->addSql("RENAME TABLE flow3_resource_resource TO typo3_flow3_resource_resource");
    $this->addSql("RENAME TABLE flow3_resource_resourcepointer TO
    typo3_flow3_resource_resourcepointer");
    $this->addSql("RENAME TABLE flow3_resource_securitypublishingconfiguration TO
    typo3_flow3_security_authorization_resource_securitypublis_6180a");
    $this->addSql("RENAME TABLE flow3_security_account TO typo3_flow3_security_account");
    }
    Migrations-Dateien enthalten meist wirklich einfachen Code
    42

    View Slide

  43. Schema Management
    $ ./flow3 doctrine:create
    $ ./flow3 doctrine:update
    Schema aktualisieren ohne Migrations zu verwenden
    • Für mache Situationen reichen Updates ohne Migrations
    • Hilfreich bei
    • der Nutzung existierender Datenbank-Dumps
    • fehlenden Migrations für die genutzte Datenbank
    • SQLite (beschränkte Unterstützung für Schema-Änderungen)
    43

    View Slide

  44. Templating-Zen
    FLOW3 bietet eine elegante, flexible und sichere
    Templating-Engine: Fluid
    • Templates sind valides HTML
    • Templates enthalten keinen PHP-Code
    • Object-Zugriff, Kontrollstrukturen, Schleifen…
    • Designer-Kompatibel
    • Erweiterbar (ViewHelper, Widgets)
    44

    View Slide

  45. Fluid
    Beispiel einer String-Zuweisung an eine Fluid-Variable:


    {title}

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

    View Slide

  46. Fluid
    Variablen können auch Objekte sein:


    Venue Street: {conference.venue.street}

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

    View Slide

  47. Fluid
    if-then-else:


    There are some comments.
    There are no comments.

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

    View Slide

  48. Fluid
    for-each:



    {name} is {age} year old.


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

    View Slide

  49. Fluid
    for-each:




    {post.title}



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

    View Slide

  50. Fluid
    ViewHelper – hier der link.action ViewHelper:

    {namespace f=F3\Fluid\ViewHelpers}

    Delete this post

    50

    View Slide

  51. Formulare
    namespace TYPO3\Blog\Domain\Model;
    /**
    * A blog post
    *
    * @FLOW3\Scope(“prototype”)
    * @FLOW3\Entity
    */
    class Post {
    /**
    * @var string
    * @FLOW3\Validate(type=“StringLength”, options={“minimum” = 10})
    */
    protected $title;
    /**
    * @var string
    * @FLOW3\Validate(type=“StringLength”, options={“maximum” = 50})
    */
    protected $author;
    /**
    51

    View Slide

  52. Formulare
    Create a new post

    Title



    Content



    Image resource




    52

    View Slide

  53. Formulare
    namespace TYPO3\Blog\Controller;
    use \TYPO3\FLOW3\MVC\Controller\ActionController;
    class PostController extends ActionController {
    /**
    * @FLOW3\Inject
    * @var \TYPO3\Blog\Domain\Repository\PostRepository
    */
    protected $postRepository;
    /**
    * Creates a new post
    *
    * @param \TYPO3\Blog\Domain\Model\Post $newPost added to the repository
    * @return void
    */
    public function createAction(\TYPO3\Blog\Domain\Model\Post $newPost) {
    $this->blog->addPost($newPost);
    $this->addFlashMessage('Your new post was created.');
    $this->redirect('index');
    }
    53

    View Slide

  54. Validierung
    Validierung behandelt verschiedene Dinge
    • hereinkommende Daten müssen abgesichert werden
    • kein böses Markup in Content vom Client
    • Die Integrität des Domain Model muss sichergestellt werden
    • Eine E-Mail muss (syntaktisch) korrekt sein
    • Kreditkarten-Nummern sollten nur aus Zahlen bestehen
    54

    View Slide

  55. Validierung
    Validierung in FLOW3
    • keiner möchte solche Prüfungen in seinen Controllern implementieren
    • FLOW3 trennt die Validierung von den Aufgaben des Controllers
    • kein PHP-Code für die Validierung notwendig
    • Regeln werden durch Annotations definiert
    55

    View Slide

  56. Validierung
    Validierungs-Modelle
    • Base Properties
    Minimale Anforderungen an individuelle Properties eines Models
    • Base Model
    Minimale Anforderungen an eine Kombination von Properties eines
    Models, Prüfung ggf. durch eigenen Validator
    • Supplemental
    Zusätzliche Anforderungen an ein Model in spezifischen Situationen
    (z.B. für eine bestimmte Action-Methode)
    56

    View Slide

  57. Validierung
    Base Properties
    • Validierungsregeln direkt an den Properties
    /**
    * @var string
    * @FLOW3\Validate(type=”StringLength”, options={“minimum” = 10})
    */
    protected $title;
    /**
    * @var string
    * @FLOW3\Validate(type=”StringLength”, options={“maximum” = 50})
    */
    protected $author;
    57

    View Slide

  58. Validierung
    Validatoren
    • Validatoren aus FLOW3 mit verkürztem Namen ansprechen
    • Count, Float, NotEmpty, RegularExpression, Uuid, DateTime,
    NumberRange, StringLength, Alphanumeric, Integer, Number, String,
    EmailAddress, Label, Raw, Text
    • Eigene Validatoren müssen das ValidatorInterface implementieren
    • Um sie zu nutzen, den fully qualified class name angeben
    /**
    * @var \My\Stuff\Domain\Model\Stuff
    * @FLOW3\Validate(type=”My\Stuff\Domain\Validator\StuffValidator”)
    */
    protected $stuff;
    58

    View Slide

  59. Property Mapper
    Eigenschaften von A nach B übertragen
    • ermöglicht komplette oder teilweise Kopien von Objekten und
    Objektstrukturen
    • wird vom MVC-Framework für das Mapping von rohen GET- und
    POST-Argumenten auf Argument-Objekte verwendet
    59

    View Slide

  60. Property Mapper
    $articleArray = array(
    'headline' => 'Hello World!',
    'story' => 'Just a demo ...'
    );
    $article = $mapper->convert($sourceArray, 'Acme.Demo\Domain\Model\Article');
    60

    View Slide

  61. Resource Management
    enctype="multipart/form-data">



    Author picture



    Bilder Upload
    Resourcen werden wie andere Properties auch in Formular
    eingebunden::
    61

    View Slide

  62. Property Mapper
    /**
    * @return void
    */
    public function initializeUpdateAction() {
    $this->arguments['blog']->getPropertyMappingConfiguration()
    ->allowCreationForSubProperty('authorPicture');
    $this->arguments['blog']->getPropertyMappingConfiguration()
    ->allowModificationForSubProperty('authorPicture');
    }
    Verschachtelte Objektstrukturen erlauben
    Aus Sicherheitsgründen ist dies standardmäßig abgeschaltet
    62

    View Slide

  63. Security
    Touchless Security, Flow-Style
    • Security wird zentralisiert umgesetzt (durch AOP)
    • Basiert auf unseren Erfahrungen im TYPO3-Projekt und der
    Spring Security (Java framework)
    • Bietet Authentifizierung, Authorisierung, Rollen, ACLs, …
    • Kann beliebige Methoden-Aufrufe abfangen
    • Filtert den Zugriff auf Content durch das Umschreiben von
    Abfragen in der Persistenz
    • Erweiterbar um neue Mechanismen zu Authentifizierung und
    Authorisierung
    63

    View Slide

  64. Security Policy
    # #
    # Security policy definition #
    # #
    # This file contains the security policy configuration for the #
    # Conference package #
    resources:
    methods:
    TYPO3_Conference_AccountActions: 'method(TYPO3\Conference\Controller\Account\(Overview|Spe
    TYPO3_Conference_MyPapersActions: 'method(TYPO3\Conference\Controller\Conference\PaperCont
    delete)Action())'
    TYPO3_Conference_PaperReviewActions: 'method(TYPO3\Conference\Controller\Conference\PaperC
    TYPO3_Conference_PaperVotingResultActions: 'method(TYPO3\Conference\Controller\Conference\
    roles:
    Conference_Visitor: []
    Speaker: [Conference_Visitor]
    ConfirmedSpeaker: [Conference_Visitor]
    TrackChair: [Conference_Visitor]
    Administrator: [Conference_Visitor]
    acls:
    Conference_Visitor:
    methods:
    TYPO3_Conference_AccountActions: GRANT
    Speaker:
    methods: 64

    View Slide

  65. Security
    Cross-Site Request Forgery
    • ermöglicht einem Angreifer die Ausführung privilegierter
    Operationen ohne selbst authentifiziert zu sein
    • die Gefahr liegt in der Nutzung von manipulierten Links oder
    Formularen während man am System angemeldet ist
    • URL-Shortener bieten eine gute Basis für solche Angriffe…
    65

    View Slide

  66. Security
    Cross-Site Request Forgery verhindern
    • Ein (wirklich!) zufälliges Token an jeden Link und jedes Formular
    anhängen
    • und die Korrektheit dieses Tokens vor jeder Aktion überprüfen
    • Das Token so oft wie möglich ändern um zu verhindern das ein
    gültiger Link geschickt werden kann während der Benutzer
    angemeldet ist
    • In den meisten Fällen reicht es aus, bei jedem Login ein neues Token
    zu erzeugen – das ist die Standard-Einstellung in FLOW3
    66

    View Slide

  67. Security
    CSRF-Schutz in FLOW3
    • Man darf das Token nie vergessen
    • FLOW3 fügt das CSRF-Token automatisch zu jedem
    • Link der generiert wird und
    • jedem mit Fluid erzeugten Formular hinzu
    • und prüft das Token vor jeder Action-Methode
    • Der CSRF-Schutz kann durch @FLOW3\SkipCsrfProtection
    je Methode abgeschaltet werden
    67

    View Slide

  68. AOP
    Aspekt-Orientierte Programmierung
    • ist ein Programmier-Paradigma
    • kapselt Zuständigkeiten um die Modularisierung zu verbessern
    • OOP modularisiert Zuständigkeiten in Objekte
    • AOP modularisiert cross-cutting concerns in Aspekten
    • FLOW3 macht die Nutzung von AOP in PHP einfach (und überhaupt
    erst möglicht)
    68

    View Slide

  69. AOP
    FLOW3 nutzt AOP für ...
    • Persistenz
    • Logging
    • Debugging
    • Security
    /**
    * @aspect
    * @introduce TYPO3\FLOW3\Persistence\Aspect\PersistenceMagicInterface, TYP
    */
    class PersistenceMagicAspect {
    /**
    * @pointcut classTaggedWith(entity) || classTaggedWith(valueobject)
    */
    public function isEntityOrValueObject() {}
    /**
    * @var string
    * @Id
    * @Column(length="40")
    * @introduce TYPO3\FLOW3\Persistence\Aspect\PersistenceMagicAspect->isE
    */
    protected $FLOW3_Persistence_Identifier;
    /**
    * After returning advice, making sure we have an UUID for each and every
    *
    * @param \TYPO3\FLOW3\AOP\JoinPointInterface $joinPoint The current join
    * @return void
    * @before classTaggedWith(entity) && method(.*->__construct())
    */
    public function generateUUID(\TYPO3\FLOW3\AOP\JoinPointInterface $joinPoin
    $proxy = $joinPoint->getProxy();
    \TYPO3\FLOW3\Reflection\ObjectAccess::setProperty($proxy, 'FLOW3_Persi
    }
    69

    View Slide

  70. Signal-Slot Event Handling
    Signal
    • kann jederzeit ausgelöst werden
    • kann frei vom Entwickler definiert werden
    Slot
    • wird aufgerufen wenn ein Signal ausgelöst wurde
    • jede Methode kann als Slot genutzt werden
    Jedes Signal kann mit jedem Slot verbunden werden
    70

    View Slide

  71. Signal-Slot Event Handling
    /**
    * @param \TYPO3\Blog\Domain\Model\Post $post
    * @param \TYPO3\Blog\Domain\Model\Comment $newComment
    * @return void
    */
    public function createAction(\TYPO3\Blog\Domain\Model\Post $post,
    \TYPO3\Blog\Domain\Model\Comment $newComment) {
    $post->addComment($newComment);
    $this->emitCommentCreated($newComment, $post);

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

    View Slide

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

    View Slide

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

    View Slide

  74. Signal-Slot Event Handling
    /**
    * Invokes custom PHP code directly after the package manager has been
    * initialized.
    *
    * @param \TYPO3\FLOW3\Core\Bootstrap $bootstrap The current bootstrap
    * @return void
    */
    public function boot(\TYPO3\FLOW3\Core\Bootstrap $bootstrap) {
    $dispatcher = $bootstrap->getSignalSlotDispatcher();
    $dispatcher->connect(
    'TYPO3\Blog\Service\Notification', '::aStaticMethodCanBeUsed'
    );
    }
    Slots können auch statische Methoden sein:
    74

    View Slide

  75. Speed und Performance
    Für den ungeduldigen Nutzer:
    • multi-layered, tagged Caches
    • Diverse Cache-Backends (File, Memcached, APC, Redis, PDO, ...)
    • Unterstützung für Reverse-Proxy (Varnish, ESI) ist in Arbeit
    • Code-Kompilierung
    • Regelmäßige Benchmarks
    • Fokus auf gute Skalierbarkeit
    75

    View Slide

  76. Mehr Features
    • Resource Management (CDNs, private Ressourcen, ...)
    • Logging
    • File Monitoring
    • Configuration Management
    • Routing
    • REST / SOAP
    • ...
    76

    View Slide

  77. • These slides can be found at:
    http://speakerdeck.com/u/kdambekalns | http://slideshare.net/kfish
    • Give me feedback:
    [email protected] | [email protected]
    • Download FLOW3: http://flow3.typo3.org
    • Follow me on twitter: @kdambekalns
    • Support me using
    Thank You!
    77

    View Slide