Technology

Get into the FLOW with Extbase

Description
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.
Categories
Published
of 114
All materials on our website are shared by users. If you have any questions about copyright issues, please report us to resolve them. We are always happy to assist you.
Related Documents
Share
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 Con
  • Search
    Related Search
    We Need Your Support
    Thank you for visiting our website and your interest in our free products and services. We are nonprofit website to share and download documents. To the running of this website, we need your help to support us.

    Thanks to everyone for your continued support.

    No, Thanks