best practices for joomla extensions developers - joomla day 2013

56
Joomla Extensions Development Best Practices Francesco Abeni GiBiLogic extensions.gibilogic.com

Upload: francesco-abeni

Post on 27-Jan-2015

111 views

Category:

Technology


3 download

DESCRIPTION

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.

TRANSCRIPT

Page 1: Best practices for Joomla extensions developers - Joomla Day 2013

Joomla Extensions Development Best Practices

Francesco Abeni GiBiLogicextensions.gibilogic.com

Page 2: Best practices for Joomla extensions developers - Joomla Day 2013

Francesco Abeni for GiBiLogichttp://extensions.gibilogic.com - [email protected]

¡Hola, mundo!

Page 3: Best practices for Joomla extensions developers - Joomla Day 2013

Shameless self-promotion

Francesco Abeni for GiBiLogichttp://extensions.gibilogic.com - [email protected]

FrancescoAbeni

sPrintAddCSSPizzaBox

Page 4: Best practices for Joomla extensions developers - Joomla Day 2013

About this speech

Francesco Abeni for GiBiLogichttp://extensions.gibilogic.com - [email protected]

The quality of code in the Joomlasphere

Page 5: Best practices for Joomla extensions developers - Joomla Day 2013

Today roadmap:

Francesco Abeni for GiBiLogichttp://extensions.gibilogic.com - [email protected]

● Tools● Files and folders● Reuse software● MVC● Other tips● Conclusions

Feedback please!

Page 6: Best practices for Joomla extensions developers - Joomla Day 2013

No dev course

Francesco Abeni for GiBiLogichttp://extensions.gibilogic.com - [email protected]

Page 7: Best practices for Joomla extensions developers - Joomla Day 2013

Our target

Francesco Abeni for GiBiLogichttp://extensions.gibilogic.com - [email protected]

Good = not bad

Excellent = above the average

Good is enough for today

Page 8: Best practices for Joomla extensions developers - Joomla Day 2013

Francesco Abeni for GiBiLogichttp://extensions.gibilogic.com - [email protected]

Page 9: Best practices for Joomla extensions developers - Joomla Day 2013

IDE basic features

Francesco Abeni for GiBiLogichttp://extensions.gibilogic.com - [email protected]

● multiple files edit● syntax highlighting● index for methods and variables● autocompletion● autoformatting● compiler● versioning / unit testing / phpdoc / ...

Page 10: Best practices for Joomla extensions developers - Joomla Day 2013

Some IDEs

Francesco Abeni for GiBiLogichttp://extensions.gibilogic.com - [email protected]

Page 11: Best practices for Joomla extensions developers - Joomla Day 2013

Versioning

Francesco Abeni for GiBiLogichttp://extensions.gibilogic.com - [email protected]

http://git-scm.com/book

Page 12: Best practices for Joomla extensions developers - Joomla Day 2013

Standard

Francesco Abeni for GiBiLogichttp://extensions.gibilogic.com - [email protected]

Page 13: Best practices for Joomla extensions developers - Joomla Day 2013

Francesco Abeni for GiBiLogichttp://extensions.gibilogic.com - [email protected]

Page 14: Best practices for Joomla extensions developers - Joomla Day 2013

Everything in its right place

Francesco Abeni for GiBiLogichttp://extensions.gibilogic.com - [email protected]

Backend ● administrator○ components

■ com_componentname● componentname.xml● componentname.php● controllers● models● views

Page 15: Best practices for Joomla extensions developers - Joomla Day 2013

Everything in its right place

Francesco Abeni for GiBiLogichttp://extensions.gibilogic.com - [email protected]

Backend ● administrator○ components

■ com_componentname● ...● config.xml● install.php● sql● tables● helpers

Page 16: Best practices for Joomla extensions developers - Joomla Day 2013

● media○ com_componentname

■ css■ js■ img

● components○ com_componentname

■ componentname.php■ controllers■ models■ views

Everything in its right place

Francesco Abeni for GiBiLogichttp://extensions.gibilogic.com - [email protected]

Frontend

● images○ com_componentname

Page 17: Best practices for Joomla extensions developers - Joomla Day 2013

Francesco Abeni for GiBiLogichttp://extensions.gibilogic.com - [email protected]

Page 18: Best practices for Joomla extensions developers - Joomla Day 2013

CSS / JS

Francesco Abeni for GiBiLogichttp://extensions.gibilogic.com - [email protected]

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.

Page 19: Best practices for Joomla extensions developers - Joomla Day 2013

CSS out of the door

Francesco Abeni for GiBiLogichttp://extensions.gibilogic.com - [email protected]

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 }

Page 20: Best practices for Joomla extensions developers - Joomla Day 2013

JS out of the door

Francesco Abeni for GiBiLogichttp://extensions.gibilogic.com - [email protected]

<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:

Page 21: Best practices for Joomla extensions developers - Joomla Day 2013

Francesco Abeni for GiBiLogichttp://extensions.gibilogic.com - [email protected]

Page 22: Best practices for Joomla extensions developers - Joomla Day 2013

Joomla framework

Francesco Abeni for GiBiLogichttp://extensions.gibilogic.com - [email protected]

● JApplication● JDatabase● JUser● JSession● JDocument● JHTML● JForm● JConfig● JUri

● JFile● JFolder● JLog● JFilterInput ● JError and JException● JDate● JUtilities● JVersion● JLayout

Page 23: Best practices for Joomla extensions developers - Joomla Day 2013

PHP functions and classes

Francesco Abeni for GiBiLogichttp://extensions.gibilogic.com - [email protected]

● pcre● trim● usort● array_map● array_unique● json_encode● json_decode● microtime(true)● glob● curl

● DateTime● Standard PHP Library● Exception● SimpleXML● TCPDF● PHPMailer

Page 24: Best practices for Joomla extensions developers - Joomla Day 2013

PHP version

Francesco Abeni for GiBiLogichttp://extensions.gibilogic.com - [email protected]

● 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

Page 25: Best practices for Joomla extensions developers - Joomla Day 2013

Francesco Abeni for GiBiLogichttp://extensions.gibilogic.com - [email protected]

Page 26: Best practices for Joomla extensions developers - Joomla Day 2013

Real objects

Francesco Abeni for GiBiLogichttp://extensions.gibilogic.com - [email protected]

book writer library

Page 27: Best practices for Joomla extensions developers - Joomla Day 2013

Bad design sample

Francesco Abeni for GiBiLogichttp://extensions.gibilogic.com - [email protected]

● views/search● views/editbook● views/book● views/books● views/booksauthor● views/topten

Don't:

Page 28: Best practices for Joomla extensions developers - Joomla Day 2013

The controller

Francesco Abeni for GiBiLogichttp://extensions.gibilogic.com - [email protected]

● Filters input● Decides what to do● Checks access permissions● Executes task(s)● Optionally, calls the view

Page 29: Best practices for Joomla extensions developers - Joomla Day 2013

The model

Francesco Abeni for GiBiLogichttp://extensions.gibilogic.com - [email protected]

● Retrieves object data● Validates object data● Gets object data● Saves object data● Hates to be mistaken as an helper

Page 30: Best practices for Joomla extensions developers - Joomla Day 2013

The view

Francesco Abeni for GiBiLogichttp://extensions.gibilogic.com - [email protected]

● Ask the model for data● Display object(s)● Uses layouts!

Page 31: Best practices for Joomla extensions developers - Joomla Day 2013

Francesco Abeni for GiBiLogichttp://extensions.gibilogic.com - [email protected]

Page 32: Best practices for Joomla extensions developers - Joomla Day 2013

Header comment

Francesco Abeni for GiBiLogichttp://extensions.gibilogic.com - [email protected]

<?php

/*** @version mybooks.php 2013-08-10 15:23:00Z zanardi* @package GiBi MyBooks* @author GiBiLogic* @authorUrl http://www.gibilogic.com* @authorEmail [email protected]* @copyright Copyright (C) 2013 GiBiLogic. All rights reserved.* @license GNU/GPL v2 or later* @description Backend entry point*/

Page 33: Best practices for Joomla extensions developers - Joomla Day 2013

Entry point

Francesco Abeni for GiBiLogichttp://extensions.gibilogic.com - [email protected]

<?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();

Page 34: Best practices for Joomla extensions developers - Joomla Day 2013

Controller - part 1

Francesco Abeni for GiBiLogichttp://extensions.gibilogic.com - [email protected]

<?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; ...

Page 35: Best practices for Joomla extensions developers - Joomla Day 2013

Controller - part 2

Francesco Abeni for GiBiLogichttp://extensions.gibilogic.com - [email protected]

<?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); } ...

Page 36: Best practices for Joomla extensions developers - Joomla Day 2013

Controller - part 3

Francesco Abeni for GiBiLogichttp://extensions.gibilogic.com - [email protected]

<?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; }

Page 37: Best practices for Joomla extensions developers - Joomla Day 2013

Model - part 1

Francesco Abeni for GiBiLogichttp://extensions.gibilogic.com - [email protected]

<?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')); }

Page 38: Best practices for Joomla extensions developers - Joomla Day 2013

Model - part 2

Francesco Abeni for GiBiLogichttp://extensions.gibilogic.com - [email protected]

<?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(); }

Page 39: Best practices for Joomla extensions developers - Joomla Day 2013

Model - part 3

Francesco Abeni for GiBiLogichttp://extensions.gibilogic.com - [email protected]

<?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(); } ...

Page 40: Best practices for Joomla extensions developers - Joomla Day 2013

Model - part 4

Francesco Abeni for GiBiLogichttp://extensions.gibilogic.com - [email protected]

<?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'); } ...

Page 41: Best practices for Joomla extensions developers - Joomla Day 2013

View - part 1

Francesco Abeni for GiBiLogichttp://extensions.gibilogic.com - [email protected]

<?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); }

Page 42: Best practices for Joomla extensions developers - Joomla Day 2013

View - part 2

Francesco Abeni for GiBiLogichttp://extensions.gibilogic.com - [email protected]

<?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'); }}

Page 43: Best practices for Joomla extensions developers - Joomla Day 2013

Francesco Abeni for GiBiLogichttp://extensions.gibilogic.com - [email protected]

Page 44: Best practices for Joomla extensions developers - Joomla Day 2013

Helpers

Francesco Abeni for GiBiLogichttp://extensions.gibilogic.com - [email protected]

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

Page 45: Best practices for Joomla extensions developers - Joomla Day 2013

Table classes

Francesco Abeni for GiBiLogichttp://extensions.gibilogic.com - [email protected]

Interface to and from the database

Active Record pattern

● Define table name and unique id● load, store, delete, and so on

Page 46: Best practices for Joomla extensions developers - Joomla Day 2013

Table classes - sample code

Francesco Abeni for GiBiLogichttp://extensions.gibilogic.com - [email protected]

<?php

class TableBook extends JTable { public function __construct(&$db) { parent::__construct(‘#__books’, ‘id’, $db); } }

Page 47: Best practices for Joomla extensions developers - Joomla Day 2013

Layouts

Francesco Abeni for GiBiLogichttp://extensions.gibilogic.com - [email protected]

Page types related to a single view (object)"tmpl" subfolder (template override)

● List● Single item (readonly)● Single item (edit form)● Blog● ...

Page 48: Best practices for Joomla extensions developers - Joomla Day 2013

Francesco Abeni for GiBiLogichttp://extensions.gibilogic.com - [email protected]

Page 49: Best practices for Joomla extensions developers - Joomla Day 2013

System messages

Francesco Abeni for GiBiLogichttp://extensions.gibilogic.com - [email protected]

$app = JFactory::getApplication();$app->enqueueMessage( $msg, $type )

Page 50: Best practices for Joomla extensions developers - Joomla Day 2013

JError / JException / JLog

Francesco Abeni for GiBiLogichttp://extensions.gibilogic.com - [email protected]

Error handling vs. logging

● JError is deprecated● JException is deprecated● Use PHP Exception class(es)

● JLog is a way to track what's happening

Page 51: Best practices for Joomla extensions developers - Joomla Day 2013

Francesco Abeni for GiBiLogichttp://extensions.gibilogic.com - [email protected]

Page 52: Best practices for Joomla extensions developers - Joomla Day 2013

Visibility

Francesco Abeni for GiBiLogichttp://extensions.gibilogic.com - [email protected]

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

Page 53: Best practices for Joomla extensions developers - Joomla Day 2013

Constants

Francesco Abeni for GiBiLogichttp://extensions.gibilogic.com - [email protected]

● 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

Page 54: Best practices for Joomla extensions developers - Joomla Day 2013

Versioning

Francesco Abeni for GiBiLogichttp://extensions.gibilogic.com - [email protected]

● version format: major.minor.release (es. v3.1.5)● variant: v3.1.5 Free, v3.1.5 Pro

Page 55: Best practices for Joomla extensions developers - Joomla Day 2013

And the road goes on and on

Francesco Abeni for GiBiLogichttp://extensions.gibilogic.com - [email protected]

Page 56: Best practices for Joomla extensions developers - Joomla Day 2013

Thanks :)

[email protected]@f_abeni / @gibilogic

http://www.slideshare.net/FrancescoAbeni/best-practices-for-joomla-extensions-developers-25353320

Francesco Abeni for GiBiLogichttp://extensions.gibilogic.com - [email protected]

Feedback please!