Best practices for Joomla extensions developers - Joomla Day 2013
Upcoming SlideShare
Loading in...5
×
 

Best practices for Joomla extensions developers - Joomla Day 2013

on

  • 1,741 views

Do you write extensions for Joomla? Do it the *right* way. You will save time and make friends amongst fellow developers (because they won't hate you when they have to read your code). ...

Do you write extensions for Joomla? Do it the *right* way. You will save time and make friends amongst fellow developers (because they won't hate you when they have to read your code).

In this session we will share standards and suggestions about the best practices to adopt when you code your extensions.

Based on a true story. Our own.

Statistics

Views

Total Views
1,741
Views on SlideShare
1,737
Embed Views
4

Actions

Likes
0
Downloads
23
Comments
0

1 Embed 4

https://twitter.com 4

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

Best practices for Joomla extensions developers - Joomla Day 2013 Best practices for Joomla extensions developers - Joomla Day 2013 Presentation Transcript

  • Joomla Extensions Development Best Practices Francesco Abeni GiBiLogic extensions.gibilogic.com
  • Francesco Abeni for GiBiLogic http://extensions.gibilogic.com - info@gibilogic.com ¡Hola, mundo!
  • Shameless self-promotion Francesco Abeni for GiBiLogic http://extensions.gibilogic.com - info@gibilogic.com Francesco Abeni sPrintAddCSSPizzaBox
  • About this speech Francesco Abeni for GiBiLogic http://extensions.gibilogic.com - info@gibilogic.com The quality of code in the Joomlasphere
  • Today roadmap: Francesco Abeni for GiBiLogic http://extensions.gibilogic.com - info@gibilogic.com ● Tools ● Files and folders ● Reuse software ● MVC ● Other tips ● Conclusions Feedback please!
  • No dev course Francesco Abeni for GiBiLogic http://extensions.gibilogic.com - info@gibilogic.com
  • Our target Francesco Abeni for GiBiLogic http://extensions.gibilogic.com - info@gibilogic.com Good = not bad Excellent = above the average Good is enough for today
  • Francesco Abeni for GiBiLogic http://extensions.gibilogic.com - info@gibilogic.com
  • IDE basic features Francesco Abeni for GiBiLogic http://extensions.gibilogic.com - info@gibilogic.com ● multiple files edit ● syntax highlighting ● index for methods and variables ● autocompletion ● autoformatting ● compiler ● versioning / unit testing / phpdoc / ...
  • Some IDEs Francesco Abeni for GiBiLogic http://extensions.gibilogic.com - info@gibilogic.com
  • Versioning Francesco Abeni for GiBiLogic http://extensions.gibilogic.com - info@gibilogic.com http://git-scm.com/book
  • Standard Francesco Abeni for GiBiLogic http://extensions.gibilogic.com - info@gibilogic.com
  • Francesco Abeni for GiBiLogic http://extensions.gibilogic.com - info@gibilogic.com
  • Everything in its right place Francesco Abeni for GiBiLogic http://extensions.gibilogic.com - info@gibilogic.com Backend ● administrator ○ components ■ com_componentname ● componentname.xml ● componentname.php ● controllers ● models ● views
  • Everything in its right place Francesco Abeni for GiBiLogic http://extensions.gibilogic.com - info@gibilogic.com Backend ● administrator ○ components ■ com_componentname ● ... ● config.xml ● install.php ● sql ● tables ● helpers
  • ● media ○ com_componentname ■ css ■ js ■ img ● components ○ com_componentname ■ componentname.php ■ controllers ■ models ■ views Everything in its right place Francesco Abeni for GiBiLogic http://extensions.gibilogic.com - info@gibilogic.com Frontend ● images ○ com_componentname
  • Francesco Abeni for GiBiLogic http://extensions.gibilogic.com - info@gibilogic.com
  • CSS / JS Francesco Abeni for GiBiLogic http://extensions.gibilogic.com - info@gibilogic.com Use existing libraries JavaScript ● MooTools (since Joomla 1.5) ● JQuery (since Joomla 2.5) CSS + JavaScript ● Bootstrap (since Joomla 3.x) P.S. got conflicts? Use JQueryEasy plugin.
  • CSS out of the door Francesco Abeni for GiBiLogic http://extensions.gibilogic.com - info@gibilogic.com Don't: <div>...</div> <br style="clear: both"> <div style="height: 200px">...</div> Do: <link rel=”stylesheet” href=”/media/componentname/styles.css”> ... <div class=”clearfix”>...</div> <div class="fixedheight">...</div> .clearfix { … } .fixedheight { height: 200px }
  • JS out of the door Francesco Abeni for GiBiLogic http://extensions.gibilogic.com - info@gibilogic.com <button id="submit" type=submit" value="ClickMe!" onclick="validateForm()" /> Do: <script src=”/media/componentname/js/script.js”> <button id="submit" type=submit" value="ClickMe!"/> document.addEvent('load',function(){ $('submit').addEvent('click',function(){ validateForm(); }); }); Don't:
  • Francesco Abeni for GiBiLogic http://extensions.gibilogic.com - info@gibilogic.com
  • Joomla framework Francesco Abeni for GiBiLogic http://extensions.gibilogic.com - info@gibilogic.com ● JApplication ● JDatabase ● JUser ● JSession ● JDocument ● JHTML ● JForm ● JConfig ● JUri ● JFile ● JFolder ● JLog ● JFilterInput ● JError and JException ● JDate ● JUtilities ● JVersion ● JLayout
  • PHP functions and classes Francesco Abeni for GiBiLogic http://extensions.gibilogic.com - info@gibilogic.com ● pcre ● trim ● usort ● array_map ● array_unique ● json_encode ● json_decode ● microtime(true) ● glob ● curl ● DateTime ● Standard PHP Library ● Exception ● SimpleXML ● TCPDF ● PHPMailer
  • PHP version Francesco Abeni for GiBiLogic http://extensions.gibilogic.com - info@gibilogic.com ● 16. Dec 2010: PHP 5.2 end of life ● 11. Jul 2013: PHP 5.3 end of life ● 01. Mar 2012: PHP 5.4 released ● 20 Jun 2013: PHP 5.5 released ● PHP 5.4 is 40% faster than PHP 5.2
  • Francesco Abeni for GiBiLogic http://extensions.gibilogic.com - info@gibilogic.com
  • Real objects Francesco Abeni for GiBiLogic http://extensions.gibilogic.com - info@gibilogic.com book writer library
  • Bad design sample Francesco Abeni for GiBiLogic http://extensions.gibilogic.com - info@gibilogic.com ● views/search ● views/editbook ● views/book ● views/books ● views/booksauthor ● views/topten Don't:
  • The controller Francesco Abeni for GiBiLogic http://extensions.gibilogic.com - info@gibilogic.com ● Filters input ● Decides what to do ● Checks access permissions ● Executes task(s) ● Optionally, calls the view
  • The model Francesco Abeni for GiBiLogic http://extensions.gibilogic.com - info@gibilogic.com ● Retrieves object data ● Validates object data ● Gets object data ● Saves object data ● Hates to be mistaken as an helper
  • The view Francesco Abeni for GiBiLogic http://extensions.gibilogic.com - info@gibilogic.com ● Ask the model for data ● Display object(s) ● Uses layouts!
  • Francesco Abeni for GiBiLogic http://extensions.gibilogic.com - info@gibilogic.com
  • Header comment Francesco Abeni for GiBiLogic http://extensions.gibilogic.com - info@gibilogic.com <?php /** * @version mybooks.php 2013-08-10 15:23:00Z zanardi * @package GiBi MyBooks * @author GiBiLogic * @authorUrl http://www.gibilogic.com * @authorEmail info@gibilogic.com * @copyright Copyright (C) 2013 GiBiLogic. All rights reserved. * @license GNU/GPL v2 or later * @description Backend entry point */
  • Entry point Francesco Abeni for GiBiLogic http://extensions.gibilogic.com - info@gibilogic.com <?php ... defined('_JEXEC') or die(); jimport('joomla.application.component.controller'); $view = JFactory::getApplication()->input->get('view', 'book'); $task = JFactory::getApplication()->input->get('task', 'index'); JFactory::getApplication()->input->set('task', "$view.$task"); $controller = JController::getInstance('MyBooks'); $controller->execute($task); $controller->redirect();
  • Controller - part 1 Francesco Abeni for GiBiLogic http://extensions.gibilogic.com - info@gibilogic.com <?php ... defined('_JEXEC') or die('The way is shut!'); jimport('joomla.application.component.controlleradmin'); /** * MyBooksControllerBook class. * * @see JControllerAdmin */ class MyBooksControllerBook extends JControllerAdmin { /** * Controller's view. * * @var JView */ private $view; ...
  • Controller - part 2 Francesco Abeni for GiBiLogic http://extensions.gibilogic.com - info@gibilogic.com <?php ... /** * Class constructor. * * @param type $config */ public function __construct($config = array()) { parent::__construct($config); $this->model = $this->getModel(); $this->view = $this->getView(JFactory::getApplication()->input->get('view', 'book'), 'html'); $this->view->setModel($this->model, true); $this->view->setModel($this->getModel('Author', 'MyBooksModel'), false); $this->view->setModel($this->getModel('Editor', 'MyBooksModel'), false); } ...
  • Controller - part 3 Francesco Abeni for GiBiLogic http://extensions.gibilogic.com - info@gibilogic.com <?php ... public function index() { $this->view->setLayout('index') $this->view->display(); } public function create() { $this->view->setLayout('create'); $this->view->display(); } public function save() { $data = JFactory::getApplication()->input->get('jform', null); if (!$data || !$this->model->validate($data)) { $msg = 'Invalid data!'; $type = 'error'; $this->setRedirect('index.php?option=com_mybooks&view=book&task=create', $msg, $type); return false; }
  • Model - part 1 Francesco Abeni for GiBiLogic http://extensions.gibilogic.com - info@gibilogic.com <?php ... defined('_JEXEC') or die('The way is shut!'); jimport('joomla.application.component.model'); jimport('joomla.html.pagination'); class MybooksModelBook extends JModel { private $table = '#__mybooks_book'; public function __construct($config = array()) { parent::__construct($config); $app = JFactory::getApplication(); $limit = $app->getUserStateFromRequest('global.list.limit', 'limit', $app- >getCfg('list_limit'), 'int'); $limitstart = $app->input->get('limitstart', 0, '', 'int'); $this->setState('limit', $limit); $this->setState('limitstart', $limitstart); $this->setState('author_id', $app->getUserStateFromRequest('com_mybooks.filters. author_id', 'author_id', 0, 'int')); }
  • Model - part 2 Francesco Abeni for GiBiLogic http://extensions.gibilogic.com - info@gibilogic.com <?php ... public function getList() { return $this->_getList( $this->buildQuery(), $this->getState('limitstart'), $this->getState('limit') ); } public function getLast() { $query = $this->_db->getQuery(true); $query->select('*')->from($this->table)->orderby('created_at DESC'); $this->_db->setQuery($query,0,1); $results = $this->_db->loadObjectList('id'); return $results ? $results : array(); } public function getLastByAuthor($author_id) { $query = $this->_db->getQuery(true); $query->select('*')->from($this->table)->where(“author_id = '$author_id'”)- >orderby('created_at DESC'); $this->_db->setQuery($query,0,1); return $this->_db->loadObject(); }
  • Model - part 3 Francesco Abeni for GiBiLogic http://extensions.gibilogic.com - info@gibilogic.com <?php ... public function create($data) { if (!$data) { return 0; } $data['created_at'] = date('Y-m-d H:i:s'); $query = $this->_db->getQuery(true); $query->insert($this->table)->columns(array_keys($data))->values(sprintf("'%s'", implode("','", array_values($data)))); $this->_db->setQuery($query); return false === $this->_db->execute() ? 0 : $this->_db->insertid(); } ...
  • Model - part 4 Francesco Abeni for GiBiLogic http://extensions.gibilogic.com - info@gibilogic.com <?php ... public function delete($ids) { $query = $this->_db->getQuery(true); $query->delete()->from($this->table)->where('id IN '.implode(',', $ids)); return false !== $this->_db->execute(); } public function getPagination(){ return new JPagination( $this->_getListCount($this->buildQuery()), $this->getState('limitstart'), $this->getState('limit') ); } private function buildQuery(){ $where = $this->buildWhere(); $query = $this->_db->getQuery(true); return $query->select('*')->from($this->table)->where($where)->orderby ('created_at DESC'); } ...
  • View - part 1 Francesco Abeni for GiBiLogic http://extensions.gibilogic.com - info@gibilogic.com <?php ... defined('_JEXEC') or die('The way is shut!'); jimport('joomla.application.component.view'); class MyBooksViewBook extends JView { public function display($tpl = null) { $this->pagination = $this->getModel()->getPagination(); $this->filter_author_id = $this->getModel()->getState('author_id'); $this->books = $this->getModel()->findAll(); $this->authors = $this->getModel('Authors')->getList(); $this->editors = $this->getModel('Editors')->getList(); $this->addToolbar($tpl); parent::display($tpl); }
  • View - part 2 Francesco Abeni for GiBiLogic http://extensions.gibilogic.com - info@gibilogic.com <?php ... protected function addToolbar($tpl){ $methodName = 'addToolBar' . ucfirst(!$tpl ? 'default' : $tpl); $this->{$methodName}(); } private function addToolBarDefault(){ JToolBarHelper::title(JText::_('COM_MYBOOKS') . ': ' . JText::_ ('COM_MYBOOKS_BOOK_LIST')); JToolBarHelper::addNew('create'); JToolBarHelper::preferences('com_mybooks'); JToolBarHelper::divider(); JToolBarHelper::deleteList('COM_MYBOOKS_BOOK_LIST_DELETE_CONFIRM', 'delete'); } private function addToolBarCreate(){ JToolBarHelper::title(JText::_('COM_MYBOOKS') . ': ' . JText::_ ('COM_MYBOOKS_BOOK_NEW')); JToolBarHelper::apply('save'); JToolBarHelper::divider(); JToolBarHelper::back('JTOOLBAR_BACK', 'index.php?option=com_mybooks'); } }
  • Francesco Abeni for GiBiLogic http://extensions.gibilogic.com - info@gibilogic.com
  • Helpers Francesco Abeni for GiBiLogic http://extensions.gibilogic.com - info@gibilogic.com Common (usually static) functions not related to a specific object ● Get date / time / external info ● Format date and numbers ● Build title and/or other HTML snippets ● Log/error management ● Handle CURL connections
  • Table classes Francesco Abeni for GiBiLogic http://extensions.gibilogic.com - info@gibilogic.com Interface to and from the database Active Record pattern ● Define table name and unique id ● load, store, delete, and so on
  • Table classes - sample code Francesco Abeni for GiBiLogic http://extensions.gibilogic.com - info@gibilogic.com <?php class TableBook extends JTable { public function __construct(&$db) { parent::__construct(‘#__books’, ‘id’, $db); } }
  • Layouts Francesco Abeni for GiBiLogic http://extensions.gibilogic.com - info@gibilogic.com Page types related to a single view (object) "tmpl" subfolder (template override) ● List ● Single item (readonly) ● Single item (edit form) ● Blog ● ...
  • Francesco Abeni for GiBiLogic http://extensions.gibilogic.com - info@gibilogic.com
  • System messages Francesco Abeni for GiBiLogic http://extensions.gibilogic.com - info@gibilogic.com $app = JFactory::getApplication(); $app->enqueueMessage( $msg, $type )
  • JError / JException / JLog Francesco Abeni for GiBiLogic http://extensions.gibilogic.com - info@gibilogic.com Error handling vs. logging ● JError is deprecated ● JException is deprecated ● Use PHP Exception class(es) ● JLog is a way to track what's happening
  • Francesco Abeni for GiBiLogic http://extensions.gibilogic.com - info@gibilogic.com
  • Visibility Francesco Abeni for GiBiLogic http://extensions.gibilogic.com - info@gibilogic.com Variables and methods ● "var ..." is deprecated since PHP 5.1.2 ● public : available from other classes ● private : available only from the class ● protected : available from the class and from inherited or parent classes
  • Constants Francesco Abeni for GiBiLogic http://extensions.gibilogic.com - info@gibilogic.com ● constants instead of variables ● drop DS ● drop DIRECTORY_SEPARATOR ● use Joomla constants: http://docs.joomla.org/Constants ● warning: JPATH_SITE vs JPATH_BASE vs JPATH_ROOT vs JPATH_ADMINISTRATOR
  • Versioning Francesco Abeni for GiBiLogic http://extensions.gibilogic.com - info@gibilogic.com ● version format: major.minor.release (es. v3.1.5) ● variant: v3.1.5 Free, v3.1.5 Pro
  • And the road goes on and on Francesco Abeni for GiBiLogic http://extensions.gibilogic.com - info@gibilogic.com
  • Thanks :) f.abeni@gibilogic.com @f_abeni / @gibilogic http://www.slideshare.net/FrancescoAbeni/best-practices-for-joomla-extensions-developers-25353320 Francesco Abeni for GiBiLogic http://extensions.gibilogic.com - info@gibilogic.com Feedback please!