The Joy of Development
project founder of
Flow and Neos

coach, coder, consultant

Lübeck, Germany

1 wife, 2 daughters,
                       TEXT HERE
1 espresso machine

likes drumming
2005
modelviewcontroller
HTTP
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
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 TYPO3FlowHttpUri
   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 TYPO3FlowHttpUri
   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;
$request->getHeader('User-Agent'); # C64

$request->setHeader('X-Coffee', 'too few');
$now = new DateTime();
$response->setLastModified($now);
$response->getHeaders()
  ->setCacheControlDirective('s-max-age', 100);
# set cookie in response:
$response->setCookie(new Cookie('counter', 1));

  # on next request, retrieve cookie:
$cookie = $request->getCookie('counter');
$response = $browser->request('http://robertlemke.com/home');
$content = $response->getContent();
$request = Request::create($storageUri, 'PUT');
$request->setContent(fopen('myfavoritemovie.m4v', 'rb'));
$request->setHeader('X-Category', 'Sissy');

$reponse = $browser->sendRequest($request);
Model
Domain-Driven Design                       /**
                                            * A Book
                                            *
A methodology which ...                     * @FlowScope(“prototy
                                                                   pe”)
                                            * @FlowEntity
                                            */
• results in rich domain models           class Book {

                                           /**
• provides a common language across         * @var string
  the project team                          */
                                           protected $title;

• simplify the design of complex           /**
                                            * @var string
  applications                              */
                                           protected $isbn;

                                          /**
Flow is the first PHP framework tailored    * @var string
                                           */
to Domain-Driven Design                   protected $description
                                                                 ;

                                          /**
                                           * @var integer
                                           */
                                          protected $price;
/**
 * A Book
 *
 * @FlowEntity
 */
class Book {

  /**
   * The title
   * @var string
   * @FlowValidate(type="StringLength", options={ "minimum"=1,
   */
  protected $title;

  /**
   * The price
   * @var integer
   * @FlowValidate(type="NumberRange", options={ "minimum"=1,
   */
  protected $price;
/**
  * 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;
}
/**
 * A repository for Books
 *
 * @FlowScope("singleton")
 */
class BookRepository extends Repository {

    public function findBestSellers() {
      ...
    }

}
# Add a book
$bookRepository->add($book);

  # Remove a book
$bookRepository->remove($book);

  # Update a book
$bookRepository->update($book);
# Find one specific book
$book = $bookRepository->findOneByTitle('Lord of the Rings');

  # Find multiple books by property
$books = $bookRepository->findByCategory('Fantasy');

  # Find books through custom find method
$bestsellingBooks = $bookRepository->findBestSellers();
TEXT HERE
TEXT HERE
Controller
class HelloWorldController extends ActionController {

    /**
      * @return string
      */
    public function greetAction() {
         return 'Hello World!';
    }

}
Hello World!


           TEXT HERE
/**
  * An action which sends greetings to $name
  *
  * @param string $name The name to mention
  * @return string
  */
public function greetAction($name) {
     return "Hello $name!";
}
dev.demo.local/acme.demo/helloworld/greet.html?name=Robert

                 dev.demo.local/acme.demo/helloworld/greet.html?name=Robert




Hello Robert!
View
<html lang="en">
    <head>
        <title>Templating</title>
    </head>
    <body>

          Our templating engine
          is called

                         Fluid
    </body>
</html>
/**
  * @param string $name
  * @return void
  */
public function greetAction($name) {
     $this->view->assign('name', $name);
}
<html>
    <head>
        <title>Fluid Example</title>
    </head>
    <body>
        <p>Hello, {name}!</p>
    </body>
</html>
/**
  * Displays a list of best selling books
  *
  * @return void
  */
public function indexAction() {
    $books = $this->bookRepository->findBestSellers();
    $this->view->assign('books', $books);
}
<ul>
   <f:for each="{books}" as="book">
       <li>{book.title} by {book.author.name}</li>
   </f:for>
</ul>
<html xmlns:f="http://typo3.org/ns/TYPO3/Fluid/ViewHelpers">
<f:form action="create" name="newBook">
    <ol>
         <li>
              <label for="name">Name</label>
              <f:form.textfield property="name" id="name" />
         </li>
         <li>
              <f:form.submit value="Create" />
         </li>
    </ol>
</f:form>
/**
  * Adds the given new book to the BookRepository
  *
  * @param AcmeDemoDomainModelBook $newBook
  * @return void
  */
public function createAction(Book $newBook) {
    $this->bookRepository->add($newBook);
    $this->addFlashMessage('Created a new book.');
    $this->redirect('index');
}
Resources
Static Resources
Static Resources
Static Resources
Persistent Resources
Persistent Resources
Dependency Injection
class SomeService {

      protected static $instance;

      public function getInstance() {
        if (self::$instance === NULL) {
          self::$instance = new self;
        }
        return self::$instance;
      }
}



class SomeOtherController {

    public function action() {
      $service = SomeService::getInstance();
      …
    }

}
class ServiceLocator {

      protected static $services = array();

      public function getInstance($name) {
        return self::$service[$name];
      }

}



class SomeOtherController {

    public function action() {
      $service = ServiceLocate::getInstance("SomeService");
      …
    }

}
Flow'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)
class BookController extends ActionController {

    /**
     * @var BookRepository
     */
    protected $bookRepository;

    /**
      * @param BookRepository $bookRepository
      */
    public function __construct(BookRepository $bookRepository) {
       $this->bookRepository = $bookRepository;
    }

}
class BookController extends ActionController {

    /**
     * @var BookRepository
     */
    protected $bookRepository;

  /**
    * @param BookRepository $bookRepository
    */
  public function injectBookRepository(BookRepository
$bookRepository) {
     $this->bookRepository = $bookRepository;
  }

}
class BookController extends ActionController {

    /**
     * @FlowInject
     * @var BookRepository
     */
    protected $bookRepository;

}
Aspect-Oriented Programming
/**
  * An action which sends greetings to $name
  *
  * @param string $name The name to mention
  * @return string
  */
public function greetAction($name) {
     return "Hello $name!";
}
dev.demo.local/acme.demo/helloworld/greet.html?name=Robert

                 dev.demo.local/acme.demo/helloworld/greet.html?name=Robert




Hello Robert!
/**
 * @FlowAspect
 */
class DemoAspect {

    /**
      * @param TYPO3FlowAopJoinPointInterface $joinPoint
      * @return void
      * @FlowAround("method(.*->greetAction())")
      */
    public function demoAdvice(JoinPointInterface $joinPoint) {
       $name = $joinPoint->getMethodArgument('name');
       return sprintf('%s, you are running out of time!');
    }
}
dev.demo.local/acme.demo/helloworld/greet.html?name=Robert

                 dev.demo.local/acme.demo/helloworld/greet.html?name=Robert




Robert, you are running out of time!
Security
resources:
  methods:
    BookManagementMethods: 'method(.*Controller->(new|create|
edit|update|delete)Action())'

roles:
  Customer: []
  Administrator: []

acls:
  Administrator:
    methods:
      BookManagementMethods: GRANT
Access Denied   (in Development context)
Sessions
/**
 * A Basket
 *
 * @FlowScope("session")
 */
class Basket {

  /**
   * The books
   * @var array
   */
  protected $books;

  /**
    * Adds a book to the basket
    *
    * @param RoeBooksShopDomainModelBasketook $book
    * @return void
    * @FlowSession(autoStart=true)
    */
  public function addBook (Book $book) {
      $this->books[] = $book;
  }
TEXT HERE
TEXT HERE
TEXT HERE
Rossmann
• second biggest drug store
  in Germany
• 5,13 billion € turnover
• 31,000 employees



Customer Database
Amadeus
• world’s biggest
  e-ticket provider
• 217 markets
• 948 million billable
  transactions / year
• 2,7 billion € revenue

Social Media Suite
World of Textile
• textile print and finishing
• 30,000 articles / day
• 180 employees




E-Commerce Platform
2.0
neos.typo3.org
?
Thank you!
Flow      flow.typo3.org
Slides    slideshare.net/robertlemke
Blog      robertlemke.com
Twitter   @robertlemke
Google+   plus.robertlemke.com

TYPO3 Flow and the Joy of Development (FOSDEM 2013)

  • 1.
    The Joy ofDevelopment
  • 2.
    project founder of Flowand Neos coach, coder, consultant Lübeck, Germany 1 wife, 2 daughters, TEXT HERE 1 espresso machine likes drumming
  • 4.
  • 6.
  • 8.
  • 9.
    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
  • 10.
    HTTP/1.1 has beendesigned 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 TYPO3FlowHttpUri 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 TYPO3FlowHttpUri 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;
  • 11.
  • 12.
    $now = newDateTime(); $response->setLastModified($now);
  • 13.
  • 14.
    # set cookiein response: $response->setCookie(new Cookie('counter', 1)); # on next request, retrieve cookie: $cookie = $request->getCookie('counter');
  • 15.
  • 16.
    $request = Request::create($storageUri,'PUT'); $request->setContent(fopen('myfavoritemovie.m4v', 'rb')); $request->setHeader('X-Category', 'Sissy'); $reponse = $browser->sendRequest($request);
  • 17.
  • 18.
    Domain-Driven Design /** * A Book * A methodology which ... * @FlowScope(“prototy pe”) * @FlowEntity */ • results in rich domain models class Book { /** • provides a common language across * @var string the project team */ protected $title; • simplify the design of complex /** * @var string applications */ protected $isbn; /** Flow is the first PHP framework tailored * @var string */ to Domain-Driven Design protected $description ; /** * @var integer */ protected $price;
  • 19.
    /** * ABook * * @FlowEntity */ class Book { /** * The title * @var string * @FlowValidate(type="StringLength", options={ "minimum"=1, */ protected $title; /** * The price * @var integer * @FlowValidate(type="NumberRange", options={ "minimum"=1, */ protected $price;
  • 20.
    /** *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; }
  • 21.
    /** * Arepository for Books * * @FlowScope("singleton") */ class BookRepository extends Repository { public function findBestSellers() { ... } }
  • 22.
    # Add abook $bookRepository->add($book); # Remove a book $bookRepository->remove($book); # Update a book $bookRepository->update($book);
  • 23.
    # Find onespecific book $book = $bookRepository->findOneByTitle('Lord of the Rings'); # Find multiple books by property $books = $bookRepository->findByCategory('Fantasy'); # Find books through custom find method $bestsellingBooks = $bookRepository->findBestSellers();
  • 24.
  • 25.
  • 26.
  • 27.
    class HelloWorldController extendsActionController { /** * @return string */ public function greetAction() { return 'Hello World!'; } }
  • 28.
    Hello World! TEXT HERE
  • 29.
    /** *An action which sends greetings to $name * * @param string $name The name to mention * @return string */ public function greetAction($name) { return "Hello $name!"; }
  • 31.
    dev.demo.local/acme.demo/helloworld/greet.html?name=Robert dev.demo.local/acme.demo/helloworld/greet.html?name=Robert Hello Robert!
  • 32.
  • 33.
    <html lang="en"> <head> <title>Templating</title> </head> <body> Our templating engine is called Fluid </body> </html>
  • 34.
    /** *@param string $name * @return void */ public function greetAction($name) { $this->view->assign('name', $name); }
  • 35.
    <html> <head> <title>Fluid Example</title> </head> <body> <p>Hello, {name}!</p> </body> </html>
  • 36.
    /** *Displays a list of best selling books * * @return void */ public function indexAction() { $books = $this->bookRepository->findBestSellers(); $this->view->assign('books', $books); }
  • 37.
    <ul> <f:for each="{books}" as="book"> <li>{book.title} by {book.author.name}</li> </f:for> </ul>
  • 38.
  • 39.
    <f:form action="create" name="newBook"> <ol> <li> <label for="name">Name</label> <f:form.textfield property="name" id="name" /> </li> <li> <f:form.submit value="Create" /> </li> </ol> </f:form>
  • 40.
    /** *Adds the given new book to the BookRepository * * @param AcmeDemoDomainModelBook $newBook * @return void */ public function createAction(Book $newBook) { $this->bookRepository->add($newBook); $this->addFlashMessage('Created a new book.'); $this->redirect('index'); }
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 47.
  • 48.
  • 49.
    class SomeService { protected static $instance; public function getInstance() { if (self::$instance === NULL) { self::$instance = new self; } return self::$instance; } } class SomeOtherController { public function action() { $service = SomeService::getInstance(); … } }
  • 50.
    class ServiceLocator { protected static $services = array(); public function getInstance($name) { return self::$service[$name]; } } class SomeOtherController { public function action() { $service = ServiceLocate::getInstance("SomeService"); … } }
  • 51.
    Flow's take onDependency 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)
  • 52.
    class BookController extendsActionController { /** * @var BookRepository */ protected $bookRepository; /** * @param BookRepository $bookRepository */ public function __construct(BookRepository $bookRepository) { $this->bookRepository = $bookRepository; } }
  • 53.
    class BookController extendsActionController { /** * @var BookRepository */ protected $bookRepository; /** * @param BookRepository $bookRepository */ public function injectBookRepository(BookRepository $bookRepository) { $this->bookRepository = $bookRepository; } }
  • 54.
    class BookController extendsActionController { /** * @FlowInject * @var BookRepository */ protected $bookRepository; }
  • 55.
  • 56.
    /** *An action which sends greetings to $name * * @param string $name The name to mention * @return string */ public function greetAction($name) { return "Hello $name!"; }
  • 57.
    dev.demo.local/acme.demo/helloworld/greet.html?name=Robert dev.demo.local/acme.demo/helloworld/greet.html?name=Robert Hello Robert!
  • 58.
    /** * @FlowAspect */ class DemoAspect { /** * @param TYPO3FlowAopJoinPointInterface $joinPoint * @return void * @FlowAround("method(.*->greetAction())") */ public function demoAdvice(JoinPointInterface $joinPoint) { $name = $joinPoint->getMethodArgument('name'); return sprintf('%s, you are running out of time!'); } }
  • 59.
    dev.demo.local/acme.demo/helloworld/greet.html?name=Robert dev.demo.local/acme.demo/helloworld/greet.html?name=Robert Robert, you are running out of time!
  • 60.
  • 62.
    resources: methods: BookManagementMethods: 'method(.*Controller->(new|create| edit|update|delete)Action())' roles: Customer: [] Administrator: [] acls: Administrator: methods: BookManagementMethods: GRANT
  • 64.
    Access Denied (in Development context)
  • 65.
  • 66.
    /** * ABasket * * @FlowScope("session") */ class Basket { /** * The books * @var array */ protected $books; /** * Adds a book to the basket * * @param RoeBooksShopDomainModelBasketook $book * @return void * @FlowSession(autoStart=true) */ public function addBook (Book $book) { $this->books[] = $book; }
  • 67.
  • 68.
  • 69.
  • 71.
    Rossmann • second biggestdrug store in Germany • 5,13 billion € turnover • 31,000 employees Customer Database
  • 72.
    Amadeus • world’s biggest e-ticket provider • 217 markets • 948 million billable transactions / year • 2,7 billion € revenue Social Media Suite
  • 73.
    World of Textile •textile print and finishing • 30,000 articles / day • 180 employees E-Commerce Platform
  • 74.
  • 75.
  • 76.
  • 77.
    Thank you! Flow flow.typo3.org Slides slideshare.net/robertlemke Blog robertlemke.com Twitter @robertlemke Google+ plus.robertlemke.com