A key feature of TYPO3 today is its extendability and flexibility. Writing extensions was never easier since the Kickstarter, and tslib_piBase. But, time doesn't stand still: new programming paradigms other innovative frameworks came up. It's time to take a next step to faster, cleaner extension coding. With the new Version 5 of TYPO3 and its basis FLOW3 the way to develop extensions will change fundamentally. With Extbase - the new framework for extension development introduced in TYPO3 4.3 - you are able to develop with the paradigms of FLOW3 today. During this talk, you get in touch with the features of the framework to understand how it supports your development process. We also address the users perspective by discussing best practices how to migrate to TYPO3 v5.
27. Value
enables and encourages the developer to write maintainable code
separates di erent responsibilities
modular architecture of the extension
relieves the developer in safety-critical and recurring tasks
validation of arguments
invoking the template mechanism
persistence
read out the settings from TypoScript and FlexForms
enables and encourages the developer to focus on solving the problem of the client
saves primary and adapting development time (direct and indirect costs)
42. Blog features
administrate blogs, blog posts and blog comments
list all available blogs
list all blog posts of a blog
list all comments of a blog post
allow users to post new comments
43. Blog features
administrate blogs, blog posts and blog comments
Blog
list all available blogs
list all blog posts of a blog
list all comments of a blog post
allow users to post new comments
44. Blog features
administrate blogs, blog posts and blog comments
Blog
list all available blogs
list all blog posts of a blog
list all comments of a blog post
allow users to post new comments Post
Comment Tag
53. Task 1: Output a listing of blogs
<!-- ###SUBPART_BLOGELEMENT### begin -->
<div class="blog element">
! ###BLOG_NAME###
! ###BLOG_LOGO###
! ###BLOG_DESCRIPTION###
! ###BLOG_MORELINK###
</div>
<!-- ###SUBPART_BLOGELEMENT### end -->
54. Task 2: Display a single post with its comments
protected function renderPost() {
! $post = $this->pi_getRecord('tx_blogexample_post', $this->piVars['postUid']);
! $comments = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows(
! ! '*',
! ! 'tx_blogexample_comment',
! ! 'deleted=0 AND hidden=0 AND sys_language_uid='
. $GLOBALS['TSFE']->sys_language_uid
! ! ! . ' AND post_uid=' . $this->piVars['postUid'] . ' AND post_table="tx_blogexample_post"'
. $this->cObj->enableFields('tx_blogexample_comment'),
! ! '',
! ! 'date DESC'
! );
// fill marker arrays and substitute in template
// return content
}
55. Task 3: Add a new comment to a blog post
the whole plugin is cached („USER“)
dynamic user input won‘t outputted instantly
de ne uncached behavior in TypoScript
[globalVar = _POST:tx_blogexample_pi1|newComment = 1]
! plugin.tx_blogexample_pi1 = USER_INT
[globals]
56. Task 3: Add a new comment to a blog post
protected function storeNewComment() {
! $fields = array(
! ! 'post_uid' => $this->piVars['postUid'],
! ! 'post_table' => 'tx_blogexample_post',
! ! 'date' => time(),
! ! 'author' => $this->piVars['author'],
! ! 'email' => $this->piVars['email'],
! ! 'content' => $this->piVars['content'],
! );
! $GLOBALS['TYPO3_DB']->exec_INSERTquery(
! ! 'tx_blogexample_comment', $fields
! );
}
67. 1
2
userFunc
Request
BlogExample
Extbase
TYPO3 Dispatcher
Controller
3
findByTitle('MyBlog')
Repository
Domain Model
Blog
Post
Comment Tag
68. 1
2
userFunc
Request
BlogExample
Extbase
TYPO3 Dispatcher
Controller
3
findByTitle('MyBlog')
Blog
4
Repository
Domain Model
Blog
Post
Comment Tag
69. 1
2
userFunc
Request
BlogExample
Extbase
TYPO3 Dispatcher
Controller
3 assign(Blog)
findByTitle('MyBlog') render() 5
Blog
4 View
Repository
Domain Model
Blog
Post
Comment Tag
70. 1
2
userFunc
Request
BlogExample
Extbase
TYPO3 Dispatcher
HTML
Response Controller
6
3 assign(Blog)
findByTitle('MyBlog') render() 5
Blog
Response
4 View
Repository
Domain Model
Blog
Post
Comment Tag
71. 1
2
userFunc
Request
BlogExample
Extbase
TYPO3 Dispatcher
HTML
Response Controller
6
3 assign(Blog)
findByTitle('MyBlog') render() 5
Blog
Response
4 View
Repository
Domain Model
Blog
Post
Comment Tag
80. /**
* The blog controller for the Blog package
*
* @version $Id:$
* @license http://opensource.org/licenses/gpl-license.php GNU Public License, version 2
*/
class Tx_BlogExample_Controller_BlogController extends Tx_Extbase_MVC_Controller_ActionController {
! /**
! * @var Tx_BlogExample_Domain_Model_BlogRepository
! */
! protected $blogRepository;
! /**
! * Initializes the current action
! *
! * @return void
! */
! public function initializeAction() {
! ! $this->blogRepository = t3lib_div::makeInstance('Tx_BlogExample_Domain_Repository_BlogRepository');
! ! $this->postRepository = t3lib_div::makeInstance('Tx_BlogExample_Domain_Repository_PostRepository');
! ! $this->administratorRepository = t3lib_div::makeInstance('Tx_BlogExample_Domain_Repository_AdministratorRepository');
! }
! /**
! * Index action for this controller. Displays a list of blogs.
! *
! * @return string The rendered view
! */
! public function indexAction() {
! ! $this->view->assign('blogs', $this->blogRepository->findAll());
! }
81. ! }
! /**
! * Index action for this controller. Displays a list of blogs.
! *
! * @return string The rendered view
! */
! public function indexAction() {
! ! $this->view->assign('blogs', $this->blogRepository->findAll());
! }
! /**
! * Displays a form for creating a new blog
! *
! * @param Tx_BlogExample_Domain_Model_Blog $newBlog A fresh blog object taken as a basis for the rendering
! * @return string An HTML form for creating a new blog
! * @dontvalidate $newBlog
! */
! public function newAction(Tx_BlogExample_Domain_Model_Blog $newBlog = NULL) {
! ! $this->view->assign('newBlog', $newBlog);
! ! $this->view->assign('administrators', $this->administratorRepository->findAll());
! }
! /**
! * Creates a new blog
! *
! * @param Tx_BlogExample_Domain_Model_Blog $newBlog A fresh Blog object which has not yet been added to the repository
! * @return void
! */
! public function createAction(Tx_BlogExample_Domain_Model_Blog $newBlog) {
! ! $this->blogRepository->add($newBlog);
! ! $this->pushFlashMessage('Your new blog was created.');
! ! $this->redirect('index');
! }
86. /**
* A repository for Blogs
*/
class Tx_BlogExample_Domain_Repository_BlogRepository extends Tx_Extbase_Persistence_Repository {
!
! /**
! * Remove the blog's posts before removing the blog itself.
! *
! * @return array An array filled with blogs
! */
! public function findAll() {
! ! $blogs = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows(
! ! ! '*',
! ! ! 'tx_blogexample_domain_model_blog',
! ! ! 'sys_language_uid=' . $GLOBALS['TSFE']->sys_language_uid
. $this->cObj->enableFields('tx_blogexample_domain_model_blog'),
! ! ! '',
! ! ! 'date'
! ! ! );
! ! !
! ! return $blogs;
! }
}
87. /**
* A repository for Blogs
*/
class Tx_BlogExample_Domain_Repository_BlogRepository extends Tx_Extbase_Persistence_Repository {
!
}
88. /**
* A repository for Posts
*/
class Tx_BlogExample_Domain_Repository_PostRepository extends Tx_Extbase_Persistence_Repository {
!
! /**
! * Finds posts by the specified blog
! *
! * @param Tx_BlogExample_Domain_Model_Blog $blog The blog the post must refer to
! * @param integer $limit The number of posts to return at max
! * @return array The posts
! */
! public function findByBlog(Tx_BlogExample_Domain_Model_Blog $blog, $limit = 20) {
! ! $query = $this->createQuery();
! ! return $query->matching($query->equals('blog', $blog))
! ! ! ->setOrderings(array('date' => Tx_Extbase_Persistence_QueryInterface::ORDER_DESCENDING))
! ! ! ->setLimit($limit)
! ! ! ->execute();
! }
! /**
! * Finds the previous of the given post
! *
! * @param Tx_BlogExample_Domain_Model_Post $post The reference post
! * @return Tx_BlogExample_Domain_Model_Post
! */
! public function findPrevious(Tx_BlogExample_Domain_Model_Post $post) {
89. ! * @param Tx_BlogExample_Domain_Model_Post $post The reference post
! * @return Tx_BlogExample_Domain_Model_Post
! */
! public function findNext(Tx_BlogExample_Domain_Model_Post $post) {
! ! $query = $this->createQuery();
! ! $posts = $query->matching($query->greaterThan('date', $post->getDate()))
! ! ! ->setOrderings(array('date' => Tx_Extbase_Persistence_QueryInterface::ORDER_DESCENDING))
! ! ! ->setLimit(1)
! ! ! ->execute();
! ! return (count($posts) == 0) ? NULL : current($posts);
! }
! /**
! * Finds most recent posts by the specified blog
! *
! * @param Tx_BlogExample_Domain_Model_Blog $blog The blog the post must refer to
! * @param integer $limit The number of posts to return at max
! * @return array The posts
! */
! public function findRecentByBlog(Tx_BlogExample_Domain_Model_Blog $blog, $limit = 5) {
! ! $query = $this->createQuery();
! ! return $query->matching($query->equals('blog', $blog))
! ! ! ->setOrderings(array('date' => Tx_Extbase_Persistence_QueryInterface::ORDER_DESCENDING))
! ! ! ->setLimit($limit)
! ! ! ->execute();
! }
}
90. Repositories
Encapsulate all data access
SQL is allowed only in the Repository
... but not necessary anymore: use the Query object instead
Magic methods: ndBy*, ndOneBy*
100. Security
All arguments must be registered.
Registration of expected arguments happens through de ning them as method
parameters.
PHPDoc is mandatory as it is used for data type validation
102. Controlle
r
odel
Do main / M
View
Con
fig
ura
tio
n
103. Principles of Domain Driven Design
focus on the domain = activity or business of user
we start with the business logic (PHP classes)
we don't care about the database backend / persistence layer
objects represent things in the real world, with their attributes and behavior
ubiquitous language
building blocks
Entity
Value Objects
Repositories
105. What's next
New Kickstarter
currently ongoing project by the core development team
will be released shortly after 4.3
Domain-Driven Design - Don't think in databases, think in Domain Models!
Support for BE-Modules
experimental by now
AJAX-Dispatcher
Dependency Injection
PDO Storage Backend
113. Bastian Waidelich
Sebastian Kurfürst
Than k You Steffen Kamper
and the TYPO3 V5 Team for all the inspiration
and the beautiful code
Ingmar Schlecht
Christopher Hlubek
Xavier Perseguers
114. Resources and links
Project web site: http://forge.typo3.org/projects/show/typo3v4-mvc
SVN: https://svn.typo3.org/TYPO3v4/CoreProjects/MVC/
Newslist typo3.projects.typo3v4mvc@lists.net elders.de
First stable release with TYPO3 4.3 alpha3: http://typo3.org/download/packages/