martedì 28 agosto 2007

Joomla 1.5: Sviluppo Componenti

La versione 1.5 di Joomla, attualmente allo stadio di RC1 (scaricabile dal sito ufficiale www.joomla.org), ha introdotto parecchi cambiamenti all'insieme di classi e funzioni di base dedicate allo sviluppo di moduli, componenti e plugins.

In particolare il nuovo framework renderà più semplice agli sviluppatori di componenti organizzare il proprio codice secondo il modello MVC (Model-View-Controller).

Una spiegazione sul modello MVC ed i sui benefici è presente, in inglese, sul wiki per sviluppatori nel sito ufficiale di Joomla per cui possiamo lasciare da parte ogni disquisizione teorica e passare direttamente a vedere con un esempio pratico come sviluppare un componente per Joomla 1.5.

Ho pensato che un componente per l'acquisizione di dati possa essere un buon componente di esempio. E' abbastanza facile da realizzare, ma nello stesso tempo non è troppo banale.

Il nome del componente è MyForm e queste sono le sue funzioni base.

  • Visualizzazione di un modulo di immissione dati
  • Salvataggio nel database dei dati immessi dall'utente
  • Visualizzazione dei dati immessi in un semplice formato tabellare.

Struttura di un componente Joomla 1.5

Paragonati ai componenti per le versioni 1.0.xx, i componenti della nuova versione hanno una struttura molto più modulare, ed interamente orientata agli oggetti. Il framework mette a disposizione classi base (JModel, JView, JController), da cui lo sviluppatore deriva le classi necessarie al proprio componente.

La struttura di base di un componente è questa:

  • Un file principale (entry point)
  • Uno o più oggetti Controller.
  • Uno o più oggetti Model.
  • Uno o più oggetti View. Ad ogni View viene associato uno o più Template.

Consiglio di tenere a portata di mano il codice del componente (myform1.zip scaricabile dal sito) per seguire meglio il discorso.

Entry point. File myform.php

in .../components/com_myform/
Dove i puntini rappresentano il percorso completo alla cartella dove è stato installato Joomla

defined('_JEXEC') or die('Restricted access');

Serve ad assicurarsi che si possa accedere al componente solo da Joomla. Un qualsiasi tentativo di eseguirne il codice dall'esterno di Joomla (per es. invocando direttamente la url www.miosito.ext/components/myform.php) viene bloccato da questa istruzione. Si tratta di un'importante misura di sicurezza e questa riga deve sempre essere inserita all'inizio di ogni file che fa parte del componente.

require_once(JPATH_COMPONENT.DS.'controller.php');

Include il file contenente la definizione della classe controller. JPATH_COMPONENT è una costante che contiene il percorso assoluto sul server della cartella del componente. DS (directory separator) è un'altra costante che contiene '/' o '\' a seconda del sistema operativo su cui si è installato Joomla. E' consigliabile utilizzare questa costante nei percorsi passati alle istruzioni require ed include per garantirsi che il codice sia indipendente dal sistema operativo.

$controller = new MyFormController();

Crea l'oggetto controller.

$controller->execute(JRequest::getVar('task'));

JRequest::getVar legge una variabile dalla URL. Il controller riceve il valore di tale variabile tramite il metodo execute() ed esegue la relativa funzione.

$controller->redirect();

Serve ad eseguire una eventuale redirezione di pagina decisa dal controller. Maggiori dettagli in seguito.

Il codice del file principale (o punto di ingresso) del componente è tutto qui. La sua funzione è di creare un'istanza dell'oggetto controller e indicargli la funzione da eseguire.

Controller. File controller.php

in .../components/com_myform/
defined('_JEXEC') or die('Restricted access');

jimport('joomla.application.component.controller');
Della funzione della prima riga si è già detto. jimport è una funzione di servizio utilizzata per includere librerie di base in alternativa alle funzioni include e require del PHP. In questo caso viene inclusa la definizione della classe base del Controller (JController) che si trova in .../libraries/joomla/application/component/controller.php
class MyFormController extends JController {

}

Definisce l'oggetto Controller principale del componente. Ci limitiamo a definire la classe senza implementare alcun metodo. In questa versione preliminare del componente tutto il lavoro viene svolto dalla classe base JController.

Se avrete la pazienza di arrivare fino alla fine di questa serie di articoli vedrete che arriverà il momento di scrivere qualcosa in questa classe.

Model. File myform.php

in .../components/com_myform/models/
defined('_JEXEC') or die();
jimport('joomla.application.component.model');

Niente di nuovo.

class MyFormModelMyForm extends JModel {
  var $form = array(
    'name'=>'myform',
    'fields' => array (
      array('label'=>'Nome',
      'name'=>'myform[nome]',
      'id'=>'nome'),
      array('label'=>'Cognome',
      'name'=>'myform[cognome]',
      'id'=>'cognome'),
      array('label'=>'Telefono',
      'name'=>'myform[telefono]',
      'id'=>'telefono',
      'size'=>15),
      array('label'=>'Indirizzo',
      'name'=>'myform[indirizzo]',
      'id'=>'indirizzo',
      'size'=>40),
      array('label'=>'Note',
      'name'=>'myform[note]',
      'id'=>'note',
      'rows'=>10,
      'cols'=>40,
      'type'=>'textarea'),
      array('name'=>'Invia',
      'type'=>'submit'),
      array('name'=>'option',
      'value'=>'com_myform',
      'type'=>'hidden'),
      array('name'=>'task',
      'value'=>'submit',
      'type'=>'hidden')
    )
  );
  function getForm() {
   return $this->form;
 }
}

L'oggetto Model contiene la logica applicativa del componente, definisce le entità che il componente deve gestire e i metodi che interagiscono con esse.

Nel nostro esempio definiamo una struttura che rappresenta un modulo di immissione dati: un array associativo di cui il campo fields è a sua volta un array di array associativi attributo/valore. E' una di quelle cose che si capiscono meglio guardando il codice piuttosto che con una spiegazione a parole!

Definiamo poi un metodo getForm() che semplicemente ritorna questa struttura dati

View. File view.html.php

in .../components/com_myform/views/myform/
defined('_JEXEC') or die('Restricted access');
jimport('joomla.application.component.view');

class MyFormViewMyForm extends JView {
  function display($tpl = null) {
    $model =& $this->getModel();
    $form = $model->getForm();
    $this->assignRef('form', $form);
    parent::display($tpl);
  }
}

Definisce l'oggetto View principale a cui è demandata la visualizzazione dei dati.

Per ogni oggetto View sono definiti uno più Template che determinano l'aspetto e l'organizzazione della visualizzazione.

I compiti del metodo display() sono

  • Recuperare un riferimento all'oggetto Model tramite il metodo JView::getModel()
  • Ricevere dall'oggetto Model la struttura da visualizzare tramite il metodo getForm() che abbiamo definito nella classe MyFormModelMyForm
  • Tramite il metodo assignRef() associare una etichetta a questa struttura dati in modo da poterla recuperare all'interno del template.
  • Invocare il metodo display() della classe base JView che passa il controllo al template per la visualizzazione.

Template. File default.php

in .../components/com_myform/views/myform/tmpl/

Non riporto tutto il codice trattandosi di semplici istruzioni di visualizzazione. La struttura che definisce il modulo di immissione dati è letta campo per campo, vengono impostati valori predefiniti per gli attributi che fossero stati lasciati vuoti, quindi il codice HTML viene visualizzato.

File di installazione myform.xml

Per ogni componente deve essere creato un file XML con le informazioni utilizzate dalla procedura di installazione per copiare al posto giusto tutti file necessari.

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE install SYSTEM 
"http://dev.joomla.org/xml/1.5/component-install.dtd">
<install type="component" version="1.5.0">
 <name>Myform</name>
 <version>1.0</version>
 <description>
   Esempio di componente per l'immissione di dati.
 </description>
 <files folder="site">
  <filename>myform.php</filename>
  <filename>controller.php</filename>
  <filename>views/myform/view.html.php</filename>
  <filename>views/myform/tmpl/default.php</filename>
  <filename>models/myform.php</filename>
 </files>
 
 <administration>
  <menu>My Form</menu>
  <files folder="admin">
   <filename>admin.myform.php</filename>
  </files>  
 </administration>
</install>

Il file admin.myform.php deve essere inserito altrimenti avremo un errore al momento dell'installazione del componente, ma al momento è vuoto perchè non sono ancora presenti le funzioni di amministrazione.

La versione preliminare del componente è pronta e può essere scaricata dal sito (myform1.zip) Per installare il componente in Joomla

  • Accedere all'area di amministrazione sito.
  • Selezionare il menu Extensions -> Install/Unistall
  • Premere il pulsante Sfoglia a fianco del campo Package File. Selezionare il file zip appena scaricato e confermare.
  • Premere Upload File & Install

Se tutto è andato bene dovreste vedere un breve testo descrittivo del componente.

Inoltre una voce My Form sarà presente sotto il menu Components anche se l'unica cosa che vedrete se la selezionate è una pagina vuota visto che non abbiamo ancora scritto le funzioni di amministrazione.

E' necessario a questo punto includere un link al componente per poterlo testare.

  • Selezionare il menu Menus -> Menu Manager
  • Fare click sotto la colonna Menu Items in corrispondenza del menu mainmenu o othermenu (o un altro menu dove volete inserire il link al componente)
  • Nella pagina seguente selezionare l'icona New
  • Selezionare sotto Internal Link, My Form -> MyForm -> Default Layout
  • Impostare un titolo per la voce di menu e salvare.

Ritornati sulla pagina principale del sito selezionare la voce del menu appena inserita. Comparirà il modulo di immissione dati.

Questo è tutto. Per il momento il componente non svolge nessun altra funzione. Aggiungeremo il resto in un prossimo articolo.

11 commenti:

Anonimo ha detto...

Scusa se oso, forse non è questo il modo, ma cercavo di imparare leggendo il tuo articolo e mi sono arenata quando indichi una cartella che io in realtà non ho
.../components/com_myform/
in .../components/
Ho sbagliato l'installazione?
Eppure l'installazione del componente e il link li ho fatti senza problemi. Hai dritte da darmi?

Massimo ha detto...

Nessun problema, figurati.

I puntini stanno per il percorso alla cartella dove hai installato Joomla. Se hai installato il componente senza ricevere un messaggio di errore e il link funziona devi avere la cartella com_myform.

Se hai installato Joomla in una cartella chiamata joomla sarà

.../joomla/components/com_myform

la prima parte del percorso solo tu puoi saperla perché dipende da dove hai installato php+apache in locale (se sei in locale) oppure è il percorso alla cartella pubblica sul tuo spazio web se stai provando su un host.

Ad esempio io in locale sotto Windows e Wamp ho:

C:\wamp\www\joomla\components\com_myform

Se non riesci a venire a capo di questo esempio prova con quello nella guida che trovi qui che è forse più completo.

Anonimo ha detto...

Complimenti, per l'ottima ed esauriente guida!
Buon lavoro,
Henry.

Anonimo ha detto...

Ho risolto il problema della cartella introvabile era una protezione di windows vista.
Grazie per la guida è davvero preziosissima.

Marco ha detto...

Dopo aver visto la guida al component MCV ufficiale di Joomla sono approdato alla tua. Anche se sono solo alla prima puntata la ho trovata molto esauriente e piena di spunti interessanti!
Sono nuovo del modello MCV e mentre nell'esempio del sito ufficiale anche la Vista entrava nel merito dei singoli campi, nella tua implementazione trovo una reale separazione tra vista e modello.
Grazie ancora!
Non vedo l'ora di gustarmi le prossime puntate!

Massimo ha detto...

Ti ringrazio dei complimenti, mi fa piacere che tu abbia trovato utile il post.

vincenzo ha detto...

complimentoni per la guida, la trovo davvero utile.

Ho cercato poi di fare un altro passettino, cioè di mettere i "radiobutton".

Ho inserito nella classe MyFormModelMyForm il seguente codice:
array('label'=>'Radio1', 'name'=>'myform[ck1]','id'=>'radio1', 'type'=>'radio', 'value'=>'radio1'),
array('label'=>'Radio2', 'name'=>'myform[ck1]','id'=>'radio2', 'type'=>'radio', 'value'=>'radio2'),

ho fatto le dovute modifiche anche a tutti gli altri file e tutto funziona correttamente.

L'unica cosa che non và è quando vado ad inserire la funzione ceck (modificando anche qui i campi per la verifica). L'errore è il seguente:
Call to a member function getForm() on a non-object ../com_myform\views\myform\view.html.php on line 12

come potrei risolvere? qualcuno ha già provato ad inserire radiobutton o altri tipi di imput come modulo?

Grazie mille
Vincenzo

Massimo ha detto...

Qualcuno ha provato modificare il form per inserire un campo data e la spiegazione su come fare è in questo post se non l'avessi vista. Prova a controllare dovrebbe servire anche al tuo caso.

Anonimo ha detto...

Ciao, io invece ho questo problema. Durante l'installazione mi viene segnalato che un altro componente utilizza componentes\com_myform. Devo eliminare la suddetta cartella ? Non vorrei fare pasticci. Cosa posso fare ? Complimenti per il lavoro fatto, la tua è una guida preziosa.

Massimo ha detto...

Il componente è creato passo-passo ogni post del tutorial contiene una propria versione di com_myform, probabilmente avrai installato una versione relativa ad un post precedente. Dovresti poterla disinstallare senza rimuovere manualmente la cartella.

Comunque visto che dici di aver paura di fare 'pasticci', spero che ti sia chiaro che questo è un componente di esempio da utilizzare per imparare a sviluppare. Preciso questo perché devi esserti messo in una situazione tale da non fare danni in caso di errori, installando il tutto in una versione locale o comunque di test di Joomla.

Anonimo ha detto...

Grazie Massimo. Ho fatto una ricerca più mirata. Il coponente non esisteva tra quelli installati. Allora mi son ricordato che avevo creato io una cartella di prova per seguire il corso. Volevo scriverci direttamente i file dentro, ma poi ho cambiato idea. E' bastata questa per non permettermi l'installazione, anche se era ancora vuota. L'ho cancellata e tutto è andato buon fine. Ovviamente provo in locale. Grazie ancora Piero

Posta un commento

Nota. Solo i membri di questo blog possono postare un commento.