Introduzione
Il grande successo di Joomla in questi anni è sicuramente dovuto alla semplicità ed alle potenzialità d'utilizzo, nonché ai numerosi plugin e moduli sviluppati. Esistono di fatto svariate estensioni pronte all'uso, distribuite gratuitamente per fini non commerciali, per rendersene conto basta dare un'occhiata al sito ufficiale che raccoglie tutte le estensioni Joomla. Per i più esigenti, comunque, può succedere di non trovare un'estensione che corrisponda alle proprie aspettative, in questo caso è possibile sviluppare ed ideare un plugin o un modulo che integri al suo interno le funzionalità da noi attese. In questa guida vedremo come sviluppare un componente standard, costituito da una parte back end ed una frond end, e che si interfacci con il database alla base di Joomla, in sostanza, andremo a simulare il comportamento base di un qualsiasi modulo/pluing Joomla.
Obiettivi del componente
Il componente che implementeremo astrae il concetto di bacheca online. Esso sarà formato da una parte back end e una front end. Tramite l'interfaccia front end, gli utenti del sito visualizzeranno le informazioni immesse dagli amministratori che a loro volta utilizzeranno l'interfaccia di back end per tale scopo. L'amministratore o il manager del sistema potrà, semplicemente utilizzando un form, inserire l'annuncio ed il titolo da visualizzare, quest'ultimo sarà automaticamente memorizzato all'interno del database Joomla. Questo semplice componente possiede al suo interno tutte le basi di un qualunque modulo Joomla, cioè programmazione della parte front end, della parte back end, interazione con il database e le basi sulla politica di sicurezza intrapresa dagli sviluppatori Joomla.
Requisiti fondamentali
Per procedere allo sviluppo di un componente Joomla occorre, principalmente conoscere un minimo di teoria, nello specifico gli argomenti che ci interesseranno sono le basi del linguaggio PHP e dei sistemi web, un minimo di semantica SQL per la strutturazione di semplici query, una conoscenza del pattern di programmazione MVC (Model-View-Controller) e le librerie adottate ed esportate da Joomla 1.5 per poter rendere affidabile, semplice e possibile lo sviluppo e l'integrazione del componente all'interno del CMS. Per quanto riguarda il linguaggio PHP, potrete trovare ottime guide e diverse risorse all'interno del nostro sito dedicato a PHP, stessa cosa per il "linguaggio" SQL.
Il framework Joomla ed il MVC
Con la versione 1.5 di Joomla gli sviluppatori hanno fatto un notevole sforzo per rendere possibile a "chiunque" lo sviluppo di componenti integrabili con il CMS, ciò è stato reso possibile grazie alla riscrittura di alcune classi del core di Joomla, nonché ad un'accurata implementazione del modello MVC, all'interno del sito Joomla.org è presente anche una sezione "Developer" interamente dedicata agli sviluppatori, dalla quale poter trarre numerosi spunti.
Esula da quest'articolo una trattazione dettagliata del modello MVC; sinteticamente comunque è possibile definire il modello MVC, come un modello di programmazione (pattern di programmazione) che consente di progettare le applicazioni modularmente in modo che il livello dati, il livello presentazione ed il livello logico, siano indipendenti tra di loro, cioè un cambiamento effettuato in uno dei tre livelli non deve implicare uno stravolgimento nei restanti due. Il Model è deputato alla gestione della logica dell'applicazione (elaborazione, accesso ai dati), la componente View organizza i dati per essere visualizzati all'utente e la parte Controller viene utilizzata per gestire le richieste dell'utente indirizzandole verso gli oggetti appropriati. Per permettere ciò e dare una base ai programmatori, i padri di Joomla 1.5 hanno ideato una struttura base per lo sviluppo dei componenti, questa struttura naturalmente rispecchia l'MVC ed è articolata in quattro "componenti software":
- Uno o più oggetti Model;
- Uno o più oggetti View;
- Uno o più oggetti Controller;
- Un file denominato Entry Point;
Prepariamo le cartelle
Per organizzare in maniera efficace tutti i file che facciano parte di un componente Joomla possiamo strutturare in modo gerarchico le nostre cartelle. La prima cartella da creare è quella madre, cioè quella che conterrà tutte le altre. Il nome della cartella madre per convenzione inizia con la stringa com_ seguita dal nome del componente, nel nostro caso la cartella si chiamerà com_bacheca. Al suo interno inseriremo allo stesso livello tre cartelle, una admin (conterrà tutti i file e le cartelle d'installazione e gestione del back end), languages (conterrà tutti i file .ini e le cartelle per rendere l'applicazione multilingua, sia lato amministratore che utente), site (contenente tutti i file e le cartella da utilizzare lato front end). Allo stesso livello di queste tre cartelle inseriremo un file XML denominandolo nomeComponente.xml, nel nostro caso bacheca.xml, approfondiremo la funzionalità nell'articolo.
Impartiamo le direttive a Joomla con XML
Come fa il motore di Joomla a sapere esattamente dove sono allocati i vari file e database da utilizzare per il corretto funzionamento del componente? La risposta a questa domanda è semplicissima, all'interno della cartella principale che conterrà tutti i nostri file, infatti dovrà essere presente una particolare file XML, tale file avrà per convenzione come nome quello che viene dato al componente e naturalmente come esenzione quella .xml, nel nostro caso il file sarà denominato bacheca.xml. Il file in oggetto è composto da diverse direttive, e può essere suddiviso in diverse parti. La prima parte riguarda per lo più informazioni generali sul componente, come ad esempio il nome del componente (attributo name), la data di creazione (attributo creationDate), l'autore (author), informazioni sul copyright (copyright), licenza d'utilizzo (license), versione del componente (versione) ed eventualmente una descrizione del componente.
<name>Bacheca</name> <creationDate>Marzo 2010</creationDate> <author>Antonio Avolio for html.it</author> <authorUrl>https://www.html.it/</authorUrl> <copyright>Copyright 2010 Antonio Avolio</copyright> <license>http://www.gnu.org/licenses/gpl-3.0.html GNU/GPL</license> <version>1.0</version> <description> <![CDATA[Esempio di componente]]> </description>
La seconda parte interessa la gestione del database, cioè dove sono collocati gli script d'installazione e disinstallazione dello stesso, nel nostro caso utilizzeremo i file install.sql ed unistall.sql rispettivamente per installare e disinstallare il nostro componente.
<install> <sql> <file charset="utf8" driver="mysql">install.sql</file> </sql> </install> <uninstall> <sql> <file charset="utf8" driver="mysql">uninstall.sql</file> </sql> </uninstall>
Come accennato in precedenza il nostro componente è formato da una parte front end ed un back end, quindi dovremmo fornire al motore di Joomla l'esatta collocazione dei file utilizzati da queste due aree. Relativamente al componente front end inseriremo la collocazione dei file all'interno del tag files folder site, avendo cura di specificare i files controller, model e viev.
<files folder="site"> <filename>bacheca.php</filename> <filename>controller.php</filename> <filename>views/bacheca/view.html.php</filename> <filename>views/bacheca/tmpl/default.php</filename> <filename>models/bacheca.php</filename> </files>
Analogo discorso sarà effettuato per i file facenti parte del back end applicativo, avendo cura di specificare come file folder "admin" e tutti i file che compongono tale area. All'interno del tag principale administration, sarà nostra cura inserire una voce menu all'interno della quale inserire la stringa da visualizzare all'interno dell'elenco componenti.
È possibile relativamente alla parte back end ed alla parte front end specificare un file di localizzazione internazionale, così facendo renderemo il nostro componente multilingua. Tale operazione è resa possibile dall'utilizzo del tag languages, naturalmente occorrerà creare un file per ogni lingua che specificheremo, nella posizione indicata all'interno del file xml.
… <languages> <language tag="it-IT">languages/site/it-IT.com_bacheca.ini</language> </languages> …
Nel nostro caso occorrerà creare nella cartella languages/site il file it-IT.com_bacheca.ini .
Il database
Il nostro componente memorizzerà le informazioni in una tabella che sarà inclusa nel database di Joomla, occorrerà pertanto installare e gestirne l'eventuale disinstallazione. Come è emerso dal file XML, per assolvere a questo scopo dovremo creare due file install.sql e uninstall.sql, essi saranno contenuti nella cartella "admin" relativa al nostro componente. Tali file conterranno semplicemente le istruzioni per manipolare un record ed una tabella in un database, in particolare il file unistall.sql "dropperà" la tabella associata al componente, andando quindi a ripulire il database di Joomla, l'istruzione da impartire è pertanto DROP TABLE IF EXISTS '#__bacheca'. È il caso di mettere in risalto la presenza del carattere cancelletto e del doppio underscore prima del nome della tabella, così facendo il motore di Joomla anteporrà automaticamente al nome della tabella scelto il prefisso utilizzato per le tabella di Joomla (ad esempio jos_ in caso d'installazione standard).
Discorso analogo viene fatto per il file install.sql, in questo caso però dovremo prevedere la creazione della tabella, attribuendo ai vari campi tutte proprietà tipiche di un campo database, ad esempio specificando la key della tabella, il charset ecc. Esula da quest'articolo una trattazione approfondita del linguaggio sql, viene riportato a titolo esemplificativo il contenuto del file install.sql:
DROP TABLE IF EXISTS '#__bacheca'; CREATE TABLE '#__bacheca' ( 'id' INT NOT NULL AUTO_INCREMENT, 'description' TEXT NOT NULL, 'tittle' TEXT NOT NULL, PRIMARY KEY ('id') ) DEFAULT CHARSET=utf8;
Parliamo più lingue
Internazionalizzare il nostro componente è sicuramente un vantaggio per gli utenti, l'internazionalizzazione viene effettuata avvalendosi dell'ausilio di due file con estensione ini per ogni lingua che si desidera integrare, uno per il front end ed uno per il back end. I due file dovranno rispettare nella nomenclatura secondo la seguente convenzione:
- iniziare con l'identificativo di località nel nostro caso it-IT, nel caso di inglese americano en-US ecc.;
- Inserimento di un . (punto);
- nome del componente preceduto dal prefisso com_ ;
- terminare con per .ini;
Secondo le direttive richieste quindi i nostri file avranno nome it-IT.com_bacheca.ini, e saranno memorizzati all'interno del path /com_bacheca/languages/admin e /com_bacheca/languages/site, rispettivamente per la "traduzione" del back end e del front end. Al loro interno inseriremo tante righe quante sono le parole da tradurre, ogni riga, infatti indicherà al motore di ricerca di Joomla come tradurre una determinata stringa e sarà formata da una parte sinistra (stringa in lingua "originale") ed una parte destra (stringa nella lingua in cui tradurre la parola o frase) intervallate da un = . Ad esempio volendo tradurre la stringa no post scriveremo :
NO POST=Nessun post
Nella seconda parte dell'articolo vedremo come programmare la parte relativa al backend del nostro plugin. Seguiteci nelle prossime pubblicazioni.
Programmiamo il back end applicativo
La parte back e front end, rispettando il pattern MVC hanno una composizione simile tra di loro, quindi alcuni ragionamenti fatti per questa sezioni saranno validi anche per la parte front end. Ogni applicazione conterrà un particolare file detto entry point.
Il primo passo: L'entry point
Ogni modulo o plugin possiede al proprio interno uno o più (lato front end e back end) "entry point" (punto d'ingresso), tale oggetto è un normalissimo file PHP, che importa e richiama alcune librerie proprie di Joomla. Nel nostro caso chiameremo il file in questione admin.bacheca.php, trattandosi dell'entry point lato amministratore, esso sarà posizionato all'interno della cartella admin del nostro modulo. La prima istruzione che sarà presente in questo file, come del resto anche negli altri contenti codice PHP (naturalmente dopo la dichiarazione dei tag PHP), è relativa alla possibilità d'accedere al componente solo ed esclusivamente attraverso Joomla, l'istruzione che permette ciò è:
defined("_JEXEC") or die ("Accesso negato");
Il comando rende impossibile, ad esempio, accedere direttamente alla pagina bacheca.php, cioè digitando l'indirizzo http://www.miosito.it/components/bacheca.php riceveremo un messaggio d'errore automaticamente generato da Joomla, tale scelta va inquadrata nell'ottica di gestione della sicurezza effettuata dal CMS, ecco perché ogni file facente parte del componente includerà tale dichiarazione. Altra inclusione molto importante (e quasi standard per tutti i file) riguarda la direttiva JPATH_COMPONENT esplicitata nel seguente modo:
require_once(JPATH_COMPONENT.DS."controller.php");
Cerchiamo di capirne il significato. Viene passato alla funzione require_once tramite la concatenazione delle costanti JPATH_COMPONENT e DS, il path relativo al file contente il controller della nostra applicazione, JPATH_COMPONENT come detto è una costante, essa ritorna il percorso assoluto sul server della cartelle nella quale vengono archiviati i componenti, mentre DS (anch'essa una costante) è utilizzato per motivi di compatibilità dei path nei diversi sistemi operativi, infatti a seconda del sistema operativo sul quale è in esecuzione il nostro Joomla ritornerà il relativo "directory separator" (‘/' per i sistemi *nix based, ‘' microsoft based).
Si ha a questo punto la necessità di definire ed istanziare l'oggetto controller, deputato al controllo delle attività svolte dal componente. È buona norma verificare che il controller sia presente all'interno della variabile globale $_REQUEST utilizzando il seguente codice:
if($controller = JRequest::getWord('controller')) { $path = JPATH_COMPONENT.DS.'controllers'.DS.$controller.'.php'; if(file_exists($path)) { require_once $path; } else { $controller = ''; } }
Eseguito tale controllo siamo pronti per istanziare l'oggetto controller, avvalendoci dell'opretato new:
// Istanzia l'oggetto Controlle $classname = 'BachecaController'.$controller; $controller = new $classname(); …
Una volta creato il controller si avrà cura d'invocare il metodo JRequest.
$controller->execute(JRequest::get(‘task'));
L'invocazione di execute eseguita dall'oggetto controller determina la funzione che verrà eseguita dal componente, tale metodo viene ereditato dalla classe base JController editata dagli sviluppatori di Joomla. È importante non accedere direttamente alle variabili di PHP per motivi di sicurezza.
È altresì possibile eseguire un redirect invocando il metodo redirect() sull'oggetto $controller in presenza di determinati eventi che potrebbero compromettere la stabilità del nostro componente. In definitiva l'oggetto entry point ha come unico scopo la creazione dell'oggetto controller e l'invocazione su esso di alcuni metodi al fine di rendere l'applicazione Joomla da noi sviluppata sicura. Il nome utilizzato per individuare la classe controller non è casuale, è infatti fondamentale adottare una particolare nomenclatura, il nome della classe Controller difatti, sarà formato aggiungendo la stringa "Controller" ad un prefisso, quest'ultimo per semplicità è il nome del componente nel nostro caso Bacheca. In definitiva la nostra classe controller avrà nome: BachecaController.
Per semplicità abbiamo inserito un solo controller all'interno dell'applicazione, ma vale la pena ricordare che è possibile editare più controller per ogni componente, a loro volta derivate dal controller padre o figlio, ciò accade quando ad esempio si voglio includere diverse funzioni per diversi profili utente ad esempio.
L'oggetto controller
Come abbiamo visto in precedenza l'entry point riporta al suo interno dove reperire il controller dell'applicazione, nel nostro caso esso è contenuto nel file bachecaController.php, quindi inizieremo creando un file php con tale nome, al sui interno procederemo inserendo le direttive standard viste in precedenza relative alle restrizioni d'accesso, in più importeremo con l'ausilio della funzione jimport la definizione della classe Controller di JController.
// Impedisce l'accesso diretto al file defined( '_JEXEC' ) or die( 'Restricted access' ); // Inclusione classe base JController jimport('joomla.application.component.controller');
Una volta importata la classe base, occorrerà inserire al suo interno tutti i metodi invocabili dall'applicazione, nel nostro caso l'unica funzione invocabile sarà quella display(), che dovrà provvedere alla visualizzazione delle informazioni memorizzate nel database.
class BachecaController extends JController { function display() { parent::display(); } }
Il modello
Il modello contiene la logica applicativa del componente software che si sta sviluppando, esso ha come compito principale quello di fornire i servizi al controller ed al view dell'applicazione. Il model è creato dal controller, che ne potrà invocare direttamente i metodi oppure demandarne l'invocazione ad altri oggetti come ad esempio a View.
Anche in questo caso si devono seguire delle convenzioni sulle nomenclature della classe e della cartella. I file relativi al model saranno contenuti nelle rispettive cartelle models all'interno di admin e site, ogni classe model sarà denominata come segue nomeComponenteModelNomeModel mentre il file sarà della forma nome componente.php. All'interno del nostro componente implementeremo due classi model, bacheca e ppost. All'interno del file bacheca.php inseriremo la classe BachecaModelBacheca, che avrà come funzioni principali quella di paginare i vari post e recuperare tutti i post contenuti nel database, per far ciò si avvarrà dei metodo buildQuery e &getData, il primo provvederà a creare la query di selezione sulla tabella #__bacheca, il secondo è deputato al caricamento dei dati (per il codice completo di queste due classi si rinvia ai file allegati alla presente guida).
Naturalmente è inutile dire quale sarà la prima riga di questi file defined('JEXEC') or die();, successivamente tramite la direttiva jimport andremo ad includere la classe base joomla.apllication.component.model. Eseguite le operazioni preliminari siamo pronti per creare gli oggetti model per il nostro componente come estensione di JModel base. Ricordiamo ancora una volta che l'unico compito delle classi Model è quello di fornire servizi alle altri classi, nel nostro caso si ha la necessità d'estrarre i post dal database al fine di poterli visualizzare nella bacheca.
Il model ppost viene utilizzato per il popolamento del database con le informazioni che gli amministratori o manager inseriscono nelle apposite form, pertanto in tale classe ci aspettiamo di trovare oltre che al costruttore, almeno una funzione per la memorizzazione delle informazioni nonché una funzione per l'eliminazione dei post vecchi oppure indesiderati, in tali metodi si fa uso sia di direttive native di php che di alcune relative a Joomla
Template back end
Anche lato amministratore, occorre predisporre un meccanismo di presentazione dei dati, naturalmente non possiamo non avvalerci di un template, ad ogni view possono essere associati differenti template, nel nostro caso lavoreremo sul template di default di Joomla. Il file relativo al template (default.php), verrà posizionato all'interno della cartella com_bacheca/views/bacheca/tmpl. Il codice contenuto in questo file è relativamente semplice, si tratta infatti di produrre in output una semplice pagina html con le informazioni da mostrare all'utente amministratore. Grazie ad alcune funzioni di Joomla in più potremo creare semplicemente i pulsanti che dovranno comparire nella barra dei pulsanti, per i nostri scopi sono richiesti i pulsanti cancella, edita ed aggiungi, è altresì semplice visualizzare il nome del componente con un'eventuale icona.
// Creazione pulsanti JToolBarHelper::title( JText::_('Bacheca' ), 'generic.png'); JToolBarHelper::deleteList(); JToolBarHelper::editListX(); JToolBarHelper::addNewX();
Per la creazione della lista di visualizzazione dei post, utilizzeremo ancora una volta una funzione predefinita di Joomla come JText:: che ci consente di creare una casella di testo con l'etichetta desiderata. Naturalmente il recupero dei post avviene semplicemente tramite un ciclo for sul result set della query.
Oltre a poter visualizzare, selezionare e cancellare un componente è necessario predisporre i meccanismi di aggiornamento e creazione di un nuovo post, per questo occorre creare un template con queste funzionalità, il file deputato a questo compito è default.php contenuto nella cartella views/ppost/tmpl/default.php, in tale file eseguiremo includeremo dei semplici controlli javascript per verificare che siano valorizzati i campi titolo e descrizione del post.
L'oggetto Tables
All'interno del nostro componente all'interno della cartella admin/tables è presente il file ppost, tale file implementa al suo interno l'oggetto TablePPost come erede di JTable, tale oggetto è di supporto al modello che lo richiama per eseguire operazioni sui dati, quali modifica ed inserimento, nel nostro caso oltre al costruttore è stata implementata una funzione check() che verifica il corretto inserimento della descrizione e del titolo per il post.
Front end
Abbiamo visto fino ad ora come gestire la parte back end, sicuramente la parte più complessa di tutta l'applicazione perché oltre alla visualizzazione, occorre prevedere una fase di creazione e modifica dei post, concentriamoci ora sulla parte front end, tutti i file relativi a tale parte saranno contenuti nella cartella site a sua volta contenuta nella cartella madre com_bacheca. Come anticipato in precedenza, la composizione è del tutto simile alla parte back end, perché anch'essa rispetta il patter MVC, pertanto sui file controller.php e bacheca.php non discuteremo.
Il modello del front end, è molto semplice, infatti all'interno della classe BachecaModelBacheca contenuta nel file bacheca.php posizionato nella cartella /site/models è presente un unico metodo &getData, che ha come unico scopo quello di recuperare i post presenti nella tabellla #__bacheca tramite una query di selezione.
function &getData() { $sql = "SELECT * FROM #__bacheca "; $this->_db->setQuery($sql); $rq = $this->_db->loadObjectList(); return $rq; }
La parte view ha come unico compito quello di visualizzare a video i vari post, anche in questo caso si va ad utilizzare il template impostato di default nell'ambiente Joomla, semplicemente effettuando una stampa delle informazioni contenute nel database.
Come possiamo vedere la stampa è molto "spartana", questo perché trattandosi di una guida non si vuole distrarre l'attenzione del lettore sulle parti fondamentali dello sviluppo del componente.
Prepariamoci per la distribuzione
La distribuzione del nostro componente avverrà utilizzando il file zip, quindi con un qualsiasi software 7zip, winzip ecc. andremo a produrre in output un file .zip contente il nostro progetto, a cui potremo assegnare il nome che più ci aggrada.
Dopo aver creato il file .zip del nostro componente potremo installarlo come un normale componente Joomla.
Pubblicazione dei post
Per poter dare la possibilità agli utenti di visualizzare i post inseriti lato back end, andremo ad includere nel menu principale la voce bacheca, per far ciò collegandoci al back end di Joomla come amministratori, entreremo nella sezione "Gestione voci di menu".
Utilizzando il tasto nuovo andremo a selezionare la voce di menu "Bacheca Online" e successivamente inseriremo le informazioni riguardanti il titolo e l'alis della voce appena creata.
Conclusioni
Il componente oggetto di questa mini guida presenta tutte le caratteristiche tipiche di una qualsiasi estensione Joomla, abbiamo volutamente tralasciato implementazioni sofisticate e dettagliate delle funzioni per poterci concentrare sugli aspetti cardine dello sviluppo in ambiente Joomla, naturalmente il progetto sviluppato
può essere arricchito con piccoli sforzi di nuove funzioni, quali la possibilità di abilitare/disabilitare un post, inserire una data di validità ecc.
Alleghiamo per completezza al seguente articolo il file compresso del nostro progetto, che potrà essere già utilizzato all'interno del nostro CMS, oppure modificato o analizzato per comprendere meglio le dinamiche di sviluppo.