factoriser le model d'un composant

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

  • [RÉGLÉ] factoriser le model d'un composant

    Bonjour !

    Je suis actuellement en stage dans un environnement Joomla! que je découvre .
    Ma mission consiste à déboguer, factoriser et améliorer un composant de migration.

    Le composant à été partiellement débogué, cependant, je souhaite factoriser un fichier de migration ( models/migrate.php ) qui fait plus de 3 800 lignes.
    Ce fichier est composé d'environ 39 méthodes.
    J'aimerais isoler chaque méthode dans un fichier distinct afin de pouvoir les appeler dès que besoin dans mon fichier migrate.php histoire de rendre mon code plus lisible.

    J'ai tenté vainement d'inclure les méthodes avec des includes(); mais ca ne fonctionne pas.
    En fouillant un peu sur le web, je suis tombé sur jimport() (qui apparemment est déconseillé.) et Jloader , mais je n'arrive pas à en tirer quoi que ce soit...
    Enfin, j'ai essayé de jouer sur les héritages, mais je n'ai pas pu renommer ma "class NameComposantModelMigrate extend JModelLegacy" (C'est une convention Joomla! si j'ai bien compris )

    Me voilà dépourvu d'idées .. Je viens donc vers vous si quelqu’un de la communauté Joomla! peut m'aiguiller ce serait vraiment sympa !

    Merci d'avance.
    Dimitri.
    Dernière édition par dimitri.kft à 21/02/2020, 10h28

  • #2
    normalement include_once 'tonfichier.php'; marche parfaitement

    Commentaire


    • #3
      Hello.

      Jloader sert à enregistrer une classe dans le framework, pour que celui-ci puisse charger dynamiquement le fichier au premier appel de celle-ci.

      Voici un exemple d'utilisation :
      Code PHP:
      JLoader::register('GskiComiteHelper'JPATH_ADMINISTRATOR DIRECTORY_SEPARATOR 'components' DIRECTORY_SEPARATOR 'com_gskicomite' DIRECTORY_SEPARATOR 'helpers' DIRECTORY_SEPARATOR 'gskicomite.php'); 
      Dans cet exemple je dis que la classe GskiComiteHelper est définie dans le dossier helpers de l'admin de mon composant, dans le fichier gskicomitehelper.php

      Une fois l'enregistrement réalisé par JLoader, tu peux appeler la classe (on l'instancier) depuis n'importe où.
      Dernière édition par roland_d_alsace à 11/02/2020, 20h10
      alexandreelise, dimitri.kft et c-line aiment ceci.
      A tous les utilisateurs de Joomla du très Grand Est de la France et du Jura suisse
      Rejoignez le Joomla Users Groupe Alsace...
      roland_d_alsace va-t-il devenir roland_du_grand_est ?

      Commentaire


      • #4
        Hello Roland

        Juste une curiosité de ma part : joomla 4 et ses namespaces va tout chambouler n'est-ce pas ? Le autoload va rendre inutile jloader en principe non ? Dès lors que le namespace est correctement rédigé, php (joomla) sait quoi charger, quand et où se trouve le source.

        Bonne soirée
        Christophe (cavo789)
        Mon blog, on y parle Docker, PHP, WSL, Markdown et plein d'autres choses : https://www.avonture.be
        Logiciel gratuit de scan antivirus : https://github.com/cavo789/aesecure_quickscan (plus de 45.000 virus détectés, 700.000 fichiers sur liste blanche)​

        Commentaire


        • #5
          Bonjour et merci de vos réponses,

          pour include_once() ca marche mais sous certaines conditions qui ne vont pas avec mon code , ( par exemple je suis obligé de coupé le return de mes méthodes.) Sinon cela ne fonctionne pas. Et le include_once ne fonctionne pas en dehors d'une méthode puisque je suis dans un objet.

          Ma méthode :

          Code PHP:
          public function insertImg($sql) {
                  
          $db JFactory::getDBO();
                  
          $user  JFactory::getUser();
                  if(
          JFolder::create(JPATH_ROOT.DS.'images'.DS.'k2')) {
                      if(
          JFolder::create(JPATH_ROOT.DS.'images'.DS.'k2'.DS.'categories')) {
                      }
                      if(
          JFolder::create(JPATH_ROOT.DS.'images'.DS.'k2'.DS.'items')) {
                      }
                  }
                  if (
          $sql == ''){
                      
          $query $db->getQuery(true);

                      
          $query
                      
          ->select($db->quoteName(array('id''name''alias''description''parent''extraFieldsGroup''published''access''ordering''image''params''trash''plugins''language')))
                      ->
          from($db->quoteName('#__k2_categories'));

                      
          $db->setQuery($query);
                      
          $sql =  $db->loadAssocList();
                  }
                  foreach (
          $sql as $elem =>$row) {
                      
          $message self::insertImg3($row);
                      
          $catalias $row['alias'];
                      unset(
          $sql[$elem]);
                      if (
          $sql == array()){
                          
          $valuesjsons json_encode(array('task' => 'insertImg2''sql' => '''message' => $message,
                                  
          'type' => 'ImageCategorie''name' => $catalias.'.jpg'), JSON_NUMERIC_CHECK);
                          return 
          $valuesjsons;
                          die;
                      }
                      else {
                          
          $valuesjsons json_encode(array('task' => 'insertImg''sql' => $sql'message' => $message,
                                  
          'type' => 'ImageCategorie''name' => $catalias.'.jpg'), JSON_NUMERIC_CHECK);
                          return 
          $valuesjsons;
                          die;
                      }
                  }
                  return 
          $valuesjsons;
              }

              } 

          Avec include_once :

          Code PHP:
          public function insertImg($sql) {
                  include_once(
          "insert_image/insertImage.php");
                  return 
          $valuesjsons;
              } 

          Roland si j'ai bien suivi la marche à suivre, je place le Jloader dans une methode de mon models/migrate.php qui fait appelle à la class comprenant ma méthode dans le dossier helper/insertImg.php .

          Code PHP:
          JLoader::register('InsertImgHelper'JPATH_ADMINISTRATOR DIRECTORY_SEPARATOR 'components' DIRECTORY_SEPARATOR 'com_k2toflexi' DIRECTORY_SEPARATOR 'helpers' DIRECTORY_SEPARATOR 'insertImg.php'); 


          Si c'est bien ça, je n'arrive pas à appeler ma class depuis le migrate.php (la je pense que c'est un manque de technique de ma part) j'ai tenté en vain :

          Code PHP:
          public function insertImg($row){
                  
          parent::insertImg($row);
              }


              public function 
          insertImg(){
                  
          JLoader::register('InsertImgHelper'JPATH_ADMINISTRATOR DIRECTORY_SEPARATOR 'components' DIRECTORY_SEPARATOR 'com_k2toflexi' DIRECTORY_SEPARATOR 'helpers' DIRECTORY_SEPARATOR 'insertImg.php');
              } 

          Y'a t'il une façon particulière pour appeler ma méthode avec Joomla! ?
          Merci d'avance et bonne journée;
          Dimitri.
          Dernière édition par dimitri.kft à 12/02/2020, 12h24

          Commentaire


          • #6
            c'est bizarre car j'utilise mes propres class qui sont dans le libraries et je les récupères comme ca (ca marche pour J3 et 4)

            Code:
            require_once(JPATH_LIBRARIES .'/ymages/helper.php');
            $ys = new ymagesHelper() ;

            et toutes mes function ont un return

            Code:
              function exifKey($photo_raw, $info = 'IFD0Orientation'){
                    $exif_info = '';
                    $arr_exif_fields = $this->exifFields();
                    $exif_raw = exif_read_data($photo_raw, 0, true);
                    foreach ($exif_raw as $key => $section) {
                        foreach ($section as $name => $val) {
                            if(in_array($key.$name, $arr_exif_fields, false)){
                            //$exif_info .= $key.$name .'=>'. $val . '<br />';                
                            if ($key.$name == $info){
                                $exif_info = $val;                    
                            }
                            }
                        }
                    }
                    if ($info=='IFD0Orientation' && $exif_info == ''){
                        $exif_info = '0';
                    }
                    return $exif_info;
                }

            Commentaire


            • #7
              Hello.

              Apparemment il agit donc surtout de classes et méthodes statiques.

              Il est donc facile de faire des classes comportant des méthodes par groupe de fonctionnalités.

              Ton composant s'appelle donc : com_k2toflexi.

              Dans ton fichier insertImg.php tu places toutes tes méthodes liées aux images (par exemple) :

              Code PHP:
              defined('_JEXEC') or die('Restricted access');

              use 
              Joomla\CMS\Factory as JFactory//facultatif mais utilise pour l’autocomplétion sur tu utilise un IDE
              ....


              abstract class 
              InsertImgHelper
              {

                  public static function 
              insertImg($sql) {
                      
              $db JFactory::getDBO();
                      
              $user  JFactory::getUser();
                      if(
              JFolder::create(JPATH_ROOT.DS.'images'.DS.'k2')) {
                          if(
              JFolder::create(JPATH_ROOT.DS.'images'.DS.'k2'.DS.'categories')) {
                          }
              ...... 
              Tu donnes l'emplacement de tes classes<->fichier.php au framework de Joomla par JLoader::register

              En général on ne le fait qu'une fois, dans une partie "commune", donc par exemple au début de
              /component/com_k2toflexi/k2toflexi.php et dans /administrator/component/com_k2toflexi/k2toflexi.php
              Code PHP:
              <?php

              // No direct access to this file
              defined('_JEXEC') or die('Restricted access');

              use 
              Joomla\CMS\MVC\Controller\BaseController as JControllerLegacy;


              jimport('joomla.application.component.controller');

              JLoader::register('InsertImgHelper'JPATH_ADMINISTRATOR DIRECTORY_SEPARATOR 'components' DIRECTORY_SEPARATOR 'com_k2toflexi' DIRECTORY_SEPARATOR 'helpers' DIRECTORY_SEPARATOR 'insertImg.php');  

              .......
              Mais tu peux aussi le mettre dans ton fichier migrate.php.
              L'important étant que quand tu appelleras la première fois l'une des méthodes de cette classe, le JLoader ait déjà été exécuté afin que Joomla sache quel fichier charger (il fera alors le include tout seul).

              Et ensuite quand tu as besoin de ta méthode insertImg dans migrate.php par exemple tu fera l'appel de cette manière :
              Code PHP:
              ....

              $valuesjson InsertImgHelper::insertImg($sql);

              ..... 
              Pour une classe dynamique (donc que tu instancies) la technique est exactement la même, faire le JLoader ('emplacement_du_fichier','NomDeLaClasse') chronologiquement avant le new NomdeLaClasse)
              Dernière édition par roland_d_alsace à 12/02/2020, 21h39
              alexandreelise aime ceci.
              A tous les utilisateurs de Joomla du très Grand Est de la France et du Jura suisse
              Rejoignez le Joomla Users Groupe Alsace...
              roland_d_alsace va-t-il devenir roland_du_grand_est ?

              Commentaire


              • #8
                Malheureusement je tente tout ce que vous m'avez dit dans tout les sens depuis avant hier mais je n'arrive pas à faire appel à ma méthode externe, je reviendrai dessus un peu plus tard en espérant comprendre pourquoi cela ne fonctionne pas chez moi !

                En tout cas un grand merci pour la précision de vos réponses .
                bonne journée.
                Dimitri.

                Commentaire


                • #9
                  pourquoi tu ne crees pas une toute simple pour tester avec une classe dimitriHelper et seule public function monTest () qui return 'OK' par exemple

                  Code:
                  require_once(JPATH_LIBRARIES .'/dimitri/helper.php');
                  $dmtr = new dimitriHelper() ;
                  echo $dmtr->monTest();

                  pas besoin d'autre chose

                  Commentaire


                  • #10
                    Bonjour, juste un petit retour sur mon problème, j'ai enfin réussi à faire fonctionner l'appel de mes méthodes, mon problème venais des méthodes elle-même qui en appelais d'autres, donc comme elles étaient rangé dans deux fichiers distinct forcement ça ne pouvait pas fonctionner !

                    J'ai utilisé le Jloader::register qui fonctionne très bien . Merci beaucoup roland_d_alsace .

                    Commentaire


                    • #11
                      Envoyé par cavo789 Voir le message
                      Hello Roland

                      Juste une curiosité de ma part : joomla 4 et ses namespaces va tout chambouler n'est-ce pas ? Le autoload va rendre inutile jloader en principe non ? Dès lors que le namespace est correctement rédigé, php (joomla) sait quoi charger, quand et où se trouve le source.

                      Bonne soirée
                      Hello Christophe.

                      Je ne suis pas un spécialiste de l’utilisation des "namespace".

                      Je vais quand même prendre le risque d’essayer de te répondre.
                      Concernant l’usage des autoload, je pense que l’on conservera les jloader.

                      J’ai même lu que le coreteam gardera la procédure permettant de retrouver dynamiquement les (anciennes) classes commençant par J et qui fait le mapping sur les classes avec namespaces qui au passage (certaines mais pas toutes) ont changées de nom en perdant ce préfixe J de sécurité.

                      En effet le jloader permet de retrouver le fichier décrivant la classe dynamiquement.
                      Pour les classes communes définies dans ton extension on met donc les jloader dans un fichier php exécuté tout au début du cycle de ton extension et l’affaire est réglée.

                      Pour les classes du frameWork, celui-ci utilise une méthode de php pour lancer le jloader à l’appel d’une méthode d’une classe statique ou à instanciation et faire le mapping de nom.

                      L’implémentation des namespaces se fait elle à la phase de compilation du code.
                      Donc rien de dynamique.

                      Résultat : il faut mettre les ´use’ impérativement au début de chaque fichier php.
                      C’est strict.
                      Impossible de factoriser de quelques façons, ni de mettre toutes les définitions dans un fichier commun appelé par un include.

                      Je pense donc que si on utilise les autoload directement liés au namespaces ceci en imposera l’usage.
                      On aura donc l'obligation d'avoir ce paquet de use dans chaque fichier pour les classes du composant mais aussi pour celles du frameWork, ce qui me parait assez contraignant.

                      Moi j’ai pris l’habitude de le faire, mais c’est pour une autre raison.
                      Cela me permet de bénéficier de l’autocomplétion et de la documentation quand je rédige mon code.

                      J’espère ne pas avoir dit trop des conneries car comme dit je ne suis pas expert dans ce domaine et je n’ai pas encore forcément découvert toutes les finesses de l'utilisation de l'autoload et des "namespace".

                      Donc tu vois, tu en sais peut-être plus que moi .
                      A bientôt.
                      Dernière édition par roland_d_alsace à 21/02/2020, 17h43
                      A tous les utilisateurs de Joomla du très Grand Est de la France et du Jura suisse
                      Rejoignez le Joomla Users Groupe Alsace...
                      roland_d_alsace va-t-il devenir roland_du_grand_est ?

                      Commentaire


                      • #12
                        Bonsoir Roland

                        Merci pour ta réponse.

                        Note : je ne suis pas un pro pour expliquer sans la moindre faute comment fonctionne le autoload mais voici ce que je crois être le mode de fonctionnement / la façon dont je le fais avec mes propres développements (hors Joomla).

                        Tu installes composer de manière globale sur ta machine (voir site getcomposer.org),
                        Au niveau de ton projet, tu fais un "composer install" afin de créer un fichier composer.json vide et un dossier vendor avec composer qui y est présent.
                        Surtout le fichier vendor/autoload.php qui se charge de faire le boulot.
                        Dans le fichier /composer.json, tu vas, manuellement, définir tes namespaces.
                        Tu peux p.ex. définir que tout qui commence par "Roland" sera trouvé dans le dossier /src de ton site.
                        Tu peux définir Roland\Joomla et dire que c'est dans /src/joomla.
                        Etc.
                        Et définir un failback : si pas trouvé, alors de regarder dans tel ou tel folder (tu peux en préciser plusieurs).

                        Code:
                        {
                            "autoload": {
                                "psr-4": {"Roland\\": "src/"}
                            }
                        }
                        Quand tu adaptes composer.json, tu lances en ligne de commande un composer update afin que composer regénère ses fichiers. Ceux-ci sont stocké dans le dossier /vendor/composer. Tu as de multiples fichiers selon les normes utilisées (p.ex. PSR-4).

                        Composer.json est le fichier core pour le script vendor/autoload.php que tu dois charger dans ton script (pour Joomla, dans index.php). Tu fais un require_once (vendor/autoload.php).

                        Et le tour est joué.

                        Autoload met en place une instruction php spl_autoload_register qui est une fonction "magique" : elle est appellée par PHP lorsqu'il traite un script PHP qui fait appel à un namespace. spl_autoload_register permet d'enregistrer une fonction qui sera donc appellée et qui va traiter le "Mais où est donc définie la classe demandée?". Au travers des fichiers /vendor/composer/xxx.php ayant été généré par composer update; spl_autoload_register va savoir que Roland\ se trouve dans le dossier /src et que Roland\Joomla dans src/joomla.

                        Ca c'est pour les namespaces.

                        Ensuite quand tu dis que ton script utilise Roland\Joomla\Controller, du coup, spl_autoload_register sait qu'il doit charger le fichier controller.php; la dernière partie étant le nom du fichier à charger; fichier qui implémente la classe Controller (du même nom que le fichier).

                        Tu peux changer cette norme au travers du fichier composer.json ici aussi.

                        Voilà, ça, c'est mon utilisation des namespaces en dehors de Joomla.

                        Ma question était donc : sachant cela, la manière dont le autoloader de composer fonctionne, est-ce que JLoader a encore un sens puisque, de ma compréhension, cela fait la même chose...

                        JLoader ne deviendrait pas du coup inutile ? Question que je me suis posé à la lecture de ta proposition plus haut.

                        Bonne soirée.
                        dimitri.kft et alexandreelise aiment ceci.
                        Christophe (cavo789)
                        Mon blog, on y parle Docker, PHP, WSL, Markdown et plein d'autres choses : https://www.avonture.be
                        Logiciel gratuit de scan antivirus : https://github.com/cavo789/aesecure_quickscan (plus de 45.000 virus détectés, 700.000 fichiers sur liste blanche)​

                        Commentaire


                        • #13
                          Salut Christophe.

                          Merci pour ce complément d’informations (je me doutais que tu avais déjà pas mal "creusé" la question) .
                          Toutefois, je ne crois pas qu'il est nécessaire d'utiliser composer.
                          Dans la méthode magique php tu peux mettre ton code perso pour gérer l'autoload.

                          Le fond de ma réponse était plutôt que à mon avis les namespace et l'autoload sont bien moins souple que le système actuel, car vu que les namespaces sont gérés à la pré-compilation de PHP et non à l’interprétation, on perd le dynamisme qu'apporte la classe JLoader actuel.

                          Par exemple quand dans une méthode particulière j'ai besoin d'une classe "non standard", et bien je fais à ce moment seulement le JLoader pour enregistrer la classe et son fichier avant de l'utiliser.
                          Par ce système on pourrait même envisager d'avoir 2 variantes d'une classe de même nom dans 2 fichiers différents.

                          Toute cette souplesse on la perdrait si on abandonnait le JLoader au profit seul de l'autoload dépendant des namespace.
                          Dernière édition par roland_d_alsace à 22/02/2020, 12h45
                          A tous les utilisateurs de Joomla du très Grand Est de la France et du Jura suisse
                          Rejoignez le Joomla Users Groupe Alsace...
                          roland_d_alsace va-t-il devenir roland_du_grand_est ?

                          Commentaire

                          Annonce

                          Réduire
                          Aucune annonce pour le moment.

                          Partenaire de l'association

                          Réduire

                          Hébergeur Web PlanetHoster
                          Travaille ...
                          X