Création de composant Joomla! 1.6

Réduire
X
 
  • Filtrer
  • Heure
  • Afficher
Tout effacer
nouveaux messages

  • Création de composant Joomla! 1.6

    Bonjour, je viens de me lancer dans l'aventure Joomla! il y a quelques semaines et je dois dire que c'est un CMS vraiment très déroutant.

    J'ai pour mission de créer un prototype de site reprenant plusieurs fonctionnalités très spécifiques en relation avec des tables dans une base de données. Du coup, je me suis orienté vers la création de composants, et grâce à ce tutoriel j'ai réussi à mettre en place un composant Hello World fonctionnel. Pas très difficile me direz-vous, il suffit de recopier le code.

    Pour répondre à mes besoins, je l'ai ensuite entièrement réécrit, pas évident quand on ne connait pas le MVC à la base et quand on fait du PHP objet pour la première fois. Là où ça semble vraiment se compliquer c'est lorsque le composant fonctionne avec plusieurs tables. J'ai deux scripts sql et JInstaller m'a vraiment l'air capricieux, car quand phpMyAdmin les acceptent sans broncher, Joomla me dis non lors de l'installation du composant, ou alors il me dis oui mais aucune table ne se crée dans la base de données. J'ai l'impression qu'il n'y a pas que le script sql qui joue lors de la création des tables pendant l'installation, mais je ne vois pas quel autre fichier pourrait avoir de l'influence dessus à part le .xml à la racine du composant :
    <install> <!-- s'exécute à l'installation -->
    <sql>
    <file driver="mysql" charset="utf8">sql/install.mysql.utf8.sql</file>
    </sql>
    </install>

    <uninstall> <!-- s'execute à la désinstallation -->
    <sql>
    <file driver="mysql" charset="utf8">sql/uninstall.mysql.utf8.sql</file>
    </sql>
    </uninstall>

    <update> <!-- nouvelle fonctionnalité joomla 1.6, s'exécute lors de la mise à jour -->
    <schemas>
    <schemapath type="mysql">sql/updates/mysql</schemapath>
    </schemas>
    </update>

    J'ai un script sql de désinstallation très simple :
    DROP TABLE IF EXISTS `#__page_xxxxxx_contacts_service`;
    DROP TABLE IF EXISTS `#__page_xxxxxx_contacts_contact`;
    DROP TABLE IF EXISTS `#__page_xxxxxx_contacts_contact_service`;
    DROP TABLE IF EXISTS `#__page_xxxxxx_contacts_commune`;
    DROP TABLE IF EXISTS `#__page_xxxxxx_contacts_contact_commune`;
    DROP TABLE IF EXISTS `#__page_xxxxxx_contacts_departement`;
    il est basé sur le modèle de hello world sauf qu'il y a plusieurs tables à effacer, et là je me retrouve avec une erreur lors de la désinstallation du composant par le back-end de Joomla :
    JInstaller::Install : erreur SQL Fonction DB échouée avec le numéro d'erreur 1064
    You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'DROP TABLE IF EXISTS `dev_page_xxxxxx_contacts_service`' at line 1 SQL=DROP TABLE IF EXISTS `dev_page_xxxxxx_contacts_service`;
    Je passe vraiment beaucoup de temps à comparer ce qui ne va pas dans mes fichiers grâce à eclipse helios, à la recherche d'un truc tout bête du genre mauvais appel de fonction mais je ne trouve rien. J'ai vérifié les encodages de mes fichiers sql avec notepad++ et ils sont bien en utf8.

    Après cette intense semaine à patauger, je commence à désespérer de trouver la solution, d'autant plus que je commence à voir d'autres problèmes se profiler à l'horizon qui ne sont pas aborder dans le tutoriel hello world. A savoir, comment insérer du code HTML dans un composant pour son affichage front-end, car j'ai par exemple besoin d'insérer une image comportant des liens et des requêtes MySQL. Pour cela, j'ai essayé de modifier le contenu de tous les fichiers index.html du répertoire "site" en espérant qu'ils afficheraient quelque chose en front-end, mais rien... du coup je ne sais toujours pas à quoi ils servent, en plus ils sont envahissants.

    Voilà pourquoi je dis que ce CMS est très déroutant pour un non habitué au développement dans le framework joomla.

    J'ai auparavant développé avec wordpress, et pour cette fonctionnalité j'aurais simplement insérer le code HTML/php nécessaire dans un modèle de page. C'est une solution moins portable que celle du package.zip d'un composant sous Joomla, et beaucoup moins standardisé, mais aussi beaucoup plus simple et moins contraignante. Je me rassure en me disant qu'il doit y avoir une raison à cette complexité de création de composant Joomla. Il doit surement être plus sécurisé et ça semble plus propre, mais bon encore faut-il réussir à le rendre fonctionnel, et au niveau de l'investissement en temps c'est peut être pas forcément rentable.
    Dernière édition par jophoen à 20/06/2011, 10h27 Raison: changement de statut sujet en réglé

  • #2
    Re : Création de composant Joomla! 1.6

    Tu attaques beaucoup de sujets en même temps. Il te faut un bon guide. Le mien ça a été Learning Extension for Joomla, qui détaille bien toute les phases de la création d'un Comp, jusqu'a l'install. Mais ça, on voit souvent cela en dernier quand le composant est en V1.
    Il faut bien comprendre les rouages MVC, car chaque partie a des fonctions bien précises, qui n'ont rien a voir avec le HTML de Wordpress.
    Bref, faut avoir ce guide pour démarrer, Helloword est un début, mais n'est pas vraiment complet...

    On insère trés facilement du code HTML, du moment que tu es au bon endroit : view/tmpl/default.php, dont voici un exemple...
    Code PHP:
    <?php 
    // no direct access
    defined('_JEXEC') or die('Restricted access'); 
    JHTML::stylesheet('filters.css''media/com_jbreedm/css/');
    $n count$this->chiotsdisp );
    ?>
    <table border="0">
        <tbody>
            <tr>
                <td align="center" width="300" valign="top"><strong><span style="font-family: Georgia, 'Times New Roman', Times, serif; font-size: 14pt; color: #0000ff;">
                <?php
                    
    if ( ($this->portee->birthday) != '0000-00-00' )
                        {
                        echo 
    $this->portee->nb .' 'JText::_('PUPPIES_BORNED') . JHTML::_('date',  $this->portee->birthdayJText::_('DATE_FORMAT_LC4') );
                        
                        }
                    else
                        {
                         echo 
    JText::_('PUPPIES_AWAITED') . JHTML::_('date',  $this->portee->awaitedJText::_('DATE_FORMAT_LC4') );
                        }
                
    ?></span></strong></td>
                <td colspan="2" align="center" valign="middle"><img src="images/stories/com_jbreedm/lesparents.jpg" border="0" width="222" height="50" /></td>
            </tr>
            <tr>
                <td>
                    <p><span style="text-decoration: underline;"><strong style="color: #660000;"><span style="font-size: medium;">Les couleurs :</span></strong></span></p>
                    <?php echo $this->portee->comments?>
                    <br />
                    <?php
                    
    if (!empty($this->portee->photo_chiots) )
                        {
                        
    $filename 'images/stories/com_jbreedm/'$this->portee->photo_chiots ;
                        list(
    $width$height$type$attr) = getimagesize($filename);
                        if (
    file_exists($filename) )
                            {
                               
    ?>
                            <span style="color: #006699; font-size: x-small;">Photo: <?php echo date ("d m Y H:i:s."filemtime($filename)); ?></span><br />
                            <a href="images/stories/com_jbreedm/<?php echo $this->portee->photo_chiots?>" onclick="window.open('<?php echo $filename?>','','scrollbars=yes,resizable=yes,dependent=yes,width=<?php echo $width?>,height=<?php echo $height?>,left='+(screen.availWidth/2-<?php echo $width/2?>)+',top='+(screen.availHeight/2-<?php echo $height/2?>)+'');return false;"><img src="images/stories/com_jbreedm/<?php echo $this->portee->photo_chiots?>" border="0" height="200" /></a>
                            <?php
                            
    }
                        }
                    
    ?>
                    </td>
                    <td style="text-align: center;" valign="top"><a href="<?php echo $this->mere->page?>"><img src="images/stories/com_jbreedm/<?php echo $this->mere->photo?>" border="0" alt="D'autres photos et le pedigree de <?php echo $this->mere->dname?>" height="220" /><br /><img src="images/stories/com_jbreedm/<?php echo $this->mere->logoname?>" border="0" height="20" /></a></td>
                    <td style="text-align: center;" valign="top"><a href="<?php echo $this->pere->page?>"><img src="images/stories/com_jbreedm/<?php echo $this->pere->photo?>" border="0" alt="D'autres photos et le pedigree de <?php echo $this->pere->dname?>" height="250" /><br />  <img src="images/stories/com_jbreedm/<?php echo $this->pere->logoname?>" border="0" height="20" /></a></td>
                </tr>
            </tbody>
        </table>
       </td>
      </tr>
    </tbody>
    </table>
    Dernière édition par liubov à 19/06/2011, 09h42 Raison: complément d'info
    Developper of JBreeding Manager: http://www.jbreeding.fr/
    J-cook Referral : Service Générateur d'Extensions pour Joomla

    Commentaire


    • #3
      Re : Création de composant Joomla! 1.6

      Oui je me suis heurté à pas mal d'obstacles d'un coup mais bon c'est comme ça qu'on apprend!

      Merci pour la solution qui insère du code HTML en front-end, c'est vrai que si on se base sur le schéma MVC ce sont logiquement les vues qui se chargent de l'affichage. Par contre le code HTML ne se "fond" pas dans le thème du site (thème par défaut), en gros le code source de la page se limite au simple code HTML que j'ai saisis : page blanche avec les balises de texte.

      Pour mon soucis avec JInstaller je l'ai résolu. En fait le fichier qui me posait soucis c'était le .php contenu dans le répertoire admin/tables. En suivant cette doc sur JTable j'ai modifié mon .php en question avec une classe pour chaque table. Par contre JTable ne reconnait pas les clés composés du coup j'ai du faire un truc un peu plus moche pour les tables d'association en rajoutant un ID qui s'auto-incrémente.

      Code:
      <?php
      defined('_JEXEC') or die('Restricted access');
      
      jimport('joomla.database.table');
      
      /*
       * 
       */
      class XxxxxxContactsTableService extends JTable{
      	var $id_service = null;
      	var $libelle_service = null;
      	function __construct(&$db){
      		parent::__construct('#__page_xxxxxx_contacts_departement','id_departement',$db);
      	}
      }
      class  XxxxxxContactsTableContact extends JTable{
      	var $id_contact = null;
      	var $nom = null;
      	var $prenom = null;
      	var $fonction = null;
      	var $telephone = null;
      	var $mail = null;
      	function __construct(&$db){
      		parent::__construct('#__page_xxxxxx_contacts_contact','id_contact',$db);
      	}
      }
      class XxxxxxContactsTableContactService extends JTable{
      	var $id_contact = null;
      	var $id_service = null;
      	function __construct(&$db){
      		parent::__construct('#__page_xxxxxx_contacts_contact_service','id_contact,id_service',$db);
      	}
      }
      class XxxxxxContactsTableCommune extends JTable{
      	var $id_commune = null;
      	var $libelle_commune = null;
      	var $id_departement = null;
      	function __construct(&$db){
      		parent::__construct('#__page_xxxxxx_contacts_commune','id_commune',$db);
      	}
      }
      class XxxxxxContactsTableContactCommune extends JTable{
      	var $id_contact = null;
      	var $id_commune = null;
      	function __construct(&$db){
      		parent::__construct('#__page_xxxxxx_contacts_contact_commune','id_contact,id_commune',$db);
      	}
      }
      class XxxxxxContactsTableDepartement extends JTable{
      	var $id_departement = null;
      	var $libelle_departement = null;
      	function __construct(&$db){
      		parent::__construct('#__page_xxxxxx_contacts_departement','$id_departement',$db);
      	}
      }
      Le problème avec mon script de désinstallation sql (erreur 1064) était totalement différent. En fait, j'ai un peu de mal à y croire, mais en remplaçant tout simplement les majuscules par des minuscules (drop table au lieu de DROP TABLE) ça s'est mis à passer :
      Code:
      drop table if exists `#__page_xxxxxx_contacts_service`;
      drop table if exists `#__page_xxxxxx_contacts_contact`;
      drop table if exists `#__page_xxxxxx_contacts_contact_service`;
      drop table if exists `#__page_xxxxxx_contacts_commune`; 
      drop table if exists `#__page_xxxxxx_contacts_contact_commune`;
      drop table if exists `#__page_xxxxxx_contacts_departement`;
      Maintenant mon composant construit correctement toutes les tables en base, et les supprime lors de sa désinstallation par le back-end joomla!

      Commentaire


      • #4
        Re : Création de composant Joomla! 1.6

        Pour corriger ce que j'ai écris au dessus au sujet des classes correspondant au table, j'ai du enlever les variables déclarées comme null car du coup je ne récupérais pas les données (logique) et lors de la soumission du formulaire d'ajout ou d'édition j'obtenais une page blanche.

        Je suis à nouveau confronté à un problème technique, en fait j'ai 6 tables, dont deux qui sont associatives (elles contiennent seulement les clés étrangères pour pouvoir faire la correspondance entre mes tables).

        En utilisant une vue administrateur, celle qui me permet d'éditer où d'ajouter un contact, j'aimerais avoir de la même manière qu'il existe pour les catégories, un liste déroulante avec les occurrences des autres tables proposées.

        Je me suis basé sur la syntaxe du tutoriel HelloWorld qui inclue une liste déroulante pour associer un message à une catégorie :

        admin/models/fields/contact.php :
        Code PHP:
        class JFormFieldContact extends JFormFieldList
        {
            protected 
        $type "Contact";
            
            protected function 
        getOptions(){
                
        $db JFactory::getDBO();
                
        $query = new JDatabaseQuery;
                
        $query->select('co.id_contact,co.nom,co.prenom,co.fonction,co.telephone,co.email,dept.id_departement,dept.libelle_departement,serv.id_service,serv.libelle_service,comm.id_commune,comm.libelle_commune');
                
        $query->from('#__xxxxxx_contacts_contact AS co');
                
        $query->leftJoin('#__xxxxxx_contacts_contact_commune AS coco ON coco.id_contact=co.id_contact');
                
        $query->leftJoin('#__xxxxxx_contacts_commune AS comm ON coco.id_commune=comm.id_commune');
                
        $query->leftJoin('#__xxxxxx_contacts_contact_service AS cose ON cose.id_contact=co.id_contact');
                
        $query->leftJoin('#__xxxxxx_contacts_service AS serv ON serv.id_service=cose.id_service');
                
        $query->leftJoin('#__xxxxxx_contacts_departement AS dept ON dept.id_departement=comm.id_departement');
                
        $db->setQuery((string)$query);
                
        $messages $db->loadObjectList();
                
        $options = array();
                if (
        $messages)
                {
                    foreach(
        $messages as $message){
                        
        $options[] = JHtml::_('select.option'$message->id_contact$message->nom$message->prenom$message->fonction$message->telephone$message->email . ($message->id_departement ' (' $message->libelle_departement ')' ''), ($message->id_service ' (' $message->libelle_service ')' ''), ($message->id_commune ' (' $message->libelle_commune ')' ''));
                    }
                }
                
                
        $options array_merge(parent::getOptions(), $options);
                return 
        $options;
            }

        Mais sans succès, je n'obtiens que les données de la table contact. Cette méthode ne doit pas fonctionner pour les tables d'associations. Les catégories sont référencés par une clé étrangère directement écrite dans la table, et non en passant par une table d'association. Donc je n'arrive pas à récupérer ces données.

        Le modèle de formulaire xml utilisé (admin/models/forms/contact.xml) :
        Code HTML:
        <?xml version="1.0" encoding="UTF-8"?>
        <form
        	addrulepath="/administrator/components/com_xxxxxxcontacts/models/rules"
        >
        	<fieldset name="details">
        		<field
        			name="id_contact"
        			type="hidden"
        		/>
        		<field
        			name="nom"
        			type="text"
        			label="COM_XXXXXXCONTACTS_CONTACT_NOM_LABEL"
        			description="COM_XXXXXXCONTACTS_CONTACT_NOM_DESCRIPTION"
        			size="40"
        			class="inputbox"
        			required="true"
        			default=""
        		/>
        		<field
        			name="prenom"
        			type="text"
        			label="COM_XXXXXXCONTACTS_CONTACT_PRENOM_LABEL"
        			description="COM_XXXXXXCONTACTS_CONTACT_PRENOM_DESCRIPTION"
        			size="40"
        			class="inputbox"
        			required="true"
        			default=""
        		/>
        		<field
        			name="fonction"
        			type="text"
        			label="COM_XXXXXXCONTACTS_CONTACT_FONCTION_LABEL"
        			description="COM_XXXXXXCONTACTS_CONTACT_FONCTION_DESCRIPTION"
        			size="40"
        			class="inputbox"
        			required="true"
        			default=""
        		/>
        		<field
        			name="telephone"
        			type="text"
        			label="COM_XXXXXXCONTACTS_CONTACT_TELEPHONE_LABEL"
        			description="COM_XXXXXXCONTACTS_CONTACT_TELEPHONE_DESCRIPTION"
        			size="40"
        			class="inputbox"
        			default=""
        		/>
        		<field
        			name="email"
        			type="text"
        			label="COM_XXXXXXCONTACTS_CONTACT_EMAIL_LABEL"
        			description="COM_XXXXXXCONTACTS_CONTACT_EMAIL_DESCRIPTION"
        			size="40"
        			class="inputbox"
        			default=""
        		/>
        	</fieldset>
        	<fieldset name="service">
        		<field
        			name="id_departement"
        			type="hidden"
        		/>
        		<field
        			name="libelle_departement"
        			type="category"
        			label="COM_XXXXXXCONTACTS_CONTACT_DEPARTEMENT_LABEL"
        			description="COM_XXXXXXCONTACTS_CONTACT_DEPARTEMENT_DESC"
        			class="inputbox"
        			extension="com_xxxxxxcontacts"
        			required="true"
        		/>
        		<field
        			name="id_service"
        			type="hidden"
        		/>
        		<field
        			name="libelle_service"
        			type="category"
        			label="COM_XXXXXXCONTACTS_CONTACT_SERVICE_LABEL"
        			description="COM_XXXXXXCONTACTS_CONTACT_SERVICE_DESC"
        			class="inputbox"
        			extension="com_xxxxxxcontacts"
        			required="true"
        		/>
        		<field
        			name="id_commune"
        			type="hidden"
        		/>
        		<field
        			name="libelle_commune"
        			type="category"
        			label="COM_XXXXXXCONTACTS_CONTACT_COMMUNE_LABEL"
        			description="COM_XXXXXXCONTACTS_CONTACT_COMMUNE_DESC"
        			class="inputbox"
        			extension="com_xxxxxxcontacts"
        			required="true"
        		/>
        	</fieldset>
        </form>
        Grosso modo, ce que j'essaie de faire, c'est que lors de l'ajout ou l'édition d'un contact, on puisse lui associer un département, un service et une commune. Chacun de ces champs correspondent à des tables distinctes, et comme un contact peut être situé dans plusieurs services et communes, je dois passer par des tables d'association.
        Dernière édition par jophoen à 27/06/2011, 13h24

        Commentaire

        Annonce

        Réduire
        Aucune annonce pour le moment.

        Partenaire de l'association

        Réduire

        Hébergeur Web PlanetHoster
        Travaille ...
        X