Un exemple complet : auto
Faisons maintenant un grand pas vers plus de complexité. Nous voulons disposer d’une liste de véhicules d’occasion pouvant être mise à jour depuis la partie administrative. Il nous faut concevoir les éléments suivants :
- un nouveau composant public pour le Frontend ;
- un composant d'administration pour le Backend ;
- une table de données dédiée ;
- (facultatif) un module pour afficher les entrées sur le site Web ;
- (facultatif) un module de recherche pour étendre la recherche de Joomla! à vos nouveaux contenus.
Pour vous faire une idée de l’objectif que nous désirons atteindre, la fi gure suivante présente la liste sur le site. Vous pouvez immédiatement voir le résultat en installant le composant nommé com_auto.zip.
Vous devez voir apparaître sur le site une liste de véhicules avec une vue miniature. Si vous cliquez sur une miniature, une fenêtre apparaît avec une vue détaillée du véhicule (voir Figure 15.5). Notre liste concerne des types de véhicules, mais vous pouvez gérer des données très différentes. En général, une telle liste convient aux attentes des visiteurs. Nous ne les autorisons pas à modifier les données.
L’administrateur doit en revanche pouvoir ajouter, supprimer et modifier des enregistrements. Cette gestion des données comprend les opérations suivantes :
- création de nouveaux enregistrements ;
- modification des enregistrements existants ;
- suppressions des enregistrements existants.
Pour éviter de rendre l’exemple trop complexe, nous allons nous limiter à quatre champs. Deux champs contiendront du texte (pour le type de véhicule et le constructeur) et deux autres champs contiendront les références des fichiers des photos (petit et grand format). Vous comprendrez vite le principe de la programmation d’un composant dans Joomla! et vous aurez sans doute envie de réutiliser l’exemple avec une structure de données plus complexe. Le composant doit s’intégrer à la structure d’administration existante. L’interface de gestion doit offrir un aspect comme celui de la Figure 15.6. Il faut pouvoir réaliser les fonctions qui sont proposées par les boutons standard du haut de la fenêtre. Vous devez prévoir une barre d’outils pour l’affichage sous forme de liste et une autre pour le mode Édition d’un enregistrement. Vous devez publier et dépublier les enregistrements et profiter de la fonction de sélection multiple avec les cases à cocher à gauche des lignes dans la liste.
Figure 15.5 Exemple de composant spécifique sur le site Web.
Figure 15.6 Affichage de l’interface de gestion dans l’administration de Joomla!
Il faut également concevoir un formulaire pour le mode Modifi cation et un autre pour le mode Création d’enregistrement (voir Figure 15.7).
Nous décidons d’appeler ce composant com_auto. Pensez à installer le composant pour mieux suivre les explications. Vous pourrez éventuellement décompresser le paquetage dans un dossier de travail pour le modifier, ou le modifier directement dans son dossier d’implantation. Après chaque retouche, vous pouvez juger de son impact (pour parfois constater que cela ne fonctionne plus). Un exemple trop complexe devient vite incompréhensible. Voilà pourquoi j’ai cherché à maintenir les fichiers courts, en ne conservant que l’essentiel.
Figure 15.7 Exemple d’enregistrement en mode Édition dans l’administration de Joomla!
15.2.1 La table de données MySQL
Le composant se base sur une table MySQL dans laquelle sont stockés les enregistrements des véhicules. Cette table est créée automatiquement pendant l’installation. Les instructions SQL correspondantes sont stockées après l’installation dans le fichier nommé /administrator/com_auto/install.sql. Il existe par ailleurs un fichier uninstall.sql pour supprimer la table lorsque vous désinstallez le composant.
Vous pouvez visualiser cette table nommée jos_auto en naviguant sur le site local jusqu’à la racine puis dans l’administration PHP par l’adresse http://localhost/phpmyadmin. Vous pouvez accéder à la table jos_auto (voir Figure 15.8).
Le préfixe jos_ a été défini pendant l’installation de Joomla! dans la configuration. Le champ nommé published contient soit la valeur 1 (l’enregistrement est publié), soit la valeur 0 (non publié). Pour les deux photos, nous prévoyons un chemin d’accès que vous devrez sans doute adapter. En vous servant du libellé, vous devinerez où créer un sous-répertoire portant le nom du composant et contenant les images fournies sur le CD-ROM d’accompagnement.
15.2.2 La partie publique Frontend
Commençons par la liste des véhicules visibles par les visiteurs. Comme avec le premier composant, il nous faut plusieurs fichiers :
- /components/com_auto/auto.php ;
- /components/com_auto/controller.php ;
- /components/com_auto/views/auto/view.html.php ;
- /components/com_auto/views/auto/tmpl/default.php ;
- /components/com_auto/models/auto.php.
Figure 15.8 La table spécifique jos_auto dans MySQL.
Cette fois-ci, nous utilisons un modèle, ce qui est normal puisque nous allons gérer des données provenant d’une base de données.
Le point d’entrée (/components/com_auto/auto.php)
Il est normal d’avoir un point d’entrée. Il correspond au fichier /components/com_auto/auto.php. Ce fichier centralise les éléments puis délègue les différentes opérations (voir Listing 15.6).
<?php // Accès direct interdit defined(‘_JEXEC’) or die(‘Restricted access’); // Chargement du contrôleur primaire de Joomla! require_once (JPATH_COMPONENT.DS.’controller.php’); // Création d’un contrôleur $controller = new AutoController(); // Lecture de la tâche à réaliser $controller->execute(JRequest::getCmd(‘task’)); // Redirection depuis le contrôleur $controller->redirect(); ?>
Listing 15.6 : /components/com_auto/auto.php
Le code source est très proche de celui du composant com_hallo (vous voyez que le recyclage fonctionne !) (voir Listing 15.7).
Le contrôleur (/components/com_auto/controller.php)
Nous retrouvons les mêmes lignes que dans le composant com_hallo :
<?php
defined(‘_JEXEC’) or die();
jimport(‘joomla.application.component.controller’);
class AutoController extends JController{
function display(){
parent::display();
}
}
Listing 15.7 : /components/com_auto/controller.php
La vue (/components/com_auto/views/auto/view.html.php)
C’est ici que nous divergeons du précédant exemple. Il faut définir comment récupérer les données pour peupler notre liste (voir Listing 15.8).
<?php
jimport( ‘joomla.application.component.view’);
class AutoViewAuto extends JView{
function display($tpl = null){
$model = &$this->getModel();
$rows = $model->getAutoList();
$this->assignRef(‘rows’ , $rows);
parent::display($tpl);
}
}
?>
Listing 15.8 : /components/com_auto/views/auto/view.html.php
$model = &$this->getModel();
Nous créons une instance du modèle, c’est-à-dire un objet qui est stocké dans la variable appelée $model :
$rows = $model->getAutoList();
La méthode getAutoList() est appelée dans l’objet et renvoie en résultat un tableau de type Array appelé $rows (il contient les lignes ou enregistrements) :
$this->assignRef(‘rows’, $rows);
parent::display($tpl);
Les données qui en résultent sont récupérées puis transmises au template.
Le template (/components/com_auto/views/auto/tmpl/default.php)
Dans le template standard, les différentes lignes contenues dans le tableau $rows sont transmises une à une dans une boucle for (voir Listing 15.9).
<?php
defined(‘_JEXEC’) or die(‘Restricted access’);
?>
<script type="text/JavaScript">
function FensterOeffnen (Adresse) {
MeinFenster = window.open(Adresse, "Auto",
„width=400,height=300,left=100,top=200");
MeinFenster.focus();
}
</script>
<h1><?php echo "Liste de nos voitures"; ?></h1>
<ul>
<?
// Lecture des enregistrements vers un tableau Array
foreach ($this->rows as $row) { ?>
<li><?php echo $row->type; ?> <small><em>(<?php echo $row-
>constructeur; ?>)
</em></small><br>
<a href="<?php echo $row->photo_grande; ?>" onclick="FensterOeffnen
(this.href); return false"><img src=<?php echo $row->photo_mini; ?>>
</a>
</li>
<?php
}
?>
</ul> foreach ($this->rows as $row) { ?>
<li>
<?php echo $row->type; ?>
<?php echo $row->constructeur; ?>
<?php echo $row->photo_mini; ?>
</li>
<?php } ?>
Listing 15.9 : /components/com_auto/views/auto/tmpl/default.php
C’est la seule partie spécifique dans ce template. Les autres lignes concernent le formatage en HTML ou le code JavaScript pour ouvrir la fenêtre flottante. Vous pouvez enrichir ces portions du code source avec des effets visuels. Servez-vous d’outils appropriés comme Dreamweaver ou MooTools. Cette partie du formatage est devenue autonome dans Joomla!1.5, hormis la variable $rows.
Le Modèle (/components/com_auto/models/auto.php)
Nous allions oublier l’essentiel, le modèle ! Il faut expliquer comment accéder aux données (voir Listing 15.10).
<?php
defined(‘_JEXEC’) or die();
jimport(‘joomla.application.component.model’); class AutoModelAuto
extends JModel {
function _getAutoQuery( &$options ){
$db = JFactory::getDBO();
$id = @$options[‘id’];
$select = ‘a.*’;
$from = ‘#__auto AS a’;
$wheres[] = ‘a.published = 1’;
$query = "SELECT " . $select .
"\n FROM " . $from .
"\n WHERE " . implode( "\n AND ", $wheres );
return $query;
}
function getAutoList( $options=array() ){
$query = $this->_getAutoQuery( $options );
$result = $this->_getList( $query );
return @$result;
}
}
?>
Listing 15.10 : /components/com_auto/models/auto.php
Deux méthodes sont essentielles dans ce modèle. Tout d’abord, la méthode _getAutoQuery() qui se charge d’accéder aux données. C’est elle qui contient l’instruction SQL. L’autre méthode se nomme getAutolist(). Elle contrôle l’accès et récupère le résultat. Vous vous souvenez peut-être encore du contenu du fichier views.html.php. Il contenait la ligne suivante :
$rows = $model->getAutoList();
C’est de cette manière que la méthode accède à l’objet représentant le modèle puis récupère les données résultantes dans $rows. Dans la classe AutoModelAuto, ce renvoi des données est réalisé par la méthode getAutoList().
Conclusion
Nous sommes entrés dans une époque où il est normal de plonger dans le langage PHP et la programmation orientée objet. Pourtant, même si vous n’avez aucune connaissance des concepts de classe, de méthode et d’héritage, vous pourrez parvenir à créer des projets (mais vous serez quelque peu perdu). En vous laissant guider par l’approche MVC de Joomla!, vous comprenez concrètement comment ces différents concepts s’articulent. Si vous comparez par exemple le premier composant com_hallo à la partie de com_auto que nous venons de voir, force est de constater que 80 % du code ne change
pas (sauf le modèle bien sûr).
15.2.3 La partie administration de com_auto
L’affichage des données sur le site Web s’est avérée assez simple, mais leur gestion sera un peu plus complexe. Ici, nous devrons présenter les données aux yeux de l’administrateur, pour qu’il puisse les modifier, créer de nouveaux enregistrements, en supprimant et décider lesquels doivent être visibles, donc publiés. Il faut prévoir beaucoup plus de fonctions d’interactivité.
La table des composants
Dans Joomla!, tous les éléments des menus des composants sont définis sous forme d’enregistrements dans une table de la base de données qui porte le nom [préfixe]components. C’est également à cet endroit que vous trouverez les éléments de menu de tous les composants de la partie administrative. Il n’est donc pas étonnant que nous y trouvions le composant com_auto (voir Figure 15.9). Vous remarquerez qu’il y a également un objet graphique dans cette table. C’est celui qui doit apparaître à gauche du menu (‘js/ThemeOffice/component.png’). Tous les graphiques des menus se trouvent dans le sous-dossier [CheminJoomla]/includes/js/ThemeOffice (voir Figure 15.10).
Figure 15.9 La table components dans phpMyAdmin.
Figure 15.10 Le petit graphique à gauche de l’élément de menu.
Pour créer la partie administrative du composant, il faut encore plus de fichiers. Voici tous les fichiers en langage PHP du sous-dossier [CheminJoomla]/administration/components/com_auto/ :
- /administration/components/admin.auto.php ;
- /administration/components/controller.php ;
- /administration/components/controllers/auto.php ;
- /administration/components/com_auto/views/autos/view.html.php ;
- /administration/components/com_auto/views/autos/tmpl/default.php ;
- /administration/components/com_auto/views/auto/view.html.php ;
- /administration/components/com_auto/views/auto/tmpl/form.php ;
- /administration/components/com_auto/tables/auto.php ;
- /administration/components/com_auto/install.sql ;
- /administration/components/com_auto/uninstall.sql.
Le point d’entrée (/administration/components/com_auto/admin.auto.php)
La partie d’administration présente elle aussi un point d’entrée fonctionnel (voir Listing 15.11).
<?php defined(‘_JEXEC’) or die(‘Restricted access’); $controller = JRequest::getVar(‘controller’, ‘auto’); require_once(JPATH_ADMINISTRATOR.DS.’controllers’.DS.$controller.’.php’; $classname = ‘AutosController’.$controller; $controller = new $classname( ); $controller->execute( JRequest::getVar(‘task’)); $controller->redirect(); ?>
Listing 15.11 : /administration/components/com_auto/admin.auto.php
Maintenant que nous sommes devenus des spécialistes, tout cela ne nous pose aucun problème de compréhension. La seule nouveauté est éventuellement l’instruction conditionnelle if qui permet de chercher d’autres contrôleurs après le contrôleur primaire.
Le Contrôleur (/administration/components/com_auto/controller.php)
Le contrôleur primaire ne nous apporte rien de neuf (voir Listing 15.12).
<?php
jimport(‘joomla.application.component.controller’);
class AutosController extends JController{
function display(){
parent::display();
}
}?>
Listing 15.12 : /administration/components/com_auto/controller.php
Un autre contrôleur (/administration/components/com_auto/controllers/auto.php) Les choses deviennent plus spécifiques maintenant. Nous devons définir un autre contrôleur que voici (voir Listing 15.13) :
<?php
defined(‘_JEXEC’) or die();
class AutosControllerAuto extends AutosController{
function __construct(){
parent::__construct();
$this->registerTask( ‘add’, ‘edit’ );
$this->registerTask( ‘unpublish’, ‘publish’);
}
function edit() {
JRequest::setVar( ‘view’, ‘auto’ );
JRequest::setVar( ‘layout’, ‘form’ );
JRequest::setVar(‘hidemainmenu’, 1);
parent::display();
}
function save() {
$model = $this->getModel(‘auto’);
if ($model->store($post)) {
$msg = JText::_( ‘Auto sauvegarde OK !’ );
} else {
$msg = JText::_( ‘Erreur de sauvegarde de Auto’ );
}
$link = ‘index.php?option=com_auto’;
$this->setRedirect($link, $msg);
}
function remove(){
$model = $this->getModel(‘auto’);
if(!$model->delete()) {
$msg = JText::_( ‘Erreur: Une ou plusieurs autos non supprimees’’ );
} else {
$msg = JText::_( ‘Auto(s) supprimees’ );
}
$this->setRedirect( ‘index.php?option=com_auto’, $msg );
}
function publish(){
$this->setRedirect( ‘index.php?option=com_auto’ );
$db =& JFactory::getDBO();
$user =& JFactory::getUser();
$cid = JRequest::getVar( ‘cid’, array(), ‘post’, ‘array’ );
$task = JRequest::getCmd( ‘task’ );
$publish = ($task == ‘publish’);
$n = count( $cid );
if (empty( $cid )) {
return JError::raiseWarning( 500, JText::_( ‘Pas de selection’ ) );
}
JArrayHelper::toInteger( $cid );
$cids = implode( ‘,’, $cid );
$query = ‘UPDATE #__auto’
. ‘ SET published = ‘ . (int) $publish
. ‘ WHERE id IN ( ‘. $cids .’ )’
;
$db->setQuery( $query );
if (!$db->query()) {
return JError::raiseWarning( 500, $row->getError() );
}
$this->setMessage( JText::sprintf( $publish ? ‘Publies’ : ‘Non publiés’,
$n ) );
}
function cancel(){
$msg = JText::_( ‘Operation annulee’ );
$this->setRedirect( ‘index.php?option=com_auto’, $msg );
}
}
?>
Listing 15.13 : /administration/components/com_auto/controllers/auto.php
Ce contrôleur définit toute une série de méthodes : edit, save, remove, publish et cancel. Le modèle est instancié dans ces méthodes. Des appels sont effectués dans le modèle, par exemple à la méthode de stockage store. Les deux classes statiques nommées JText et JError permettent de renseigner l’utilisateur sur la réussite ou non de l’opération (voir Figure 15.11).
Figure 15.11 Affichage d’un message par la classe statique JText.
La vue Liste (/administration/components/com_auto/views/autos/view.html.php)
Cette définition de vue est un peu plus complexe car il faut insérer une barre d’outils spécifique (voir Listing 15.14).
<?php
defined(‘_JEXEC’) or die();
jimport( ‘joomla.application.component.view’ );
class AutosViewAutos extends JView{
function display($tpl = null){
JToolBarHelper::title( JText::_( ‘Auto Manager’ ), ‘generic.png’ );
JToolBarHelper::publishList();
JToolBarHelper::unpublishList();
JToolBarHelper::deleteList();
JToolBarHelper::editListX();
JToolBarHelper::addNewX();
$items = & $this->get( ‘Data’);
$this->assignRef(‘items’, $items);
parent::display($tpl);
}
}
Listing 15.14 : /administration/components/com_auto/views/autos/view.html.php
Figure 15.12 Aperçu de la barre d’outils dans la liste des autos.
La classe nommée JToolbarHelper se charge de l’affichage (voir Figure 15.12).
La liste du template (/administration/components/com_auto/views/autos/tmpl/default.php)
Il faut bien sûr assurer une mise en forme de la liste. Nous procédons donc à la préparation des données du template standard (voir Listing 15.15).
<?php defined(‘_JEXEC’) or die(‘Restricted access’); ?>
<form action="index.php" method="post" name="adminForm">
<div id="editcell">
<table class="adminlist"><thead><tr>
<th width="5"><?php echo JText::_( ‘NUM’ ); ?></th>
<th width="20"> <input type="checkbox" name="toggle" value=""
onclick="checkAll(<?php echo count( $this->items ); ?>);" /></th>
<th class="title"><?php echo JHTML::_(‘grid.sort’, ‘Auto’, ‘a.text’,
@$lists[‘order_Dir’], @$this->lists[‘order’] ); ?></th>
<th width="5%" align="center"><?php echo JHTML::_(‘grid.sort’, ‘Published’,
‘a.published’, @$this->lists[‘order_Dir’], @$this->lists[‘order’] ); ?>
</th>
<th width="1%" nowrap="nowrap"><?php echo JHTML::_(‘grid.sort’, ‘ID’, ‘a.id’,
@$this->lists[‘order_Dir’], @$this->lists[‘order’] ); ?></th>
</tr></thead>
<?php
$k = 0;
for ($i=0, $n=count( $this->items ); $i < $n; $i++){
$row = &$this->items[$i];
$published = JHTML::_(‘grid.published’, $row, $i );
$link = JRoute::_( ‘index.php?option=com_auto&controller=auto&task=
edit&cid[]=’.$row->id );
?>
<tr class="<?php echo "row$k"; ?>">
<td></td>
<td></td>
<td><a href="<?php echo $link; ?>"><?php echo $row->type; ?></a></td>
<td align="center"><?php echo $published;?></td>
<td align="center"><?php echo $row->id; ?></td>
</tr>
<?php
$k = 1 - $k;
}
?>
</table></div>
<input type="hidden" name="option" value="com_auto" />
<input type="hidden" name="task" value="" />
<input type="hidden" name="boxchecked" value="0" />
<input type="hidden" name="controller" value="auto" />
</form>
Listing 15.15 : /administration/components/com_auto/views/autos/tmpl/default.php
Le template est constitué d’un code HTML assez simple dans un formulaire. C’est ce code qui se charge de l’affichage de la table (voir Figure 15.13).
Figure 15.13 La table du composant auto.
La vue formulaire (/administration/components/com_auto/views/auto/view.html.php)
Il faut également prévoir un affichage sous forme de fiche pour chaque auto (un seul enregistrement). Observez bien le nom du sous-dossier. Nous sommes à présent dans le sous-dossier auto, alors que la liste se trouve dans le sous-dossier autos au pluriel (Listing 15.16).
<?php
defined(‘_JEXEC’) or die();
jimport( ‘joomla.application.component.view’ );
class AutosViewAuto extends JView{
function display($tpl = null){
$auto =& $this->get(‘Data’);
$isNew = ($auto->id < 1);
$text = $isNew ? JText::_( ‘New’ ) : JText::_( ‘Edit’ );
JToolBarHelper::title( JText::_( ‘Auto’ ).’: <small>[ ‘ . $text.’ ]
</small>’ );
JToolBarHelper::save();
if ($isNew) {
JToolBarHelper::cancel();
} else {
JToolBarHelper::cancel( ‘cancel’, ‘Close’ );
}
$this->assignRef(‘auto’, $auto);
parent::display($tpl);
}
}
Listing 15.16 : /administration/components/com_auto/views/auto/view.html.php
Nous procédons à la construction de la barre d’outils pour la vue fiche (voir Figure 15.14). Dans cet affichage, nous pouvons insérer des données et modifier un enregistrement existant. La variable nommée $isNew permet de décider entre les deux contextes.
Figure 15.14 La barre d’outils du formulaire du mode fiche.
Formulaire du template (/administration/components/com_auto/views/auto/tmpl/form.php)
Ce template standard permet de construire le formulaire de la vue fiche individuelle (voir Listing 15.17).
<?php defined(‘_JEXEC’) or die(‘Restricted access’); ?>
<script language="JavaScript" type="text/JavaScript">
function submitbutton(pressbutton) {
var form = document.adminForm;
if (pressbutton == ‘cancel’) {
submitform( pressbutton );
return;
}
// do field validation
if (form.text.value == "") {
alert( "<?php echo JText::_( ‘Texte obligatoire’, true ); ?>" );
} else {
submitform( pressbutton );
}
}
</script>
<form action="index.php" method="post" name="adminForm"
id="adminForm">
<div>
<fieldset class="adminform">
<legend><?php echo JText::_( ‘Details’ ); ?></legend>
<table class="admintable">
<tr>
<td width="110" class="key">
<label for="title">
<?php echo JText::_( ‘Type’ ); ?>:
</label>
</td>
<td>
<input class="inputbox" type="text" name="type" id="type"
size="60" value="<?php echo $this->auto->type; ?>" />
</td>
</tr>
<tr>
<td width="110" class="key">
<label for="alias">
<?php echo JText::_( ‘Constructeur’ ); ?>:
</label>
</td>
<td>
<input class="inputbox" type="text" name="constructeur"
id="constructeur" size="60" value="<?php echo $this->auto->
constructeur; ?>" />
</td>
</tr>
<tr>
<td class="key">
<label for="lag">
<?php echo JText::_( ‘Photo mini (120px)’ ); ?>:
</label>
</td>
<td>
<input class="inputbox" type="text" name="photo_mini" id="photo_
mini" size="60" value="<?php echo $this->auto->photo_mini; ?>" />
<?php echo JText::_( ‘(Veuillez indiquer un lien avec http://
vers un fichier de photo)’ ); ?>
</td>
</tr>
<tr>
<td colspan="2">
<?php if ($this->auto->photo_mini){?>
<img src="<?php echo $this->auto->photo_mini; ?>">
<?php } ?>
</td>
</tr>
<tr>
<td class="key">
<label for="lag">
<?php echo JText::_( ‘Photo grande (350px)’ ); ?>:
</label>
</td>
<td>
<input class="inputbox" type="text" name="photo_grande" id="photo_
grande" size="60" value="<?php echo $this->auto->photo_grande; ?>" />
<?php echo JText::_( ‘(Veuillez indiquer un lien avec http://
vers un fichier de photo)’ ); ?>
</td>
</tr>
<tr>
<td colspan="2">
<?php if ($this->auto->photo_grande){?>
<img src="<?php echo $this->auto->photo_grande; ?>">
<?php } ?>
</td>
</tr>
<tr>
<td width="120" class="key">
<?php echo JText::_( ‘Published’ ); ?>:
</td>
<td>
<?php echo JHTML::_( ‘select.booleanlist’, ‘published’, ‘class=
"inputbox"’, $this->auto->published ); ?>
</td>
</tr>
</table>
</fieldset>
</div>
<div class="clr"></div>
<div class="clr"></div> <input type="hidden" name="option" value="com_auto" />
<input type="hidden" name="id" value="<?php echo $this->auto->id; ?>" />
<input type="hidden" name="task" value="" />
<input type="hidden" name="controller" value="auto" />
</form>
Listing 15.17 : /administration/components/com_auto/views/auto/tmpl/form.php
Nous trouvons à nouveau du code HTML pur ainsi que des variables PHP ($this->auto->id) et des appels de classes statiques (JText). La Figure 15.15 montre le résultat affiché.
Figure 15.15 Formulaire de modification d’un enregistrement de la table.
La table auto (/administration/components/com_auto/tables/auto.php)
Il nous reste à définir la classe de la table pour que le modèle sache quelles données il doit manipuler. La classe nommée JTable simplifi e tous les accès aux données. C’est une classe abstraite (autrement dit une interface). Les classes qui en dérivent peuvent exploiter la structure dont elles héritent via leurs méthodes. Le nom de la table et la clé primaire (l’index) sont définis au niveau du constructeur de la classe (voir Listing 15.18).
<?php
// Accès direct interdit
defined(‘_JEXEC’) or die(‘Restricted access’); class TableAuto extends
JTable {
/** @var int Primary key */
var $id = 0;
/** @var string */
var $type = ‘’;
/** @var string */
var $constructeur = ‘’;
/** @var string */
var $photo_mini = ‘’;
/** @var string */
var $photo_grande = ‘’;
/** @var string */
var $published = 0;
/** @var int */ /**
* Constructor
*
* @param object Database connector object
*/
function TableAuto(& $db) {
parent::__construct(‘#__auto’, ‘id’, $db);
}
}
?>
Listing 15.18 : /administration/components/com_auto/tables/auto.php
Installation (/administration/components/com_auto/install.sql) et désinstallation (idem/uninstall.sql)
Les deux procédures d’installation et de désinstallation supposent pour Joomla! de savoir créer la table du composant et la supprimer. Deux fichiers contenant des instructions SQL sont conçus à cet effet (voir Listings 15.19 et 15.20).
DROP TABLE IF EXISTS `#__auto`;
CREATE TABLE `#__auto` (
`id` int(11) NOT NULL auto_increment,
`type` text character set utf8 NOT NULL,
`constructeur` varchar(100) character set utf8 NOT NULL,
`photo_grande` varchar(200) character set utf8 NOT NULL,
`photo_mini` varchar(200) character set utf8 NOT NULL,
`published` tinyint(1) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=5 ;
INSERT INTO `#__auto` (`id`, `type`, `constructeur`, `photo_grande`,
`photo_mini`, `published`) VALUES
(2, ‘Smart fortwo’, ‘Smart’, ‘http://localhost/joomla150/images/stories/
com_auto/smart_grande.jpg’, ‘http://localhost/joomla150/images/stories/
com_auto/smart_mini.jpg’, 1),
(4, ‘Roadster’, ‘Smart’, ‘http://localhost/joomla150/images/stories/com_
auto/roadster_grande.jpg’, ‘http://localhost/joomla150/images/stories/
com_auto/roadster_mini.jpg’, 1); Listing 15.20 : administration/
components/com_auto/uninstall.sql
DROP TABLE IF EXISTS `#__auto`;
Listing 15.19 : /administration/components/com_auto/install.sql
15.2.4 Test du composant
Après avoir étudié tous ces fichiers sources, vous pouvez tester le composant et vérifier que vous pouvez gérer entièrement la table de données par l’administration Joomla!. Essayez de créer des enregistrements, d’en effacer, d’en modifier et d’en publier. Vous pouvez agir sur tout un groupe en sélectionnant plusieurs enregistrements par leur case à cocher.
15.2.5 Création d’un paquetage d’installation
Pour concevoir un paquetage exploitable par l’installateur, il nous reste à écrire le fichier XML contenant les métadonnées.
administrator\components\com_autoauto.xml
C’est dans ce fichier que vous décrivez les éléments qui constituent le nouveau composant. L’installateur va se servir de ces descriptions. Le fichier doit contenir tous les noms de fichiers enchâssés dans des balises XML. C’est grâce à cela que l’installateur de Joomla! va savoir créer les sousdossiers, y copier les fichiers et enfin créer la table de données (voir Listing 15.21).
<?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>Auto</name> <creationDate>November 2007</creationDate> <author>Hagen Graf</author> <authorEmail>hagen.graf@gmail.com</authorEmail> <authorUrl>http://www.cocoate.com</authorUrl> <copyright>All rights reserved</copyright> <license>GNU/GPL</license> <version>Component Version String</version> <description>Description du composant ... </description> <files folder="site"> <filename>index.html</filename> <filename>auto.php</filename> <filename>controller.php</filename> <filename>views/index.html</filename> <filename>views/auto/index.html</filename> <filename>views/auto/view.html.php</filename> <filename>views/auto/tmpl/index.html</filename> <filename>views/auto/tmpl/default.php</filename> <filename>models/auto.php</filename> </files> <install> <sql> <file charset="utf8" driver="mysql">install.sql</file> </sql> </install> <uninstall> <sql> <file charset="utf8" driver="mysql">uninstall.sql</file> </sql> </uninstall> <administration> <menu>Livre Joomla! 1.5 : Auto</menu> <files folder="admin"> <filename>index.html</filename> <filename>admin.auto.php</filename> <filename>controller.php</filename> <filename>controllers/auto.php</filename> <filename>controllers/index.html</filename> <filename>models/auto.php</filename> <filename>models/autos.php</filename> <filename>models/index.html</filename> <filename>views/autos/view.html.php</filename> <filename>views/autos/index.html</filename> <filename>views/autos/tmpl/default.php</filename> <filename>views/autos/tmpl/index.html</filename> <filename>views/auto/view.html.php</filename> <filename>views/auto/tmpl/form.php</filename> <filename>views/auto/index.html</filename> <filename>views/auto/tmpl/index.html</filename> <filename>tables/auto.php</filename> <filename>tables/index.html</filename> <filename>install.sql</filename> <filename>uninstall.sql</filename> </files> </administration> </install>
Listing 15.21 : administrator\components\com_autoauto.xml
Vous savez déjà créer le paquetage en rassemblant tous les fichiers dans un fichier .zip qui porte le nom du composant. Dans notre cas le paquetage s’appelle com_auto.zip. Les fichiers de la partie Frontend sont dans le sous-dossier de premier niveau site et ceux de l’administration dans le sousdossier admin (voir Figure 15.16).
Figure 15.16 Les fichiers du composant com_auto prêt à être empaquetés.
Vous pouvez maintenant procéder à l’installation du fichier .zip dans Joomla! et le diffuser à d’autres utilisateurs. Pensez toujours à désinstaller la version précédente du composant avant de le réinstaller. Vous savez comment faire : EXTENSIONS > INSTALLER/DÉSINSTALLER, sélection du composant et cliquez sur le bouton DÉSINSTALLER.
Faisons maintenant un grand pas vers plus de complexité. Nous voulons disposer d’une liste de véhicules d’occasion pouvant être mise à jour depuis la partie administrative. Il nous faut concevoir les éléments suivants :un nouveau composant public pour le Frontend ;un composant d'administration pour le Backend ;une table de données dédiée ;(facultatif) un module pour afficher les entrées sur le site Web ;(facultatif) un module de recherche pour étendre la recherche de Joomla! à vos nouveaux contenus.Pour vous faire une idée de l’objectif que nous désirons atteindre, la fi gure suivante présente la liste sur le site. Vous pouvez immédiatement voir le résultat en installant le composant nommé com_auto.zip.Vous devez voir apparaître sur le site une liste de véhicules avec une vue miniature. Si vous cliquez sur une miniature, une fenêtre apparaît avec une vue détaillée du véhicule (voir Figure 15.5). Notre liste concerne des types de véhicules, mais vous pouvez gérer des données très différentes. En général, une telle liste convient aux attentes des visiteurs. Nous ne les autorisons pas à modifier les données.L’administrateur doit en revanche pouvoir ajouter, supprimer et modifier des enregistrements. Cette gestion des données comprend les opérations suivantes :création de nouveaux enregistrements ;modification des enregistrements existants ;suppressions des enregistrements existants.Pour éviter de rendre l’exemple trop complexe, nous allons nous limiter à quatre champs. Deux champs contiendront du texte (pour le type de véhicule et le constructeur) et deux autres champs contiendront les références des fichiers des photos (petit et grand format). Vous comprendrez vite le principe de la programmation d’un composant dans Joomla! et vous aurez sans doute envie de réutiliser l’exemple avec une structure de données plus complexe. Le composant doit s’intégrer à la structure d’administration existante. L’interface de gestion doit offrir un aspect comme celui de la Figure 15.6. Il faut pouvoir réaliser les fonctions qui sont proposées par les boutons standard du haut de la fenêtre. Vous devez prévoir une barre d’outils pour l’affichage sous forme de liste et une autre pour le mode Édition d’un enregistrement. Vous devez publier et dépublier les enregistrements et profiter de la fonction de sélection multiple avec les cases à cocher à gauche des lignes dans la liste.Figure 15.5 Exemple de composant spécifique sur le site Web.Figure 15.6 Affichage de l’interface de gestion dans l’administration de Joomla!Il faut également concevoir un formulaire pour le mode Modifi cation et un autre pour le mode Création d’enregistrement (voir Figure 15.7).Nous décidons d’appeler ce composant com_auto. Pensez à installer le composant pour mieux suivre les explications. Vous pourrez éventuellement décompresser le paquetage dans un dossier de travail pour le modifier, ou le modifier directement dans son dossier d’implantation. Après chaque retouche, vous pouvez juger de son impact (pour parfois constater que cela ne fonctionne plus). Un exemple trop complexe devient vite incompréhensible. Voilà pourquoi j’ai cherché à maintenir les fichiers courts, en ne conservant que l’essentiel.Figure 15.7 Exemple d’enregistrement en mode Édition dans l’administration de Joomla!15.2.1 La table de données MySQLLe composant se base sur une table MySQL dans laquelle sont stockés les enregistrements des véhicules. Cette table est créée automatiquement pendant l’installation. Les instructions SQL correspondantes sont stockées après l’installation dans le fichier nommé /administrator/com_auto/install.sql. Il existe par ailleurs un fichier uninstall.sql pour supprimer la table lorsque vous désinstallez le composant.Vous pouvez visualiser cette table nommée jos_auto en naviguant sur le site local jusqu’à la racine puis dans l’administration PHP par l’adresse http://localhost/phpmyadmin. Vous pouvez accéder à la table jos_auto (voir Figure 15.8).Le préfixe jos_ a été défini pendant l’installation de Joomla! dans la configuration. Le champ nommé published contient soit la valeur 1 (l’enregistrement est publié), soit la valeur 0 (non publié). Pour les deux photos, nous prévoyons un chemin d’accès que vous devrez sans doute adapter. En vous servant du libellé, vous devinerez où créer un sous-répertoire portant le nom du composant et contenant les images fournies sur le CD-ROM d’accompagnement.15.2.2 La partie publique FrontendCommençons par la liste des véhicules visibles par les visiteurs. Comme avec le premier composant, il nous faut plusieurs fichiers :/components/com_auto/auto.php ;/components/com_auto/controller.php ;/components/com_auto/views/auto/view.html.php ;/components/com_auto/views/auto/tmpl/default.php ;/components/com_auto/models/auto.php.Figure 15.8 La table spécifique jos_auto dans MySQL.Cette fois-ci, nous utilisons un modèle, ce qui est normal puisque nous allons gérer des données provenant d’une base de données.Le point d’entrée (/components/com_auto/auto.php)Il est normal d’avoir un point d’entrée. Il correspond au fichier /components/com_auto/auto.php. Ce fichier centralise les éléments puis délègue les différentes opérations (voir Listing 15.6).<?php// Accès direct interditdefined(‘_JEXEC’) or die(‘Restricted access’);// Chargement du contrôleur primaire de Joomla!require_once (JPATH_COMPONENT.DS.’controller.php’);// Création d’un contrôleur$controller = new AutoController();// Lecture de la tâche à réaliser$controller->execute(JRequest::getCmd(‘task’));// Redirection depuis le contrôleur$controller->redirect();?>Listing 15.6 : /components/com_auto/auto.phpLe code source est très proche de celui du composant com_hallo (vous voyez que le recyclage fonctionne !) (voir Listing 15.7).Le contrôleur (/components/com_auto/controller.php)Nous retrouvons les mêmes lignes que dans le composant com_hallo :<?phpdefined(‘_JEXEC’) or die();jimport(‘joomla.application.component.controller’);class AutoController extends JController{ function display(){ parent::display(); }}Listing 15.7 : /components/com_auto/controller.phpLa vue (/components/com_auto/views/auto/view.html.php)C’est ici que nous divergeons du précédant exemple. Il faut définir comment récupérer les données pour peupler notre liste (voir Listing 15.8).<?phpjimport( ‘joomla.application.component.view’); class AutoViewAuto extends JView{ function display($tpl = null){ $model = &$this->getModel(); $rows = $model->getAutoList(); $this->assignRef(‘rows’ , $rows); parent::display($tpl); } }?>Listing 15.8 : /components/com_auto/views/auto/view.html.php$model = &$this->getModel();Nous créons une instance du modèle, c’est-à-dire un objet qui est stocké dans la variable appelée $model :$rows = $model->getAutoList();La méthode getAutoList() est appelée dans l’objet et renvoie en résultat un tableau de type Array appelé $rows (il contient les lignes ou enregistrements) :$this->assignRef(‘rows’, $rows);parent::display($tpl);Les données qui en résultent sont récupérées puis transmises au template.Le template (/components/com_auto/views/auto/tmpl/default.php)Dans le template standard, les différentes lignes contenues dans le tableau $rows sont transmises une à une dans une boucle for (voir Listing 15.9).<?phpdefined(‘_JEXEC’) or die(‘Restricted access’);?><script type="text/JavaScript"> function FensterOeffnen (Adresse) { MeinFenster = window.open(Adresse, "Auto", „width=400,height=300,left=100,top=200"); MeinFenster.focus();}</script><h1><?php echo "Liste de nos voitures"; ?></h1><ul><? // Lecture des enregistrements vers un tableau Array foreach ($this->rows as $row) { ?><li><?php echo $row->type; ?> <small><em>(<?php echo $row- >constructeur; ?>) </em></small><br> <a href="<?php echo $row->photo_grande; ?>" onclick="FensterOeffnen (this.href); return false"><img src=<?php echo $row->photo_mini; ?>> </a> </li> <?php } ?> </ul> foreach ($this->rows as $row) { ?> <li> <?php echo $row->type; ?> <?php echo $row->constructeur; ?> <?php echo $row->photo_mini; ?> </li> <?php } ?>Listing 15.9 : /components/com_auto/views/auto/tmpl/default.phpC’est la seule partie spécifique dans ce template. Les autres lignes concernent le formatage en HTML ou le code JavaScript pour ouvrir la fenêtre flottante. Vous pouvez enrichir ces portions du code source avec des effets visuels. Servez-vous d’outils appropriés comme Dreamweaver ou MooTools. Cette partie du formatage est devenue autonome dans Joomla!1.5, hormis la variable $rows.Le Modèle (/components/com_auto/models/auto.php)Nous allions oublier l’essentiel, le modèle ! Il faut expliquer comment accéder aux données (voir Listing 15.10).<?phpdefined(‘_JEXEC’) or die();jimport(‘joomla.application.component.model’); class AutoModelAutoextends JModel { function _getAutoQuery( &$options ){ $db = JFactory::getDBO(); $id = @$options[‘id’]; $select = ‘a.*’; $from = ‘#__auto AS a’; $wheres[] = ‘a.published = 1’; $query = "SELECT " . $select . "\n FROM " . $from . "\n WHERE " . implode( "\n AND ", $wheres ); return $query; } function getAutoList( $options=array() ){ $query = $this->_getAutoQuery( $options ); $result = $this->_getList( $query ); return @$result; }}?>Listing 15.10 : /components/com_auto/models/auto.phpDeux méthodes sont essentielles dans ce modèle. Tout d’abord, la méthode _getAutoQuery() qui se charge d’accéder aux données. C’est elle qui contient l’instruction SQL. L’autre méthode se nomme getAutolist(). Elle contrôle l’accès et récupère le résultat. Vous vous souvenez peut-être encore du contenu du fichier views.html.php. Il contenait la ligne suivante :$rows = $model->getAutoList();C’est de cette manière que la méthode accède à l’objet représentant le modèle puis récupère les données résultantes dans $rows. Dans la classe AutoModelAuto, ce renvoi des données est réalisé par la méthode getAutoList().ConclusionNous sommes entrés dans une époque où il est normal de plonger dans le langage PHP et la programmation orientée objet. Pourtant, même si vous n’avez aucune connaissance des concepts de classe, de méthode et d’héritage, vous pourrez parvenir à créer des projets (mais vous serez quelque peu perdu). En vous laissant guider par l’approche MVC de Joomla!, vous comprenez concrètement comment ces différents concepts s’articulent. Si vous comparez par exemple le premier composant com_hallo à la partie de com_auto que nous venons de voir, force est de constater que 80 % du code ne changepas (sauf le modèle bien sûr).15.2.3 La partie administration de com_autoL’affichage des données sur le site Web s’est avérée assez simple, mais leur gestion sera un peu plus complexe. Ici, nous devrons présenter les données aux yeux de l’administrateur, pour qu’il puisse les modifier, créer de nouveaux enregistrements, en supprimant et décider lesquels doivent être visibles, donc publiés. Il faut prévoir beaucoup plus de fonctions d’interactivité.La table des composantsDans Joomla!, tous les éléments des menus des composants sont définis sous forme d’enregistrements dans une table de la base de données qui porte le nom [préfixe]components. C’est également à cet endroit que vous trouverez les éléments de menu de tous les composants de la partie administrative. Il n’est donc pas étonnant que nous y trouvions le composant com_auto (voir Figure 15.9). Vous remarquerez qu’il y a également un objet graphique dans cette table. C’est celui qui doit apparaître à gauche du menu (‘js/ThemeOffice/component.png’). Tous les graphiques des menus se trouvent dans le sous-dossier [CheminJoomla]/includes/js/ThemeOffice (voir Figure 15.10).Figure 15.9 La table components dans phpMyAdmin.Figure 15.10 Le petit graphique à gauche de l’élément de menu.Pour créer la partie administrative du composant, il faut encore plus de fichiers. Voici tous les fichiers en langage PHP du sous-dossier [CheminJoomla]/administration/components/com_auto/ :/administration/components/admin.auto.php ;/administration/components/controller.php ;/administration/components/controllers/auto.php ;/administration/components/com_auto/views/autos/view.html.php ;/administration/components/com_auto/views/autos/tmpl/default.php ;/administration/components/com_auto/views/auto/view.html.php ;/administration/components/com_auto/views/auto/tmpl/form.php ;/administration/components/com_auto/tables/auto.php ;/administration/components/com_auto/install.sql ;/administration/components/com_auto/uninstall.sql.Le point d’entrée (/administration/components/com_auto/admin.auto.php)La partie d’administration présente elle aussi un point d’entrée fonctionnel (voir Listing 15.11).<?phpdefined(‘_JEXEC’) or die(‘Restricted access’);$controller = JRequest::getVar(‘controller’, ‘auto’);require_once(JPATH_ADMINISTRATOR.DS.’controllers’.DS.$controller.’.php’;$classname = ‘AutosController’.$controller;$controller = new $classname( );$controller->execute( JRequest::getVar(‘task’));$controller->redirect();?>Listing 15.11 : /administration/components/com_auto/admin.auto.phpMaintenant que nous sommes devenus des spécialistes, tout cela ne nous pose aucun problème de compréhension. La seule nouveauté est éventuellement l’instruction conditionnelle if qui permet de chercher d’autres contrôleurs après le contrôleur primaire.Le Contrôleur (/administration/components/com_auto/controller.php)Le contrôleur primaire ne nous apporte rien de neuf (voir Listing 15.12).<?phpjimport(‘joomla.application.component.controller’);class AutosController extends JController{ function display(){ parent::display(); }}?>Listing 15.12 : /administration/components/com_auto/controller.phpUn autre contrôleur (/administration/components/com_auto/controllers/auto.php) Les choses deviennent plus spécifiques maintenant. Nous devons définir un autre contrôleur que voici (voir Listing 15.13) :<?phpdefined(‘_JEXEC’) or die();class AutosControllerAuto extends AutosController{function __construct(){ parent::__construct(); $this->registerTask( ‘add’, ‘edit’ ); $this->registerTask( ‘unpublish’, ‘publish’);}function edit() { JRequest::setVar( ‘view’, ‘auto’ ); JRequest::setVar( ‘layout’, ‘form’ ); JRequest::setVar(‘hidemainmenu’, 1); parent::display();}function save() { $model = $this->getModel(‘auto’); if ($model->store($post)) { $msg = JText::_( ‘Auto sauvegarde OK !’ ); } else { $msg = JText::_( ‘Erreur de sauvegarde de Auto’ ); } $link = ‘index.php?option=com_auto’; $this->setRedirect($link, $msg);} function remove(){ $model = $this->getModel(‘auto’); if(!$model->delete()) { $msg = JText::_( ‘Erreur: Une ou plusieurs autos non supprimees’’ ); } else { $msg = JText::_( ‘Auto(s) supprimees’ ); } $this->setRedirect( ‘index.php?option=com_auto’, $msg );}function publish(){ $this->setRedirect( ‘index.php?option=com_auto’ ); $db =& JFactory::getDBO(); $user =& JFactory::getUser(); $cid = JRequest::getVar( ‘cid’, array(), ‘post’, ‘array’ ); $task = JRequest::getCmd( ‘task’ ); $publish = ($task == ‘publish’); $n = count( $cid ); if (empty( $cid )) { return JError::raiseWarning( 500, JText::_( ‘Pas de selection’ ) ); } JArrayHelper::toInteger( $cid ); $cids = implode( ‘,’, $cid ); $query = ‘UPDATE #__auto’ . ‘ SET published = ‘ . (int) $publish . ‘ WHERE id IN ( ‘. $cids .’ )’ ; $db->setQuery( $query ); if (!$db->query()) { return JError::raiseWarning( 500, $row->getError() ); } $this->setMessage( JText::sprintf( $publish ? ‘Publies’ : ‘Non publiés’, $n ) );}function cancel(){ $msg = JText::_( ‘Operation annulee’ ); $this->setRedirect( ‘index.php?option=com_auto’, $msg );}} ?>Listing 15.13 : /administration/components/com_auto/controllers/auto.phpCe contrôleur définit toute une série de méthodes : edit, save, remove, publish et cancel. Le modèle est instancié dans ces méthodes. Des appels sont effectués dans le modèle, par exemple à la méthode de stockage store. Les deux classes statiques nommées JText et JError permettent de renseigner l’utilisateur sur la réussite ou non de l’opération (voir Figure 15.11).Figure 15.11 Affichage d’un message par la classe statique JText.La vue Liste (/administration/components/com_auto/views/autos/view.html.php)Cette définition de vue est un peu plus complexe car il faut insérer une barre d’outils spécifique (voir Listing 15.14).<?phpdefined(‘_JEXEC’) or die();jimport( ‘joomla.application.component.view’ );class AutosViewAutos extends JView{ function display($tpl = null){ JToolBarHelper::title( JText::_( ‘Auto Manager’ ), ‘generic.png’ ); JToolBarHelper::publishList(); JToolBarHelper::unpublishList(); JToolBarHelper::deleteList(); JToolBarHelper::editListX(); JToolBarHelper::addNewX(); $items = & $this->get( ‘Data’); $this->assignRef(‘items’, $items); parent::display($tpl); }}Listing 15.14 : /administration/components/com_auto/views/autos/view.html.phpFigure 15.12 Aperçu de la barre d’outils dans la liste des autos.La classe nommée JToolbarHelper se charge de l’affichage (voir Figure 15.12).La liste du template (/administration/components/com_auto/views/autos/tmpl/default.php)Il faut bien sûr assurer une mise en forme de la liste. Nous procédons donc à la préparation des données du template standard (voir Listing 15.15).<?php defined(‘_JEXEC’) or die(‘Restricted access’); ?><form action="index.php" method="post" name="adminForm"><div id="editcell"><table class="adminlist"><thead><tr><th width="5"><?php echo JText::_( ‘NUM’ ); ?></th><th width="20"> <input type="checkbox" name="toggle" value=""onclick="checkAll(<?php echo count( $this->items ); ?>);" /></th><th class="title"><?php echo JHTML::_(‘grid.sort’, ‘Auto’, ‘a.text’,@$lists[‘order_Dir’], @$this->lists[‘order’] ); ?></th><th width="5%" align="center"><?php echo JHTML::_(‘grid.sort’, ‘Published’,‘a.published’, @$this->lists[‘order_Dir’], @$this->lists[‘order’] ); ?></th><th width="1%" nowrap="nowrap"><?php echo JHTML::_(‘grid.sort’, ‘ID’, ‘a.id’,@$this->lists[‘order_Dir’], @$this->lists[‘order’] ); ?></th></tr></thead><?php $k = 0; for ($i=0, $n=count( $this->items ); $i < $n; $i++){ $row = &$this->items[$i]; $published = JHTML::_(‘grid.published’, $row, $i ); $link = JRoute::_( ‘index.php?option=com_auto&controller=auto&task= edit&cid[]=’.$row->id ); ?> <tr class="<?php echo "row$k"; ?>"> <td></td> <td></td> <td><a href="<?php echo $link; ?>"><?php echo $row->type; ?></a></td> <td align="center"><?php echo $published;?></td> <td align="center"><?php echo $row->id; ?></td> </tr> <?php $k = 1 - $k; }?></table></div><input type="hidden" name="option" value="com_auto" /><input type="hidden" name="task" value="" /><input type="hidden" name="boxchecked" value="0" /><input type="hidden" name="controller" value="auto" /></form>Listing 15.15 : /administration/components/com_auto/views/autos/tmpl/default.phpLe template est constitué d’un code HTML assez simple dans un formulaire. C’est ce code qui se charge de l’affichage de la table (voir Figure 15.13).Figure 15.13 La table du composant auto.La vue formulaire (/administration/components/com_auto/views/auto/view.html.php)Il faut également prévoir un affichage sous forme de fiche pour chaque auto (un seul enregistrement). Observez bien le nom du sous-dossier. Nous sommes à présent dans le sous-dossier auto, alors que la liste se trouve dans le sous-dossier autos au pluriel (Listing 15.16).<?phpdefined(‘_JEXEC’) or die();jimport( ‘joomla.application.component.view’ );class AutosViewAuto extends JView{ function display($tpl = null){ $auto =& $this->get(‘Data’); $isNew = ($auto->id < 1); $text = $isNew ? JText::_( ‘New’ ) : JText::_( ‘Edit’ ); JToolBarHelper::title( JText::_( ‘Auto’ ).’: <small>[ ‘ . $text.’ ] </small>’ ); JToolBarHelper::save(); if ($isNew) { JToolBarHelper::cancel(); } else { JToolBarHelper::cancel( ‘cancel’, ‘Close’ ); } $this->assignRef(‘auto’, $auto); parent::display($tpl); }}Listing 15.16 : /administration/components/com_auto/views/auto/view.html.phpNous procédons à la construction de la barre d’outils pour la vue fiche (voir Figure 15.14). Dans cet affichage, nous pouvons insérer des données et modifier un enregistrement existant. La variable nommée $isNew permet de décider entre les deux contextes.Figure 15.14 La barre d’outils du formulaire du mode fiche.Formulaire du template (/administration/components/com_auto/views/auto/tmpl/form.php)Ce template standard permet de construire le formulaire de la vue fiche individuelle (voir Listing 15.17).<?php defined(‘_JEXEC’) or die(‘Restricted access’); ?><script language="JavaScript" type="text/JavaScript">function submitbutton(pressbutton) { var form = document.adminForm; if (pressbutton == ‘cancel’) { submitform( pressbutton ); return; } // do field validation if (form.text.value == "") { alert( "<?php echo JText::_( ‘Texte obligatoire’, true ); ?>" ); } else { submitform( pressbutton ); }}</script> <form action="index.php" method="post" name="adminForm" id="adminForm"><div><fieldset class="adminform"><legend><?php echo JText::_( ‘Details’ ); ?></legend><table class="admintable"><tr><td width="110" class="key"><label for="title"><?php echo JText::_( ‘Type’ ); ?>:</label></td><td><input class="inputbox" type="text" name="type" id="type" size="60" value="<?php echo $this->auto->type; ?>" /></td></tr><tr><td width="110" class="key"><label for="alias"><?php echo JText::_( ‘Constructeur’ ); ?>:</label></td><td><input class="inputbox" type="text" name="constructeur"id="constructeur" size="60" value="<?php echo $this->auto->constructeur; ?>" /></td></tr><tr><td class="key"><label for="lag"><?php echo JText::_( ‘Photo mini (120px)’ ); ?>:</label></td><td><input class="inputbox" type="text" name="photo_mini" id="photo_ mini" size="60" value="<?php echo $this->auto->photo_mini; ?>" /> <?php echo JText::_( ‘(Veuillez indiquer un lien avec http:// vers un fichier de photo)’ ); ?></td></tr><tr><td colspan="2"><?php if ($this->auto->photo_mini){?><img src="<?php echo $this->auto->photo_mini; ?>"><?php } ?></td></tr><tr><td class="key"><label for="lag"><?php echo JText::_( ‘Photo grande (350px)’ ); ?>:</label></td><td><input class="inputbox" type="text" name="photo_grande" id="photo_ grande" size="60" value="<?php echo $this->auto->photo_grande; ?>" /> <?php echo JText::_( ‘(Veuillez indiquer un lien avec http:// vers un fichier de photo)’ ); ?></td></tr><tr><td colspan="2"><?php if ($this->auto->photo_grande){?><img src="<?php echo $this->auto->photo_grande; ?>"><?php } ?></td></tr><tr><td width="120" class="key"><?php echo JText::_( ‘Published’ ); ?>:</td><td><?php echo JHTML::_( ‘select.booleanlist’, ‘published’, ‘class= "inputbox"’, $this->auto->published ); ?></td></tr></table></fieldset></div><div class="clr"></div><div class="clr"></div> <input type="hidden" name="option" value="com_auto" /><input type="hidden" name="id" value="<?php echo $this->auto->id; ?>" /><input type="hidden" name="task" value="" /><input type="hidden" name="controller" value="auto" /></form>Listing 15.17 : /administration/components/com_auto/views/auto/tmpl/form.phpNous trouvons à nouveau du code HTML pur ainsi que des variables PHP ($this->auto->id) et des appels de classes statiques (JText). La Figure 15.15 montre le résultat affiché.Figure 15.15 Formulaire de modification d’un enregistrement de la table.La table auto (/administration/components/com_auto/tables/auto.php)Il nous reste à définir la classe de la table pour que le modèle sache quelles données il doit manipuler. La classe nommée JTable simplifi e tous les accès aux données. C’est une classe abstraite (autrement dit une interface). Les classes qui en dérivent peuvent exploiter la structure dont elles héritent via leurs méthodes. Le nom de la table et la clé primaire (l’index) sont définis au niveau du constructeur de la classe (voir Listing 15.18).<?php// Accès direct interditdefined(‘_JEXEC’) or die(‘Restricted access’); class TableAuto extendsJTable { /** @var int Primary key */ var $id = 0; /** @var string */ var $type = ‘’; /** @var string */ var $constructeur = ‘’; /** @var string */ var $photo_mini = ‘’; /** @var string */ var $photo_grande = ‘’; /** @var string */ var $published = 0; /** @var int */ /** * Constructor * * @param object Database connector object */ function TableAuto(& $db) { parent::__construct(‘#__auto’, ‘id’, $db); }}?>Listing 15.18 : /administration/components/com_auto/tables/auto.phpInstallation (/administration/components/com_auto/install.sql) et désinstallation (idem/uninstall.sql)Les deux procédures d’installation et de désinstallation supposent pour Joomla! de savoir créer la table du composant et la supprimer. Deux fichiers contenant des instructions SQL sont conçus à cet effet (voir Listings 15.19 et 15.20).DROP TABLE IF EXISTS `#__auto`;CREATE TABLE `#__auto` ( `id` int(11) NOT NULL auto_increment, `type` text character set utf8 NOT NULL, `constructeur` varchar(100) character set utf8 NOT NULL, `photo_grande` varchar(200) character set utf8 NOT NULL, `photo_mini` varchar(200) character set utf8 NOT NULL, `published` tinyint(1) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=MyISAM AUTO_INCREMENT=5 ;INSERT INTO `#__auto` (`id`, `type`, `constructeur`, `photo_grande`, `photo_mini`, `published`) VALUES (2, ‘Smart fortwo’, ‘Smart’, ‘http://localhost/joomla150/images/stories/ com_auto/smart_grande.jpg’, ‘http://localhost/joomla150/images/stories/ com_auto/smart_mini.jpg’, 1), (4, ‘Roadster’, ‘Smart’, ‘http://localhost/joomla150/images/stories/com_ auto/roadster_grande.jpg’, ‘http://localhost/joomla150/images/stories/ com_auto/roadster_mini.jpg’, 1); Listing 15.20 : administration/ components/com_auto/uninstall.sqlDROP TABLE IF EXISTS `#__auto`;Listing 15.19 : /administration/components/com_auto/install.sql15.2.4 Test du composantAprès avoir étudié tous ces fichiers sources, vous pouvez tester le composant et vérifier que vous pouvez gérer entièrement la table de données par l’administration Joomla!. Essayez de créer des enregistrements, d’en effacer, d’en modifier et d’en publier. Vous pouvez agir sur tout un groupe en sélectionnant plusieurs enregistrements par leur case à cocher.15.2.5 Création d’un paquetage d’installationPour concevoir un paquetage exploitable par l’installateur, il nous reste à écrire le fichier XML contenant les métadonnées.administrator\components\com_autoauto.xmlC’est dans ce fichier que vous décrivez les éléments qui constituent le nouveau composant. L’installateur va se servir de ces descriptions. Le fichier doit contenir tous les noms de fichiers enchâssés dans des balises XML. C’est grâce à cela que l’installateur de Joomla! va savoir créer les sousdossiers, y copier les fichiers et enfin créer la table de données (voir Listing 15.21).<?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>Auto</name><creationDate>November 2007</creationDate><author>Hagen Graf</author><authorEmail>hagen.graf@gmail.com</authorEmail><authorUrl>http://www.cocoate.com</authorUrl><copyright>All rights reserved</copyright><license>GNU/GPL</license><version>Component Version String</version><description>Description du composant ... </description><files folder="site"><filename>index.html</filename><filename>auto.php</filename><filename>controller.php</filename><filename>views/index.html</filename><filename>views/auto/index.html</filename><filename>views/auto/view.html.php</filename><filename>views/auto/tmpl/index.html</filename><filename>views/auto/tmpl/default.php</filename><filename>models/auto.php</filename></files><install><sql><file charset="utf8" driver="mysql">install.sql</file></sql></install><uninstall><sql><file charset="utf8" driver="mysql">uninstall.sql</file></sql></uninstall><administration><menu>Livre Joomla! 1.5 : Auto</menu><files folder="admin"><filename>index.html</filename><filename>admin.auto.php</filename><filename>controller.php</filename><filename>controllers/auto.php</filename><filename>controllers/index.html</filename><filename>models/auto.php</filename><filename>models/autos.php</filename><filename>models/index.html</filename><filename>views/autos/view.html.php</filename><filename>views/autos/index.html</filename><filename>views/autos/tmpl/default.php</filename><filename>views/autos/tmpl/index.html</filename><filename>views/auto/view.html.php</filename><filename>views/auto/tmpl/form.php</filename><filename>views/auto/index.html</filename><filename>views/auto/tmpl/index.html</filename><filename>tables/auto.php</filename><filename>tables/index.html</filename><filename>install.sql</filename><filename>uninstall.sql</filename></files></administration></install>Listing 15.21 : administrator\components\com_autoauto.xmlVous savez déjà créer le paquetage en rassemblant tous les fichiers dans un fichier .zip qui porte le nom du composant. Dans notre cas le paquetage s’appelle com_auto.zip. Les fichiers de la partie Frontend sont dans le sous-dossier de premier niveau site et ceux de l’administration dans le sousdossier admin (voir Figure 15.16).Figure 15.16 Les fichiers du composant com_auto prêt à être empaquetés.Vous pouvez maintenant procéder à l’installation du fichier .zip dans Joomla! et le diffuser à d’autres utilisateurs. Pensez toujours à désinstaller la version précédente du composant avant de le réinstaller. Vous savez comment faire : EXTENSIONS > INSTALLER/DÉSINSTALLER, sélection du composant et cliquez sur le bouton DÉSINSTALLER.| Fichier attaché | Taille |
|---|---|
| com_auto_0.zip | 12.24 Ko |












3 commentaires
L'exemple est très bine,
L'exemple est très bine, merci.
Je vais le regarde en détail.
Je suis à la recherche d'un composant pour gérer les annonces auto (et je pense que le votre est une bonne base de départ.
Merci
Try SobiPro Demo:
Try SobiPro
Demo: http://demo.sobi-pro.eu/index.php?option...
bonjour :) merci pour le
bonjour :)
merci pour le super exemple ça fait longtemps que je cherche à un qui lui ressemble.
je suis encore une débutante et j'ai essayer de l'installer et le test . le back officce fonctionne très bien mais je ne sais pas comment test et afficher la partie front office. veuillez svp de bien préciser comment ça se fait ?
merci d'avance et bonne journée
Publier un nouveau commentaire