2. project founder of TYPO3 Flow and TYPO3 Neos
co-founder of the TYPO3 Association
coach, coder, consultant
36 years old
TEXT HERE
lives in Lübeck, Germany
1 wife, 2 daughters, 1 espresso machine
likes drumming
5. Set File Permissions
$ sudo ./flow core:setfilepermissions robert _www _www
TYPO3 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.
Linux:
$ sudo usermod -a -G www-data robert
Mac OS X:
$ sudo dscl . -append /Groups/_www GroupMembership robert
6. 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: 'TYPO3FlowPersistenceDoctrineLoggingSqlLogger'
# You might need to uncomment the following lines and specify
# the location of the PHP binary manually.
# core:
# phpBinaryPathAndFilename: 'C:/path/to/php.exe'
7. 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>
9. 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)
10. 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:
19. H e ll o Wo r ld …
5 2 1 1
Ro bert Lem ke
D.P. F l u x t r
time ();
20. 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
21. 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();
…
}
}
22. class ServiceLocator {
protected static $services = array();
public function getInstance($name) {
return self::$service[$name];
}
}
class SomeOtherController {
public function action() {
$service = ServiceLocator::getInstance("SomeService");
…
}
}
23. class BookController extends ActionController {
/**
* @var BookRepository
*/
protected $bookRepository;
/**
* @param BookRepository $bookRepository
*/
public function __construct(BookRepository $bookRepository) {
$this->bookRepository = $bookRepository;
}
}
24. class BookController extends ActionController {
/**
* @var BookRepository
*/
protected $bookRepository;
/**
* @param BookRepository $bookRepository
*/
public function injectBookRepository(BookRepository
$bookRepository) {
$this->bookRepository = $bookRepository;
}
}
27. 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)
28. class Customer {
/**
* @FlowInject
* @var AcmeCustomerNumberGenerator
*/
protected $customerNumberGenerator;
...
}
$customer = new Customer();
$customer->getCustomerNumber();
29. Object Management
<?php
declare(ENCODING = 'u
tf-8');
namespace TYPO3Conf
Flow creates proxy use TYPO3FlowAnnot
erenceDomainModel
ations as Flow;
Conference;
classes /**
* Autogenerated Prox
for realizing DI and AOP * @FlowScope(“proto
* @FlowEntity
y Class
type”)
magic */
class Paper extends
Paper_Original implem
TYPO3FlowPersiste ents TYPO3FlowObje
nceAspectPersisten c
ceMagicInterface {
_ new operator is /**
* @var string
supported * @ORMId
* @ORMColumn(length
="40")
* introduced by TYPO
3FlowPersistenceA
spectPersistenceMag
_ proxy classes are */
protected $Flow_Pers
istence_Identifier =
i
NULL;
created on the fly private $Flow_AOP_Pr
oxy_targetMethodsAnd
GroupedAdvices = arra
y
private $Flow_AOP_Pr
oxy_groupedAdviceCha
_ in production context private $Flow_AOP_Pr
oxy_methodIsInAdvice
ins = array();
all code is static Mode = array();
/**
* Autogenerated Prox
y Method
*/
public function __co
nstruct() {
30. Object Scope
/**
* @FlowScope("prototype")
*/
class BookController extends ActionController {
_ prototype: multiple instances for one request
_ singleton: one unique instance for one request
_ session: one unique instance for one session
_ default scope: prototype.
31. 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 :
…
}
}
32. Lifecycle Methods
/**
* Called shortly before the framework shuts down
*/
public function shutdownObject() {
}
33. 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
34. AOP
/**
* @Aspect
FLOW3 uses AOP for ... * @Introduce
TYPO3FlowPe
*/ rsistenceAsp
ectPer
class Persist
enceMagicAspe
_ persistence magic ct {
/**
* @Pointcut c
_ logging */
lassTaggedWit
h(entity) ||
classT
public functi
on isEntityOr
V a l u e O b j e c t( )
_ debugging /**
{}
* After retur
ning advice,
* making sure w
_ security * @param TYP
e have
O3FlowAOPJ
* @return voi oinPointInter
d face $j
* @Before cla
ssTaggedWith(
*/ entity) && me
thod(.*
public functi
on generateUU
$proxy = $joi I D( J o i n P o i n t I
n P o i n t- >g e t P r nterface
O b j e c t A c c e s s: oxy();
:setProperty(
} $proxy, 'Flow
_Persis
35.
36. Aspect
_ part of the application where cross-cutting concerns are
implemented
_ in Flow aspects are classes annotated with
@FlowAspect
43. /**
* An aspect which centralizes the logging of important session actions.
*
* @FlowAspect
* @FlowScope("singleton")
*/
class LoggingAspect {
/**
* @var TYPO3FlowLogSystemLoggerInterface
* @FlowInject
*/
protected $systemLogger;
/**
* Logs calls of start()
*
* @FlowAfter("within(TYPO3FlowSessionSessionInterface) && method(.*->start())"
* @param TYPO3FlowAopJoinPointInterface $joinPoint The current joinpoint
*/
public function logStart(TYPO3FlowAopJoinPointInterface $joinPoint) {
$session = $joinPoint->getProxy();
if ($session->isStarted()) {
$this->systemLogger->log(sprintf('Started session with id %s', $session->getId(
44. 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
45. // 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);
46. Annotations
In order to use less code, the following examples assume
that annotations have been imported directly:
use TYPO3FlowAnnotationsEntity;
/**
* @Entity
*/
class Foo {}
48. 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 Defines relations to other entities.
@OneToMany Unlike with vanilla Doctrine
@ManyToMany targetEntity does not have to be given
@OneToOne but will be reused from the @var
annotation.
cascade can be used to cascade
operation to related objects.
49. Persistence-related Annotations
@var Defines the type of a property,
collections can be typed using angle
brackets
Collection<TYPO3ConferenceDomainModelComment>
@transient The property will be ignored, it will
neither be persisted nor reconstituted
@identity Marks the property as part of an objects
identity
50. Custom Queries using the
Query Object Model
class PostRepository extends Repository {
/**
* Finds posts by the specified tag and blog
*
* @param TYPO3BlogDomainModelTag $tag
* @param TYPO3BlogDomainModelBlog $blog The blog the post must refe
* @return TYPO3FlowPersistenceQueryResultInterface The posts
*/
public function findByTagAndBlog(TYPO3BlogDomainModelTag $tag,
TYPO3BlogDomainModelBlog $blog) {
$query = $this->createQuery();
return $query->matching(
$query->logicalAnd(
$query->equals('blog', $blog),
$query->contains('tags', $tag)
)
51. 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
53. Schema Management
Manual database updates
Ad-hoc table and column creation, while you’re developing:
$ ./flow doctrine:create
$ ./flow doctrine:update
54. 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
55. 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
56. Accounts, Users, Authentication
Flow distinguishes between accounts and persons:
_ account: TYPO3FlowSecurityAccount
_ person: TYPO3PartyDomainModelPerson
A person (or machine) can have any number of accounts.
57. 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
59. 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
61. Security Policy (policy.yaml)
_ resources
defines what can potentially be protected
_ roles
defines who can potentially be granted or denied access
_ acls
defines who may or may not access which resource
66. 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...
67. 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
68. 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