Lecture 4 minutes
Lorsque l'on souhaite aller plus loin dans le développement d'importantes fonctionnalités, on se retrouve confronté au problème classique de gestion d'un "boilerplate". Le code se complexifie ce qui augmente le nombre de classes PHP et fonctions nécessaires au bon fonctionnement de notre module/librairie/T800/... Pour palier à cela, bon développeur que nous sommes, mettons en place une architecture afin de remettre tout cela en ordre. Le résultat peut conduire à un certain nombre de fichiers qu'il nous faudra ensuite inclure dans notre projet : c'est à ce niveau-là que nous allons nous intéresser à ce que propose Sugar 7 avec son autoloader pour l'utilisation de "namespaces".
Pourquoi utiliser l'autoloader de Sugar 7 ?
Plus nous avons de fichiers, plus il faudra les inclures à des moments stratégiques de l'exécution de l'application tout en prenant garde de bien nommer les différentes classes pour ne pas générer de conflits de noms. Bien souvent, c'est dans cette situation que nous allons nous retrouver :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
require_once('custom/SuperLibs/SuperModule/SuperClass.php'); require_once('custom/SuperLibs/SuperModule/AbstractFeature.php'); require_once('custom/SuperLibs/SuperModule/SimpleFeature.php'); require_once('custom/SuperLibs/SuperModule/ComplexeFeature.php'); require_once('custom/SuperLibs/SuperModule/EasyStuffHelper.php'); require_once('custom/SuperLibs/Helper/EasyStuffHelper.php'); class SuperLibs_SuperModule_SuperClass extends SuperLibs_SuperModule_AbstractFeature { protected $complexeName = SuperLibs_SuperModule_ComplexeFeature::NAME; public function __construct() { $value = SuperLibs_Helper_EasyStuffHelper::retrieveValue(); new SuperLibs_SuperModule_EasyStuffHelper($value); ... |
Alors que l'on pourrait plus simplement avoir :
1 2 3 4 5 6 7 8 9 10 11 |
namespace SuperLibs\SuperModule; use SuperLibs\Helper\EasyStuffHelper as EasyStuffHelperBase; class SuperClass extends AbstractFeature { protected $complexeName = ComplexeFeature::NAME; public function __construct() { $value = EasyStuffHelperBase::retrieveValue(); new EasyStuffHelper($value); ... |
Sugar 7 dispose de son propre autoloader ("include/utils/autoloader.php") que nous pouvons utiliser pour simplifier la gestion de nos fichiers et de nos classes. Il y a pour cela 3 moyens d’interagir avec.
1 - Modifier "composer.json" pour inclure ses "namespaces"
Sugar 7 met à disposition son composer.json qui peut être utilisé avec composer afin d'altérer/augmenter les librairies utilisées dans Sugar. L'autoloader Sugar étant couplé avec celui de composer, l'ajout d'un module PHP par ce biais permettra de rendre ses sources accessibles au travers de l'application.
Voici un exemple parmi d'autres de ce qu'on a la possibilité de faire, pour cela nous allons dans le fichier "composer.json" afin d'inclure "superrepo/supermodule" :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
{ ... "require": { "psr/log": "1.0", "ruflin/elastica" : "v1.2.1.0", "onelogin/php-saml" : "2.1.0.1", "symfony/security-core": "v2.7.1", "symfony/security-csrf": "v2.7.1", "google/apiclient": "1.1.4", "php": ">=5.3.0", "superrepo/supermodule": "@stable" }, ... } |
Notre fichier "composer.json" est prêt à être utilisé, il nous faut donc ensuite mettre à jour nos librairies à partir de la commande "composer"
1 |
composer update --no-dev |
Notre librairie est maintenant chargée dans le dossier "vendor" et utilisable au travers de l'autoloader (le "namespace" a été inclus automatiquement dans "vendor/composer/autoload_psr4.php" et sera donc connu de l'application).
2 - Utiliser le "namespace" des scripts "custom" de Sugar 7
Sans modification particulière, il est possible d'utiliser des "namespaces" supportés par Sugar et utilisables à divers endroits comme dans les "Logic Hooks".
Les plus observateurs auront vu que dans le fichier "composer.json" cité précédemment, une entrée indique le comportement de l'autoloader notamment dans la gestion des "namespaces" :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
{ ... "autoload": { "psr-4": { "Sugarcrm\\Sugarcrm\\": [ "src/", "" ], "Sugarcrm\\Sugarcrm\\custom\\": [ "custom/src/", "custom/" ], "Sugarcrm\\Sugarcrm\\inc\\": "include/", "Sugarcrm\\Sugarcrm\\custom\\inc\\": "custom/include/" } }, "autoload-dev": { "psr-4": { "Sugarcrm\\SugarcrmTest\\": "test/" } }, ... } |
Il est donc possible de faire référence à une classe en utilisant directement les "namespaces" fournis par Sugar :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
// Sans namespace /* Fichier custom/SuperLibs/SuperModule/SuperClass.php * <?php * * require_once('custom/SuperLibs/AbstractSuper.php'); * require_once('custom/SuperLibs/SuperModule/SuperInterface.php'); * * class SuperLibs_SuperModule_SuperClass extends SuperLibs_AbstractSuper implements SuperLibs_SuperModule_SuperInterface {} */ require_once('custom/SuperLibs/SuperModule/SuperClass.php'); new SuperLibs_SuperModule_SuperClass(); // Avec namespace /* Fichier custom/SuperLibs/SuperModule/SuperClass.php * <?php * * namespace Sugarcrm\Sugarcrm\custom\SuperLibs\SuperModule; * * use Sugarcrm\Sugarcrm\custom\SuperLibs\AbstractSuper; * * class SuperClass extends AbstractSuper implements SuperInterface {} */ new Sugarcrm\Sugarcrm\custom\SuperLibs\SuperModule\SuperClass(); |
3 - Déclarer son propre "namespace"
La solution 2 implique une dépendance à Sugar ce qui n'est pas forcement ce que l'on souhaite dans un contexte de librairie plus généralisé. Dans cette optique, il y a un moyen de déclarer à Sugar un ou des "namespaces" à inclure pour l'indexation de nos fichiers au travers de son autoloader.
1 |
SugarAutoLoader::addNamespace('SuperLibs\\', 'custom/SuperLibs', 'psr4'); |
Il y a différents moyens d'altérer "SugarAutoLoader" que faire un appel à "custom/include/utils/autoloader.php" pour réécrire le fichier avec notamment l'utilisation du framework Extension qui dispose d'un point d'entrée "Utils" servant à ce genre de manipulation :
1 2 3 4 |
/* Fichier custom/Extension/application/Ext/Utils/SuperLibs.php */ if (!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point'); require_once('include/utils/autoloader.php'); SugarAutoLoader::addNamespace('SuperLibs\\', 'custom/SuperLibs', 'psr4'); |
Ce type de modification à partir du framework Extension nécessite une "Réparation Rapide et Reconstruction", une fois effectuée, votre "namespace" est accessible comme partout ailleurs.
Conclusion
Chaque solution a son lot d'avantages et d’inconvénients et dépend principalement de ce que l'on souhaite atteindre comme but pour nos développements. Il est relativement simple de passer du choix 1 au 3 mais la solution 2 peut nécessiter un important refactoring si vous deviez changer d'architecture dans le but d'externaliser votre code de Sugar. Gardez cela en tête si la question sur les "namespaces" venaient à se poser.
use Happy\Coding\With\Namespaces as SugarDeveloper;
Référence : https://developer.sugarcrm.com/2014/10/15/quick-tip-psr-0-namespaces-in-sugar-7/