typo3 flow 2.0 workshop t3board13
DESCRIPTION
Slides of the TYPO3 Flow 2.0 fundamentals workshop which took place at Schmittenhöhe, Austria during T3BOARD13TRANSCRIPT
![Page 1: TYPO3 Flow 2.0 Workshop T3BOARD13](https://reader033.vdocuments.us/reader033/viewer/2022060110/555a8ca9d8b42a991b8b4626/html5/thumbnails/1.jpg)
TYPO3 Flow 2.0
Robert Lemke_
![Page 2: TYPO3 Flow 2.0 Workshop T3BOARD13](https://reader033.vdocuments.us/reader033/viewer/2022060110/555a8ca9d8b42a991b8b4626/html5/thumbnails/2.jpg)
TEXT HERE
project founder of TYPO3 Flow and TYPO3 Neos
co-founder of the TYPO3 Association
coach, coder, consultant
36 years old
lives in Lübeck, Germany
1 wife, 2 daughters, 1 espresso machine
likes drumming
![Page 3: TYPO3 Flow 2.0 Workshop T3BOARD13](https://reader033.vdocuments.us/reader033/viewer/2022060110/555a8ca9d8b42a991b8b4626/html5/thumbnails/3.jpg)
TYPO3 Flow Website and Download
![Page 4: TYPO3 Flow 2.0 Workshop T3BOARD13](https://reader033.vdocuments.us/reader033/viewer/2022060110/555a8ca9d8b42a991b8b4626/html5/thumbnails/4.jpg)
Installation via Composer
$ curl -s https://getcomposer.org/installer | php$ sudo mv composer.phar /usr/local/bin/composer
$ composer create-project --stability="beta" --dev typo3/flow-base-distribution MyProject
![Page 5: TYPO3 Flow 2.0 Workshop T3BOARD13](https://reader033.vdocuments.us/reader033/viewer/2022060110/555a8ca9d8b42a991b8b4626/html5/thumbnails/5.jpg)
Set File Permissions
$ sudo ./flow core:setfilepermissions robert _www _wwwTYPO3 Flow 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 robert
$ sudo dscl . -append /Groups/_www GroupMembership robert
Linux:
Mac OS X:
![Page 6: TYPO3 Flow 2.0 Workshop T3BOARD13](https://reader033.vdocuments.us/reader033/viewer/2022060110/555a8ca9d8b42a991b8b4626/html5/thumbnails/6.jpg)
Set Up Database Connection
Configuration/Settings.yaml
TYPO3: Flow: persistence: backendOptions: host: '127.0.0.1' # adjust to your database host dbname: 'training' # adjust to your database name user: 'root' # adjust to your database user password: 'password' # adjust to your database password
# if you want to log executed SQL queries, enable the next 2 lines # doctrine: # sqlLogger: 'TYPO3\Flow\Persistence\Doctrine\Logging\SqlLogger'
# You might need to uncomment the following lines and specify # the location of the PHP binary manually. # core: # phpBinaryPathAndFilename: 'C:/path/to/php.exe'
![Page 7: TYPO3 Flow 2.0 Workshop T3BOARD13](https://reader033.vdocuments.us/reader033/viewer/2022060110/555a8ca9d8b42a991b8b4626/html5/thumbnails/7.jpg)
Set Up Virtual Host
Apache Virtual Host
<VirtualHost *:80> DocumentRoot ~/Sites/Flow/Web/ ServerName flow.dev SetEnv FLOW_CONTEXT Development</VirtualHost>
<VirtualHost *:80> DocumentRoot ~/Sites/Flow/Web/ ServerName flow.prod SetEnv FLOW_CONTEXT Production</VirtualHost>
![Page 8: TYPO3 Flow 2.0 Workshop T3BOARD13](https://reader033.vdocuments.us/reader033/viewer/2022060110/555a8ca9d8b42a991b8b4626/html5/thumbnails/8.jpg)
Final Check
![Page 9: TYPO3 Flow 2.0 Workshop T3BOARD13](https://reader033.vdocuments.us/reader033/viewer/2022060110/555a8ca9d8b42a991b8b4626/html5/thumbnails/9.jpg)
Command Line Use
$ ./flow help kickstart:package
Kickstart a new package
COMMAND: typo3.kickstart:kickstart:package
USAGE: ./flow kickstart:package <package key>
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.flow:package:create (Create a new package)
![Page 10: TYPO3 Flow 2.0 Workshop T3BOARD13](https://reader033.vdocuments.us/reader033/viewer/2022060110/555a8ca9d8b42a991b8b4626/html5/thumbnails/10.jpg)
Command Line Use
$ ./flow help kickstart:actioncontroller
Kickstart a new action controller
COMMAND: typo3.kickstart:kickstart:actioncontroller
USAGE: ./flow kickstart:actioncontroller [<options>] <package key> <controller name>
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 indexAction. By specifying the --generate-actions flag, this command will also create a set of actions. If no model or repository exists which matches the controller name (for example "CoffeeRepository" for "CoffeeController"), an error will be shown. Likewise the command exits with an error if the specified package does not exist. By using the --generate-related flag, a missing package, model or repository can be created alongside, avoiding such an error. By specifying the --generate-templates flag, this command will also create matching Fluid templates for the actions created. This option can only be used in combination with --generate-actions. The default behavior is to not overwrite any existing code. This can be overridden by specifying the --force flag.
SEE ALSO: typo3.kickstart:kickstart:commandcontroller (Kickstart a new command controller)
![Page 11: TYPO3 Flow 2.0 Workshop T3BOARD13](https://reader033.vdocuments.us/reader033/viewer/2022060110/555a8ca9d8b42a991b8b4626/html5/thumbnails/11.jpg)
Biggest Book Store: Amazon
![Page 12: TYPO3 Flow 2.0 Workshop T3BOARD13](https://reader033.vdocuments.us/reader033/viewer/2022060110/555a8ca9d8b42a991b8b4626/html5/thumbnails/12.jpg)
Biggest River: Amazon River
![Page 13: TYPO3 Flow 2.0 Workshop T3BOARD13](https://reader033.vdocuments.us/reader033/viewer/2022060110/555a8ca9d8b42a991b8b4626/html5/thumbnails/13.jpg)
Smallest River: Roe River
![Page 14: TYPO3 Flow 2.0 Workshop T3BOARD13](https://reader033.vdocuments.us/reader033/viewer/2022060110/555a8ca9d8b42a991b8b4626/html5/thumbnails/14.jpg)
Smallest River: Roe River
![Page 15: TYPO3 Flow 2.0 Workshop T3BOARD13](https://reader033.vdocuments.us/reader033/viewer/2022060110/555a8ca9d8b42a991b8b4626/html5/thumbnails/15.jpg)
Smallest River: Roe River
![Page 16: TYPO3 Flow 2.0 Workshop T3BOARD13](https://reader033.vdocuments.us/reader033/viewer/2022060110/555a8ca9d8b42a991b8b4626/html5/thumbnails/16.jpg)
Smallest River: Roe River
![Page 17: TYPO3 Flow 2.0 Workshop T3BOARD13](https://reader033.vdocuments.us/reader033/viewer/2022060110/555a8ca9d8b42a991b8b4626/html5/thumbnails/17.jpg)
Smallest Book Store: Roebooks
![Page 18: TYPO3 Flow 2.0 Workshop T3BOARD13](https://reader033.vdocuments.us/reader033/viewer/2022060110/555a8ca9d8b42a991b8b4626/html5/thumbnails/18.jpg)
Sketchy Model
![Page 19: TYPO3 Flow 2.0 Workshop T3BOARD13](https://reader033.vdocuments.us/reader033/viewer/2022060110/555a8ca9d8b42a991b8b4626/html5/thumbnails/19.jpg)
Robert LemkeD.P. Fluxtr
time();
5 1 12
Hello World …
![Page 20: TYPO3 Flow 2.0 Workshop T3BOARD13](https://reader033.vdocuments.us/reader033/viewer/2022060110/555a8ca9d8b42a991b8b4626/html5/thumbnails/20.jpg)
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 21: TYPO3 Flow 2.0 Workshop T3BOARD13](https://reader033.vdocuments.us/reader033/viewer/2022060110/555a8ca9d8b42a991b8b4626/html5/thumbnails/21.jpg)
<?php
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(); … } }
?>
![Page 22: TYPO3 Flow 2.0 Workshop T3BOARD13](https://reader033.vdocuments.us/reader033/viewer/2022060110/555a8ca9d8b42a991b8b4626/html5/thumbnails/22.jpg)
class ServiceLocator { protected static $services = array(); public function getInstance($name) { return self::$service[$name]; }
}
class SomeOtherController { public function action() { $service = ServiceLocator::getInstance("SomeService"); … } }
![Page 23: TYPO3 Flow 2.0 Workshop T3BOARD13](https://reader033.vdocuments.us/reader033/viewer/2022060110/555a8ca9d8b42a991b8b4626/html5/thumbnails/23.jpg)
class BookController extends ActionController {
/** * @var BookRepository */ protected $bookRepository; /** * @param BookRepository $bookRepository */ public function __construct(BookRepository $bookRepository) { $this->bookRepository = $bookRepository; } }
![Page 24: TYPO3 Flow 2.0 Workshop T3BOARD13](https://reader033.vdocuments.us/reader033/viewer/2022060110/555a8ca9d8b42a991b8b4626/html5/thumbnails/24.jpg)
class BookController extends ActionController {
/** * @var BookRepository */ protected $bookRepository; /** * @param BookRepository $bookRepository */ public function injectBookRepository(BookRepository $bookRepository) { $this->bookRepository = $bookRepository; } }
![Page 25: TYPO3 Flow 2.0 Workshop T3BOARD13](https://reader033.vdocuments.us/reader033/viewer/2022060110/555a8ca9d8b42a991b8b4626/html5/thumbnails/25.jpg)
class BookController extends ActionController {
/** * @Flow\Inject * @var BookRepository */ protected $bookRepository;
}
![Page 26: TYPO3 Flow 2.0 Workshop T3BOARD13](https://reader033.vdocuments.us/reader033/viewer/2022060110/555a8ca9d8b42a991b8b4626/html5/thumbnails/26.jpg)
TYPO3\Flow\Security\Cryptography\RsaWalletServiceInterface: className: TYPO3\Flow\Security\Cryptography\RsaWalletServicePhp scope: singleton properties: keystoreCache: object: factoryObjectName: TYPO3\FLOW3\Cache\CacheManager factoryMethodName: getCache arguments: 1: value: FLOW3_Security_Cryptography_RSAWallet
![Page 27: TYPO3 Flow 2.0 Workshop T3BOARD13](https://reader033.vdocuments.us/reader033/viewer/2022060110/555a8ca9d8b42a991b8b4626/html5/thumbnails/27.jpg)
Object Management
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 gatered automatically (autowiring)
_ intuitive use and no bad magical surprises
_ fast! (like hardcoded or faster)
![Page 28: TYPO3 Flow 2.0 Workshop T3BOARD13](https://reader033.vdocuments.us/reader033/viewer/2022060110/555a8ca9d8b42a991b8b4626/html5/thumbnails/28.jpg)
class Customer {
/** * @Flow\Inject * @var \Acme\CustomerNumberGenerator */ protected $customerNumberGenerator; ...}
$customer = new Customer();$customer->getCustomerNumber();
![Page 29: TYPO3 Flow 2.0 Workshop T3BOARD13](https://reader033.vdocuments.us/reader033/viewer/2022060110/555a8ca9d8b42a991b8b4626/html5/thumbnails/29.jpg)
Object Management
<?phpdeclare(ENCODING = 'utf-8');namespace TYPO3\Conference\Domain\Model\Conference;use TYPO3\Flow\Annotations as Flow;/** * Autogenerated Proxy Class * @Flow\Scope(“prototype”) * @Flow\Entity */class Paper extends Paper_Original implements \TYPO3\Flow\Object\Proxy\ProxyInterface, \TYPO3\Flow\Persistence\Aspect\PersistenceMagicInterface { /** * @var string * @ORM\Id * @ORM\Column(length="40") * introduced by TYPO3\Flow\Persistence\Aspect\PersistenceMagicAspect */ protected $Flow_Persistence_Identifier = NULL; private $Flow_AOP_Proxy_targetMethodsAndGroupedAdvices = array(); private $Flow_AOP_Proxy_groupedAdviceChains = array(); private $Flow_AOP_Proxy_methodIsInAdviceMode = array();
/** * Autogenerated Proxy Method */ public function __construct() { $this->Flow_AOP_Proxy_buildMethodsAndAdvicesArray(); if (isset($this->Flow_AOP_Proxy_methodIsInAdviceMode['__construct'])) { parent::__construct();
} else {
Flow 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 30: TYPO3 Flow 2.0 Workshop T3BOARD13](https://reader033.vdocuments.us/reader033/viewer/2022060110/555a8ca9d8b42a991b8b4626/html5/thumbnails/30.jpg)
Object Scope
_ prototype: multiple instances for one request
_ singleton: one unique instance for one request
_ session: one unique instance for one session
_ default scope: prototype.
/** * @Flow\Scope("prototype") */class BookController extends ActionController {
![Page 31: TYPO3 Flow 2.0 Workshop T3BOARD13](https://reader033.vdocuments.us/reader033/viewer/2022060110/555a8ca9d8b42a991b8b4626/html5/thumbnails/31.jpg)
Lifecycle Methods
/** * Called after the object has been constructed and all * dependencies have been injected * * @param integer $initializationCause * @return void */ public function initializeObject($initializationCause) { switch ($initializationCause) { case ObjectManagerInterface::INITIALIZATIONCAUSE_CREATED : … case ObjectManagerInterface::INITIALIZATIONCAUSE_RECREATED : … } }
![Page 32: TYPO3 Flow 2.0 Workshop T3BOARD13](https://reader033.vdocuments.us/reader033/viewer/2022060110/555a8ca9d8b42a991b8b4626/html5/thumbnails/32.jpg)
Lifecycle Methods
/** * Called shortly before the framework shuts down */ public function shutdownObject() { }
![Page 33: TYPO3 Flow 2.0 Workshop T3BOARD13](https://reader033.vdocuments.us/reader033/viewer/2022060110/555a8ca9d8b42a991b8b4626/html5/thumbnails/33.jpg)
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 34: TYPO3 Flow 2.0 Workshop T3BOARD13](https://reader033.vdocuments.us/reader033/viewer/2022060110/555a8ca9d8b42a991b8b4626/html5/thumbnails/34.jpg)
AOP
FLOW3 uses AOP for ...
_ persistence magic
_ logging
_ debugging
_ security
/** * @Aspect * @Introduce TYPO3\Flow\Persistence\Aspect\PersistenceMagicInterface, TYPO3\Flow\Persistence
*/class PersistenceMagicAspect { /** * @Pointcut classTaggedWith(entity) || classTaggedWith(valueobject) */ public function isEntityOrValueObject() {} /** * After returning advice, making sure we have an UUID for each and every entity.
* * @param \TYPO3\Flow\AOP\JoinPointInterface $joinPoint The current join point
* @return void * @Before classTaggedWith(entity) && method(.*->__construct()) */ public function generateUUID(JoinPointInterface $joinPoint) { $proxy = $joinPoint->getProxy(); ObjectAccess::setProperty($proxy, 'Flow_Persistence_Identifier', … }
![Page 35: TYPO3 Flow 2.0 Workshop T3BOARD13](https://reader033.vdocuments.us/reader033/viewer/2022060110/555a8ca9d8b42a991b8b4626/html5/thumbnails/35.jpg)
![Page 36: TYPO3 Flow 2.0 Workshop T3BOARD13](https://reader033.vdocuments.us/reader033/viewer/2022060110/555a8ca9d8b42a991b8b4626/html5/thumbnails/36.jpg)
Aspect
_ part of the application where cross-cutting concerns are implemented
_ in Flow aspects are classes annotated with@Flow\Aspect
![Page 37: TYPO3 Flow 2.0 Workshop T3BOARD13](https://reader033.vdocuments.us/reader033/viewer/2022060110/555a8ca9d8b42a991b8b4626/html5/thumbnails/37.jpg)
Join Point
A single point in the call graph
_ method execution
_ exception
![Page 38: TYPO3 Flow 2.0 Workshop T3BOARD13](https://reader033.vdocuments.us/reader033/viewer/2022060110/555a8ca9d8b42a991b8b4626/html5/thumbnails/38.jpg)
Join Point
A single point in the call graph
_ method execution
_ exception
Represents an event, not a location
![Page 39: TYPO3 Flow 2.0 Workshop T3BOARD13](https://reader033.vdocuments.us/reader033/viewer/2022060110/555a8ca9d8b42a991b8b4626/html5/thumbnails/39.jpg)
Pointcut
A set of join points where advices could be executed
_ can be composed
_ can be named
![Page 40: TYPO3 Flow 2.0 Workshop T3BOARD13](https://reader033.vdocuments.us/reader033/viewer/2022060110/555a8ca9d8b42a991b8b4626/html5/thumbnails/40.jpg)
Advice
Action to take at a join points defined by the point cut
![Page 41: TYPO3 Flow 2.0 Workshop T3BOARD13](https://reader033.vdocuments.us/reader033/viewer/2022060110/555a8ca9d8b42a991b8b4626/html5/thumbnails/41.jpg)
Kinds of Advice
Advice types supported by Flow:
@Flow\Before@Flow\AfterReturning@Flow\AfterThrowing@Flow\After@Flow\Around
![Page 42: TYPO3 Flow 2.0 Workshop T3BOARD13](https://reader033.vdocuments.us/reader033/viewer/2022060110/555a8ca9d8b42a991b8b4626/html5/thumbnails/42.jpg)
Pointcut Designators
method(Acme\Demo\MyClass->myMethod())class(Acme\Demo\MyClass)within(Acme\Demo\MyInterface)classAnnotatedWith(someTag)methodAnnotatedWith(anotherTag)setting(Acme.Demo.SomeSetting = "yeah, do it")filter(Acme\Demo\MyCustomFilterImplementation)
evaluate(coffe.kind = "Arabica")
![Page 43: TYPO3 Flow 2.0 Workshop T3BOARD13](https://reader033.vdocuments.us/reader033/viewer/2022060110/555a8ca9d8b42a991b8b4626/html5/thumbnails/43.jpg)
namespace TYPO3\Flow\Session\Aspect;use TYPO3\Flow\Annotations as Flow;
/** * An aspect which centralizes the logging of important session actions. * * @Flow\Aspect * @Flow\Scope("singleton") */class LoggingAspect {
/** * @var \TYPO3\Flow\Log\SystemLoggerInterface * @Flow\Inject */ protected $systemLogger;
/** * Logs calls of start() * * @Flow\After("within(TYPO3\Flow\Session\SessionInterface) && method(.*->start())") * @param \TYPO3\Flow\Aop\JoinPointInterface $joinPoint The current joinpoint */ public function logStart(\TYPO3\Flow\Aop\JoinPointInterface $joinPoint) { $session = $joinPoint->getProxy(); if ($session->isStarted()) { $this->systemLogger->log(sprintf('Started session with id %s', $session->getId()), LOG_DEBUG);
} }
![Page 44: TYPO3 Flow 2.0 Workshop T3BOARD13](https://reader033.vdocuments.us/reader033/viewer/2022060110/555a8ca9d8b42a991b8b4626/html5/thumbnails/44.jpg)
Persistence
Object Persistence in the Flow
_ based on Doctrine 2
_ seamless integration into Flow
_ provides all the great Doctrine 2 features
_ uses UUIDs
_ low level persistence API
_ allows for own, custom persistence backends (instead of Doctrine 2)
_ e.g. CouchDB, Solr
![Page 45: TYPO3 Flow 2.0 Workshop T3BOARD13](https://reader033.vdocuments.us/reader033/viewer/2022060110/555a8ca9d8b42a991b8b4626/html5/thumbnails/45.jpg)
// 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 46: TYPO3 Flow 2.0 Workshop T3BOARD13](https://reader033.vdocuments.us/reader033/viewer/2022060110/555a8ca9d8b42a991b8b4626/html5/thumbnails/46.jpg)
Annotations
In order to use less code, the following examples assume that annotations have been imported directly:
use TYPO3\Flow\Annotations\Entity;
/** * @Entity */class Foo {}
![Page 47: TYPO3 Flow 2.0 Workshop T3BOARD13](https://reader033.vdocuments.us/reader033/viewer/2022060110/555a8ca9d8b42a991b8b4626/html5/thumbnails/47.jpg)
Validation and Doctrine Annotations
/** * @Entity */class Blog {
/** * @var string * @Validate Text, StringLength(minimum = 1, maximum = 80) * @Column(length="80") */ protected $title;
/** * @var \Doctrine\Common\Collections\Collection<\TYPO3\Blog\Domain\Model\Post> * @OneToMany(mappedBy="blog") * @OrderBy({"date" = "DESC"}) */ protected $posts;
...
}
![Page 48: TYPO3 Flow 2.0 Workshop T3BOARD13](https://reader033.vdocuments.us/reader033/viewer/2022060110/555a8ca9d8b42a991b8b4626/html5/thumbnails/48.jpg)
Persistence-related Annotations
@Entity Declares a class as "entity"
@Column Controls the database column related to the class property. Very useful for longer text content (type="text" !)
@ManyToOne @OneToMany @ManyToMany@OneToOne
Defines relations to other entities. Unlike with vanilla Doctrine targetEntity does not have to be given but will be reused from the @var annotation.
cascade can be used to cascade operation to related objects.
![Page 49: TYPO3 Flow 2.0 Workshop T3BOARD13](https://reader033.vdocuments.us/reader033/viewer/2022060110/555a8ca9d8b42a991b8b4626/html5/thumbnails/49.jpg)
@var Defines the type of a property, collections can be typed using angle brackets
Collection<\TYPO3\Conference\Domain\Model\Comment>
@transient The property will be ignored, it will neither be persisted nor reconstituted
@identity Marks the property as part of an objects identity
Persistence-related Annotations
![Page 50: TYPO3 Flow 2.0 Workshop T3BOARD13](https://reader033.vdocuments.us/reader033/viewer/2022060110/555a8ca9d8b42a991b8b4626/html5/thumbnails/50.jpg)
Custom Queries using theQuery Object Model
class PostRepository extends Repository {
/** * Finds posts by the specified tag and blog * * @param \TYPO3\Blog\Domain\Model\Tag $tag * @param \TYPO3\Blog\Domain\Model\Blog $blog The blog the post must refer to * @return \TYPO3\Flow\Persistence\QueryResultInterface The posts */ public function findByTagAndBlog(\TYPO3\Blog\Domain\Model\Tag $tag, \TYPO3\Blog\Domain\Model\Blog $blog) { $query = $this->createQuery(); return $query->matching( $query->logicalAnd( $query->equals('blog', $blog), $query->contains('tags', $tag) ) ) ->setOrderings(array( 'date' => \TYPO3\Flow\Persistence\QueryInterface::ORDER_DESCENDING) ) ->execute(); }}
![Page 51: TYPO3 Flow 2.0 Workshop T3BOARD13](https://reader033.vdocuments.us/reader033/viewer/2022060110/555a8ca9d8b42a991b8b4626/html5/thumbnails/51.jpg)
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 Flow
![Page 52: TYPO3 Flow 2.0 Workshop T3BOARD13](https://reader033.vdocuments.us/reader033/viewer/2022060110/555a8ca9d8b42a991b8b4626/html5/thumbnails/52.jpg)
Schema Management
Executing migration scripts
Needed after installation or upgrade:
$ ./flow doctrine:migrate
![Page 53: TYPO3 Flow 2.0 Workshop T3BOARD13](https://reader033.vdocuments.us/reader033/viewer/2022060110/555a8ca9d8b42a991b8b4626/html5/thumbnails/53.jpg)
Schema Management
Manual database updates
Ad-hoc table and column creation, while you’re developing:
$ ./flow doctrine:create
$ ./flow doctrine:update
![Page 54: TYPO3 Flow 2.0 Workshop T3BOARD13](https://reader033.vdocuments.us/reader033/viewer/2022060110/555a8ca9d8b42a991b8b4626/html5/thumbnails/54.jpg)
Schema Management
Generating migration scripts
Creates a basis for a migration script which sometimes needs to be adjusted but in any case needs to be checked:
$ ./flow doctrine:migrationgenerate
![Page 55: TYPO3 Flow 2.0 Workshop T3BOARD13](https://reader033.vdocuments.us/reader033/viewer/2022060110/555a8ca9d8b42a991b8b4626/html5/thumbnails/55.jpg)
Security
_ centrally managed (through AOP)
_ as secure as possible by default
_ modeled after TYPO3 CMS and Spring Security
_ authentication, authorization, validation, filtering ...
_ can intercept arbitrary method calls
_ transparently filters content through query-rewriting
_ extensible for new authentication or authorization mechanisms
![Page 56: TYPO3 Flow 2.0 Workshop T3BOARD13](https://reader033.vdocuments.us/reader033/viewer/2022060110/555a8ca9d8b42a991b8b4626/html5/thumbnails/56.jpg)
Accounts, Users, Authentication
Flow distinguishes between accounts and persons:
_ account: \TYPO3\Flow\Security\Account
_ person: \TYPO3\Party\Domain\Model\Person
A person (or machine) can have any number of accounts.
![Page 57: TYPO3 Flow 2.0 Workshop T3BOARD13](https://reader033.vdocuments.us/reader033/viewer/2022060110/555a8ca9d8b42a991b8b4626/html5/thumbnails/57.jpg)
Creating Accounts
_ always use the AccountFactory
_ create a party (eg. a Person) separately
_ assign the account to the party
_ add account and party to their respective repositories
![Page 58: TYPO3 Flow 2.0 Workshop T3BOARD13](https://reader033.vdocuments.us/reader033/viewer/2022060110/555a8ca9d8b42a991b8b4626/html5/thumbnails/58.jpg)
$account = $this->accountFactory->createAccountWithPassword( $accountIdentifier, $password, array($role));
$this->accountRepository->add($account);
$person = new Person();$person->addAccount($account);
$name = new PersonName('', 'Robert', '', 'Lemke');$person->setName($name);
$this->partyRepository->add($person);
![Page 59: TYPO3 Flow 2.0 Workshop T3BOARD13](https://reader033.vdocuments.us/reader033/viewer/2022060110/555a8ca9d8b42a991b8b4626/html5/thumbnails/59.jpg)
Authentication Configuration
_ Authentication Provider is responsible for authentication in a specific "area"
_ Entry Point kicks in if a restricted resource is accessed and no account is authenticated yet
![Page 60: TYPO3 Flow 2.0 Workshop T3BOARD13](https://reader033.vdocuments.us/reader033/viewer/2022060110/555a8ca9d8b42a991b8b4626/html5/thumbnails/60.jpg)
TYPO3: Flow: security: authentication: providers: DefaultProvider: provider: 'PersistedUsernamePasswordProvider' entryPoint: 'WebRedirect' entryPointOptions: routeValues: '@package': 'RobertLemke.Example.Bookshop' '@controller': 'Login' '@action': 'login' '@format': 'html'
![Page 61: TYPO3 Flow 2.0 Workshop T3BOARD13](https://reader033.vdocuments.us/reader033/viewer/2022060110/555a8ca9d8b42a991b8b4626/html5/thumbnails/61.jpg)
Security Policy (policy.yaml)
_ resources defines what can potentially be protected
_ roles defines who can potentially be granted or denied access
_ aclsdefines who may or may not access which resource
![Page 62: TYPO3 Flow 2.0 Workshop T3BOARD13](https://reader033.vdocuments.us/reader033/viewer/2022060110/555a8ca9d8b42a991b8b4626/html5/thumbnails/62.jpg)
resources: methods: BookManagementMethods: 'method(.*Controller->(new|edit|create|delete|update)Action())' BookManagementDelete: 'method(.*BookController->deleteAction())'
roles: Administrator: []
acls: methods: Administrator: BookManagementMethods: GRANT
![Page 63: TYPO3 Flow 2.0 Workshop T3BOARD13](https://reader033.vdocuments.us/reader033/viewer/2022060110/555a8ca9d8b42a991b8b4626/html5/thumbnails/63.jpg)
Login / Logout
_ simply extend AbstractAuthenticationController
_ create a Fluid template with a login form
![Page 64: TYPO3 Flow 2.0 Workshop T3BOARD13](https://reader033.vdocuments.us/reader033/viewer/2022060110/555a8ca9d8b42a991b8b4626/html5/thumbnails/64.jpg)
/** * @Flow\Scope("singleton") */class LoginController extends AbstractAuthenticationController {
/** * @param \TYPO3\Flow\Mvc\ActionRequest $originalRequest The request that * @return string */ protected function onAuthenticationSuccess(ActionRequest $originalRequest = NULL) { $this->redirect('index', 'Book'); }
/** * @return void */ public function logoutAction() { parent::logoutAction(); $this->redirect('index', 'Book'); }}
![Page 65: TYPO3 Flow 2.0 Workshop T3BOARD13](https://reader033.vdocuments.us/reader033/viewer/2022060110/555a8ca9d8b42a991b8b4626/html5/thumbnails/65.jpg)
<f:base/><f:flashMessages /><f:form action="authenticate"> <f:form.textfield name="__authentication[TYPO3][Flow][Security][Authentication][Token][UsernamePassword][username]" /> <f:form.password name="__authentication[TYPO3][Flow][Security][Authentication][Token][UsernamePassword][password]" /> <f:form.submit value="login" /></f:form>
![Page 66: TYPO3 Flow 2.0 Workshop T3BOARD13](https://reader033.vdocuments.us/reader033/viewer/2022060110/555a8ca9d8b42a991b8b4626/html5/thumbnails/66.jpg)
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 67: TYPO3 Flow 2.0 Workshop T3BOARD13](https://reader033.vdocuments.us/reader033/viewer/2022060110/555a8ca9d8b42a991b8b4626/html5/thumbnails/67.jpg)
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 68: TYPO3 Flow 2.0 Workshop T3BOARD13](https://reader033.vdocuments.us/reader033/viewer/2022060110/555a8ca9d8b42a991b8b4626/html5/thumbnails/68.jpg)
Security
CSRF Protection in Flow
_ you must not forget to add that token to any link
_ Flow 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 69: TYPO3 Flow 2.0 Workshop T3BOARD13](https://reader033.vdocuments.us/reader033/viewer/2022060110/555a8ca9d8b42a991b8b4626/html5/thumbnails/69.jpg)
Robert Lemke_robertlemke.com@robertlemke