Get into the FLOW with Extbase

Loading...

Flash Player 9 (or above) is needed to view presentations.
We have detected that you do not have it on your computer. To install it, go here.

0 comments

Post a comment

    Post a comment
    Embed Video
    Edit your comment Cancel

    3 Favorites, 2 Groups & 2 Events

    Get into the FLOW with Extbase - Presentation Transcript

    1. Get into the FLOW with Extbase http://www.sxc.hu/photo/768249
    2. Who is this?
    3. Dipl.-Ing. Mechanical Engineering
    4. infected with TYPO3 in 2OO1
    5. Tübingen
    6. 6O% selfemployed 6O% father
    7. 8O% ---- selfemployed 6O% 6O% father
    8. 5 years: Fraunhofer- Gesellschaft German Aerospace Center
    9. 5 years: high school teacher
    10. What is Extbase all about?
    11. 1997
    12. v4 2OO9
    13. v4
    14. v4 2OO6
    15. v5 v4
    16. v5 v4
    17. v5 v4
    18. Extbase v5 v4
    19. v5 v4
    20. What is Extbase all about?
    21. Extbase FLOW 3
    22. What is Extbase all about?
    23. Extbase
    24. OOP A ggregate DDD Extbase V iew Entity H elp er M VC VfB R epository
    25. Extbase Value
    26. 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)
    27. tp://commons.wikimedia.org/wiki/File:Z%C3%BCrich_-_Seefeld_-_Heureka_IMG_1757.JPG
    28. tx_ttnews 3397 tx_pbsurvey_pi1 253O tx_ttproducts_pi1 1O9O tx_mmforum_pi1 6126 tx_veguestbook_pi1 1156 tp://commons.wikimedia.org/wiki/File:Z%C3%BCrich_-_Seefeld_-_Heureka_IMG_1757.JPG
    29. ! /** ! * Main news function: calls the init_news() function and decides by the given CODEs which of the ! * functions to display news should by called. ! * ! * @param! string! ! $content : function output is added to this ! * @param! array! ! $conf : configuration array ! * @return!string! ! $content: complete content generated by the tt_news plugin ! */ ! function main_news($content, $conf) { ! ! $this->local_cObj = t3lib_div::makeInstance('tslib_cObj'); // Local cObj. ! ! $this->init($conf); ! ! if ($this->conf['displayCurrentRecord']) { ! ! ! $this->config['code'] = $this->conf['defaultCode']?trim($this->conf['defaultCode']):'SINGLE'; ! ! ! $this->tt_news_uid = $this->cObj->data['uid']; ! ! } ! ! // get codes and decide which function is used to process the content ! ! $codes = t3lib_div::trimExplode(',', $this->config['code']?$this->config['code']:$this->conf['defaultCode'], 1); ! ! if (!count($codes)) { // no code at all ! ! ! $codes = array(); ! ! ! $noCode = true; ! ! } ! ! while (list(, $theCode) = each($codes)) { ! ! ! $theCode = (string)strtoupper(trim($theCode)); ! ! ! $this->theCode = $theCode; ! ! ! switch ($theCode) { ! ! ! ! case 'SINGLE': ! ! ! ! $content .= $this->displaySingle(); ! ! ! ! break; ! ! ! ! case 'VERSION_PREVIEW': ! ! ! ! $content .= $this->displayVersionPreview(); ! ! ! ! break; ! ! ! ! case 'LATEST': ! ! ! ! case 'LIST': ! ! ! ! case 'SEARCH': ! ! ! ! case 'XML': ! ! ! ! $content .= $this->displayList(); ! ! ! ! break; ! ! ! ! case 'AMENU': ! ! ! ! $content .= $this->newsArchiveMenu(); ! ! ! ! break; ! ! ! ! case 'CATMENU': ! ! ! ! $content .= $this->displayCatMenu(); ! ! ! ! break; ! ! ! ! default:
    30. ! /** ! * Displays the "single view" of a news article. Is also used when displaying single news records with the "insert records" content element. ! * ! * @return!string! ! html-code for the "single view" ! */ ! function displaySingle() { ! ! $singleWhere = 'tt_news.uid=' . intval($this->tt_news_uid); ! ! $singleWhere .= ' AND type NOT IN(1,2)' . $this->enableFields; // only real news -> type=0 ! ! $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery( ! ! ! '*', ! ! ! 'tt_news', ! ! ! $singleWhere); ! ! $row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res); ! ! // get the translated record if the content language is not the default language ! ! if ($GLOBALS['TSFE']->sys_language_content) { ! ! ! $OLmode = ($this->sys_language_mode == 'strict'?'hideNonTranslated':''); ! ! ! $row = $GLOBALS['TSFE']->sys_page->getRecordOverlay('tt_news', $row, $GLOBALS['TSFE']->sys_language_content, $OLmode); ! ! } ! ! if ($this->versioningEnabled) { ! ! ! // get workspaces Overlay ! ! ! $GLOBALS['TSFE']->sys_page->versionOL('tt_news',$row); ! ! ! // fix pid for record from workspace ! ! ! $GLOBALS['TSFE']->sys_page->fixVersioningPid('tt_news',$row); ! ! } ! ! $GLOBALS['TSFE']->displayedNews[]=$row['uid']; ! ! if (is_array($row) && ($row['pid'] > 0 || $this->vPrev)) { // never display versions of a news record (having pid=-1) for normal website users ! ! ! ! // Get the subpart code ! ! ! if ($this->conf['displayCurrentRecord']) { ! ! ! ! $item = trim($this->getNewsSubpart($this->templateCode, $this->spMarker('###TEMPLATE_SINGLE_RECORDINSERT###'), $row)); ! ! ! } ! ! ! if (!$item) { ! ! ! ! $item = $this->getNewsSubpart($this->templateCode, $this->spMarker('###TEMPLATE_SINGLE###'), $row); ! ! ! } ! ! ! ! // reset marker array ! ! ! $wrappedSubpartArray = array(); ! ! ! ! // build the backToList link ! ! ! if ($this->conf['useHRDates']) { ! ! ! ! $pointerName = 'pointer'; ! ! ! ! $wrappedSubpartArray['###LINK_ITEM###'] = explode('|', $this->pi_linkTP_keepPIvars('|', array( ! ! ! ! ! 'tt_news' => null, ! ! ! ! ! 'backPid' => null, ! ! ! ! ! $this->config['singleViewPointerName'] => null, ! ! ! ! ! 'pS' => null, ! ! ! ! ! 'pL' => null), $this->allowCaching, ($this->conf['dontUseBackPid']?1:0), $this->config['backPid']));
    31. 'pointer'; ! ! ! ! $wrappedSubpartArray['# ##LINK_ITEM###'] = explode('|', $this- >pi_linkTP_keepPIvars(' |', array( ! ! ! ! ! 'tt_news' => null, ! ! ! ! ! 'backPid' => null, ! ! ! ! ! $this- >config['singleViewPoin terName'] => null, ! ! ! ! ! 'pS' => null, ! ! ! ! ! 'pL' => null), $this- >allowCaching, ($this- >conf['dontUseBackPid'] ?1:0), $this- >config['backPid'])); ! ! ! } else { ! ! ! ! $wrappedSubpartArray['# ##LINK_ITEM###'] = explode('|', $this- >pi_linkTP_keepPIvars(' |', array( ! ! ! ! ! 'tt_news' => null, ! ! ! ! ! 'backPid' => null, ! ! ! ! ! $this- >config['singleViewPoin terName'] => null), $this->allowCaching, ($this- >conf['dontUseBackPid'] ?1:0), $this- >config['backPid'])); ! ! ! } ! ! ! ! // set the title of the single view page to the title of the news record ! ! ! if ($this- >conf['substitutePageti tle']) { ! ! ! ! $GLOBALS['TSFE']- >page['title'] = $row['title']; ! ! ! ! // set pagetitle for indexed search to news title ! ! ! ! $GLOBALS['TSFE']- >indexedDocTitle = $row['title']; ! ! ! } ! ! ! if ($this- >conf['displaySingle.'] ['catOrderBy']) { ! ! ! ! $this- >config['catOrderBy'] = $this- >conf['displaySingle.'] ['catOrderBy']; ! ! ! } ! ! ! $markerArray = $this- >getItemMarkerArray($ro w, 'displaySingle'); ! ! ! // Substitute ! ! ! $content = $this->cObj- >substituteMarkerArrayC ached($item, $markerArray, array(), $wrappedSubpartArray); ! ! } elseif ($this- >sys_language_mode == 'strict' && $this- >tt_news_uid && $GLOBALS['TSFE']- >sys_language_content) { // not existing translation ! ! ! $noTranslMsg = $this- >local_cObj- >stdWrap($this- >pi_getLL('noTranslMsg' ), $this- >conf['noNewsIdMsg_stdW rap.']); ! ! ! $content = $noTranslMsg; ! ! } elseif ($row['pid'] < 0) { // a non-public version of a record was requested ! ! ! $nonPlublicVersion = $this->local_cObj- >stdWrap($this- >pi_getLL('nonPlublicVe rsionMsg'), $this- >conf['nonPlublicVersio nMsg_stdWrap.']); ! ! ! $content = $nonPlublicVersion; ! ! } else { // if singleview is shown with no tt_news uid given from GETvars (&tx_ttnews[tt_news]=) an error message is displayed. ! ! ! $noNewsIdMsg = $this- >local_cObj- >stdWrap($this- >pi_getLL('noNewsIdMsg' ), $this-
    32. control flow business logic CRUD data render output other , eg. config
    33. control flow business logic aggregate CRUD data render output other , eg. config
    34. control flow business logic generalize CRUD data render output other , eg. config
    35. partition
    36. Extbase use & Fluid
    37. control flow business logic CRUD data render output other , eg. config
    38. Controller Domain Model Domain Repository View other , eg. config
    39. 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
    40. 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
    41. 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
    42. TYPO3
    43. tslib_piBase tx_blog 1 userFunc TYPO3 tx_blog_pi
    44. tslib_piBase tx_blog 1 userFunc 2 exec_SELECTgetRows TYPO3 tx_blog_pi Database
    45. tslib_piBase tx_blog 1 userFunc 2 exec_SELECTgetRows TYPO3 tx_blog_pi rows as Database array 3
    46. tslib_piBase tx_blog 1 userFunc 2 exec_SELECTgetRows TYPO3 tx_blog_pi HTML rows as Database 4 array 3
    47. Control ow public function main($content, $conf) { ! $this->conf = $conf; ! $this->pi_setPiVarDefaults(); ! $this->pi_loadLL(); ! if ($this->piVars['postUid']) { ! ! if ($this->piVars['newComment']) { ! ! ! $this->storeNewComment(); ! ! } ! ! $content = $this->renderPost(); ! } elseif ($this->piVars['blogUid']) { ! ! $content = $this->renderBlog(); ! } else { ! ! $content = $this->renderListOfBlogs(); ! } ! return $this->pi_wrapInBaseClass($content); }
    48. Task 1: Output a listing of blogs protected function renderListOfBlogs() { ! $blogs = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows( ! ! '*', ! ! 'tx_blogexample_blog', ! ! 'sys_language_uid=' . $GLOBALS['TSFE']->sys_language_uid . $this->cObj->enableFields('tx_blogexample_blog'), ! ! '', ! ! 'date' ! ! ); ! $template = $this->cObj->fileResource($this->conf['template']); ! $blogElementSubpart = $this->cObj->getSubpart($template, '###SUBPART_BLOGELEMENT###');
    49. Task 1: Output a listing of blogs ! foreach ($blogs as $blog) { ! ! $linkParameters = array('blogUid' => $blog['uid']); ! ! $markers = array( ! ! ! '###BLOG_NAME###' => $blog['name'], ! ! ! '###BLOG_LOGO###' => $this->cImage('uploads/tx_blog/' . $blog['logo']), ! ! ! '###BLOG_DESCRIPTION###' => $this->pi_RTEcssText($blog['description']), ! ! ! '###BLOG_MORELINK###' => $this->pi_linkTP('show blog', $linkParameters, true), ! ! ); ! ! $blogElements.= $this->cObj->substituteMarkerArray($blogElementSubpart, $markers); ! } ! return $content; }
    50. 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 -->
    51. 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 }
    52. 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]
    53. 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 ! ); }
    54. Security: SQL injections 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' ! ); [...]
    55. Security: SQL injections 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' ! ); [...] http://www.example.com/index.php&id=99&postUid=1
    56. Security: SQL injections 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' ! ); [...] http://www.example.com/index.php&id=99&postUid=1 SELECT * FROM tx_blog_comment WHERE post_uid=1;
    57. Security: SQL injections 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' ! ); [...] http://www.example.com/index.php&id=99&postUid=1; INSERT INTO be_users SET ...; SELECT * FROM tx_blog_comment WHERE 1=1 SELECT * FROM tx_blog_comment WHERE post_uid=1; INSERT INTO be_users SET ...; SELECT * FROM tx_blog_comment WHERE 1=1 AND post_table="tx_blogexample_post"
    58. Security: SQL injections 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' ! ); [...] http://www.example.com/index.php&id=99&postUid=1; INSERT INTO be_users SET ...; SELECT * FROM tx_blog_comment WHERE 1=1 SELECT * FROM tx_blog_comment WHERE post_uid=1; INSERT INTO be_users SET ...; SELECT * FROM tx_blog_comment WHERE 1=1 AND post_table="tx_blogexample_post"
    59. Security: SQL injections 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=' . intval($this->piVars['postUid']) . ' AND post_table="tx_blogexample_post"' . $this->cObj->enableFields('tx_blogexample_comment'), ! ! '', ! ! 'date DESC' ! ); [...] http://www.example.com/index.php&id=99&postUid=1; INSERT INTO be_users SET ...; SELECT * FROM tx_blog_comment WHERE 1=1 SELECT * FROM tx_blog_comment WHERE post_uid=1; INSERT INTO be_users SET ...; SELECT * FROM tx_blog_comment WHERE 1=1 AND post_table="tx_blogexample_post"
    60. http://www.sxc.hu/photo/516864/ Extension building with Extbase
    61. TYPO3
    62. 1 userFunc Extbase TYPO3 Dispatcher
    63. 1 2 userFunc Request BlogExample Extbase TYPO3 Dispatcher Controller
    64. 1 2 userFunc Request BlogExample Extbase TYPO3 Dispatcher Controller 3 findByTitle('MyBlog') Repository Domain Model Blog Post Comment Tag
    65. 1 2 userFunc Request BlogExample Extbase TYPO3 Dispatcher Controller 3 findByTitle('MyBlog') Blog 4 Repository Domain Model Blog Post Comment Tag
    66. 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
    67. 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
    68. 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
    69. Blog Post Comment Tag
    70. Model
    71. /** * A blog * * @version $Id:$ * @copyright Copyright belongs to the respective authors * @license http://opensource.org/licenses/gpl-license.php GNU Public License, version 2 * @scope prototype * @entity */ class Tx_BlogExample_Domain_Model_Blog extends Tx_Extbase_DomainObject_AbstractEntity { ! /** ! * The blog's title. ! * ! * @var string ! * @validate Text, StringLength(minimum = 1, maximum = 80) ! * @identity ! */ ! protected $title = ''; ! /** ! * A short description of the blog ! * ! * @var string ! * @validate Text, StringLength(maximum = 150) ! */ ! protected $description = '';
    72. ! } ! /** ! * Sets this blog's title ! * ! * @param string $title The blog's title ! * @return void ! */ ! public function setTitle($title) { ! ! $this->title = $title; ! } ! /** ! * Returns the blog's title ! * ! * @return string The blog's title ! */ ! public function getTitle() { ! ! return $this->title; ! } ! /** ! * Sets the description for the blog ! * ! * @param string $description ! * @return void ! */ ! public function setDescription($description) { ! ! $this->description = $description;
    73. ! * @return Tx_Extbase_Persistence_ObjectStorage ! */ ! public function getPosts() { ! ! return $this->posts; ! } ! /** ! * Sets the administrator value ! * ! * @param Tx_BlogExample_Domain_Model_Administrator $administrator The Administrator of this Blog ! * @return void ! */ ! public function setAdministrator(Tx_BlogExample_Domain_Model_Administrator $administrator) { ! ! $this->administrator = $administrator; ! } ! /** ! * Returns the administrator value ! * ! * @return Tx_BlogExample_Domain_Model_Administrator ! */ ! public function getAdministrator() { ! ! return $this->administrator; ! } }
    74. /** * A blog post comment * * @package Blog * @subpackage Domain * @version $Id:$ * @copyright Copyright belongs to the respective authors * @license http://opensource.org/licenses/gpl-license.php GNU Public License, version 2 * @scope prototype * @entity */ class Tx_BlogExample_Domain_Model_Comment extends Tx_Extbase_DomainObject_AbstractEntity { ! /** ! * @var DateTime ! */ ! protected $date; ! /** ! * @var string ! * @validate Text, StringLength(minimum = 3, maximum = 80) ! */ ! protected $author; ! /** ! * @var string ! * @validate EmailAddress
    75. ! * @param string $content ! * @return void ! */ ! public function setContent($content) { ! ! $this->content = $content; ! } ! /** ! * Getter for content ! * ! * @return string ! */ ! public function getContent() { ! ! return $this->content; ! } ! /** ! * Returns this comment as a formatted string ! * ! * @return string ! */ ! public function __toString() { ! ! return $this->author . ' (' . $this->email . ') said on ' . $this->date->format('Y-m-d') . ':' . chr(10) ! ! ! $this->content . chr(10); ! } }
    76. http://www.sxc.hu/photo/444174/ and... action
    77. /** * 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()); ! }
    78. ! } ! /** ! * 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'); ! }
    79. How could you fetch a blog?
    80. How could you fetch a book?
    81. Model Blog Post Comment Tag
    82. Model BlogRepository Blog Post Comment Tag
    83. /** * 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; ! } }
    84. /** * A repository for Blogs */ class Tx_BlogExample_Domain_Repository_BlogRepository extends Tx_Extbase_Persistence_Repository { ! }
    85. /** * 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) {
    86. ! * @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(); ! } }
    87. 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*
    88. Blog Post Comment Tag
    89. Aggregate Blog Post Comment Tag
    90. Blog Entity Post Comment Tag
    91. Blog Entity Post Value Object Comment Tag
    92. Aggregate Root Blog Entity Post Value Object Comment Tag
    93. Aggregate getLatestComment() Root Blog Post Comment Tag
    94. Aggregate getLatestComment() Root Blog Post Comment Tag
    95. Aggregate getLatestComment() Root Blog Post Comment Tag
    96. <h1 class="csc-firstHeader">Welcome to {blog.title}</h1> <p class="bodytext">{blog.description}</p> <div class="tx-blogexample-list-container"> ! <f:if condition="{blog.posts}"> ! ! <f:then> ! ! <p class="bodytext"><f:translate key="label_recent_posts">Below are the most recent posts:</f:translate></p> ! ! ! <ul> ! ! ! ! <f:for each="{blog.posts}" as="post"> ! ! ! ! ! <li> ! ! ! ! ! ! <h3> ! ! ! ! ! ! ! <f:format.date>{post.date}</f:format.date> ! ! ! ! ! ! ! <f:link.action action="show" controller="Post" arguments="{post: post, blog: post.blog}">{post.title}</f:link.action> ! ! ! ! ! ! </h3> ! ! ! ! ! ! <p class="bodytext"><f:format.crop maxCharacters="100">{post.content}</f:format.crop></p> ! ! ! ! ! ! <p> ! ! ! ! ! ! ! By: {post.author.fullName}<br /> ! ! ! ! ! ! ! Tags: <f:for each="{post.tags}" as="tag">[{tag.name}]&nbsp;</f:for><br /> ! ! ! ! ! ! ! <f:link.action controller="Post" action="show" arguments="{post : post}"> <f:translate key="read_more">read more &gt;&gt;</f:translate> </f:link.action><br /> ! ! ! ! ! ! ! <f:link.action controller="Post" action="edit" arguments="{post : post, blog : blog}"> Edit </f:link.action>&nbsp; <f:link.action controller="Post" action="delete" arguments="{post : post, blog : blog}"> Delete </f:link.action> ! ! ! ! ! ! </p> ! ! ! ! ! </li> ! ! ! ! </f:for> ! ! ! </ul> ! ! </f:then> ! ! <f:else> ! ! ! <p>This blog currently doesn't contain any posts.</p> ! ! </f:else> ! </f:if> ! <p><f:link.action action="new" controller="Post" arguments="{blog : blog}">Create a new Post</f:link.action></p> </div>
    97. 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
    98. */ class Tx_BlogExample_Domain_Model_Comment extends Tx_Extbase_DomainObject_AbstractEntity { ! /** ! * @var DateTime ! */ ! protected $date; ! /** ! * @var string ! * @validate Text, StringLength(minimum = 3, maximum = 80) ! */ ! protected $author; ! /** ! * @var string ! * @validate EmailAddress ! */ ! protected $email; ! /** ! * @var string ! * @validate Text, NotEmpty ! */ ! protected $content; ! ! ! /** ! * Constructs this post
    99. Controlle r odel Do main / M View Con fig ura tio n
    100. 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
    101. What's next?
    102. 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
    103. - Modern architecture
    104. Modular reusable Greatly reusable components components
    105. Easy and clean API
    106. Easy testable
    107. Get more implemented in less time
    108. You will get addicted
    109. 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
    110. 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/
    SlideShare Zeitgeist 2009

    + jocraujocrau Nominate

    custom

    2649 views, 3 favs, 3 embeds more stats

    A key feature of TYPO3 today is its extendability a more

    More info about this document

    © All Rights Reserved

    Go to text version

    • Total Views 2649
      • 1927 on SlideShare
      • 722 from embeds
    • Comments 0
    • Favorites 3
    • Downloads 35
    Most viewed embeds
    • 714 views on http://flow3.typo3.org
    • 7 views on http://www.bertrandkeller.info
    • 1 views on http://csit.uniud.it

    more

    All embeds
    • 714 views on http://flow3.typo3.org
    • 7 views on http://www.bertrandkeller.info
    • 1 views on http://csit.uniud.it

    less

    Flagged as inappropriate Flag as inappropriate
    Flag as inappropriate

    Select your reason for flagging this presentation as inappropriate. If needed, use the feedback form to let us know more details.

    Cancel
    File a copyright complaint
    Having problems? Go to our helpdesk?

    Categories

    Groups / Events