{"id":18812897,"url":"https://github.com/pantaflex44/pdic","last_synced_at":"2026-01-12T04:30:14.550Z","repository":{"id":134816815,"uuid":"435006091","full_name":"pantaflex44/Pdic","owner":"pantaflex44","description":"Librairie PHP gérant l'injection de dépendances par la méthode du conteneur.","archived":false,"fork":false,"pushed_at":"2021-12-05T20:12:09.000Z","size":18,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2024-12-30T00:23:47.801Z","etag":null,"topics":["container","dependency-injection","library","open-source","php"],"latest_commit_sha":null,"homepage":"","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/pantaflex44.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-12-04T20:49:41.000Z","updated_at":"2021-12-05T20:12:12.000Z","dependencies_parsed_at":null,"dependency_job_id":"4ec21146-c261-4469-b4f6-2180c82d8faa","html_url":"https://github.com/pantaflex44/Pdic","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pantaflex44%2FPdic","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pantaflex44%2FPdic/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pantaflex44%2FPdic/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pantaflex44%2FPdic/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pantaflex44","download_url":"https://codeload.github.com/pantaflex44/Pdic/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":239748295,"owners_count":19690237,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["container","dependency-injection","library","open-source","php"],"created_at":"2024-11-07T23:35:31.989Z","updated_at":"2026-01-12T04:30:14.508Z","avatar_url":"https://github.com/pantaflex44.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"# **@Pdic** - PHP Dependency Injection Class\n\n## Sommaire\n\n1) [Introduction](#introduction)\n2) [Installation](#installation)\n3) [Injections](#injections):\n    - [Injections sélectives](#iselective)\n    - [Autowiring](#iclasses)\n    - [Paramètres personnels](#imethodes)\n4) [Stockage des paramètres personnels](#parametres)\n5) [Invocation de méthodes](#invoke)\n6) [Licence et Utilisations](#licence)\n7) [A propos](#apropos)\n\n\u003cbr\u003e\n\n\u003ca name=\"introduction\"\u003e\u003c/a\u003e\n\n## Introduction\n\nTout d'abord, l'injection de dépendance est un [Design Pattern](https://refactoring.guru/fr/design-patterns). Par ailleurs, en PHP, une normalisation est proposée pour ce Pattern: [PSR-11](https://www.php-fig.org/psr/psr-11/).\nL'injection de dépendances s'inscrit dans les principes de la programmation objet ([POO](https://grafikart.fr/formations/programmation-objet-php)).\n\nL'injection de dépendances est un mécanisme visant à simplifier la transmission de services, d'instances d'objets communs au sein d'une application.\n\nIl est souvent pratiqué de transmettre de classes en classes, l'instance d'un objet, par exemple, regroupant des fonctionnalités d'utilisations communes. Plutôt fastidieux et difficilement maintenanble comme le montre cet exemple en PHP:\n\n```php\n\u003c?php\n\nclass User\n{\n\n    private string $name;\n\n    public function __construct(string $name = 'bob') {\n        $this-\u003ename = $name;\n    }\n\n    public function setName(string $name) {\n        $this-\u003ename = $name;\n    }\n\n    public function getName(): string {\n        return $this-\u003ename;\n    }\n\n}\n\nclass FirstTreatment\n{\n\n    private User $user;\n\n    public function __construct(User $user) {\n        $this-\u003euser = $user;\n    }\n\n    public function execute(string $prefix): string {\n        return $prefix . strtoupper($this-\u003euser-\u003egetName());\n    }\n\n}\n\nclass SecondTreatment\n{\n\n    private User $user;\n\n    public function __construct(User $user) {\n        $this-\u003euser = $user;\n    }\n\n    public function execute(string $prefix): string {\n        return $prefix . strtolower($this-\u003euser-\u003egetName());\n    }\n\n}\n\nclass UserFormatter\n{\n\n    private User $user;\n\n    public function __construct(User $user) {\n        $this-\u003euser = $user;\n    }\n\n    public function toUpper(string $prefix = '@'): string\n    {\n        $treatment = new FirstTreatment($this-\u003euser);\n        return $treatment-\u003eexecute($prefix);\n    }\n\n    public function toLower(string $prefix = '@'): string\n    {\n        $treatment = new SecondTreatment($this-\u003euser);\n        return $treatment-\u003eexecute($prefix);\n    }\n\n}\n```\n\nQue nous utiliserions comme suit:\n\n```php\n\u003c?php\n\n$user = new User('Christophe');\n\n$formatter = new UserFormatter($user);\n\nvar_dump($formatter-\u003etoLower());\nvar_dump($formatter-\u003etoUpper());\n\n// string(11) \"@christophe\"\n// string(11) \"@CHRISTOPHE\"\n```\n\nDans l'exemple ci-dessus, tout le monde dépend de tout le monde et l'instance de l'objet *User* se transmet de classes en classes.\n\nUne solution existe: **L'injection de dépendances**\n\nPour celà, je vous propose une toute petite librairie PHP, très simple d'utilisation, et parfaitement efficace, pouvant répondre à 3 besoins particuliers en reposant sur 2 principes:\n\n- L'injection par ***Container*** de dépendances identifiées\n- Liaisons automatiques des dépendances, aussi appelée ***Autowiring***\n\n\u003cbr\u003e\n\n\u003ca name=\"installation\"\u003e\u003c/a\u003e\n\n## Installation\n\nEncore une fois, simplicité est maitre mot.\n\nCopiez/Collez le dossier *'pdic'* et son contenu dans le dossier de votre choix (par exemple: *'libs'*) au niveau de votre applications. Puis, dans le script principal de celle-ci, intégrez **@Pdic** comme suit:\n\n```php\n\u003c?php\n....\n\nnamespace MonApplie;\n\nrequire_once './libs/pdic/pdic.inc.php';\n\nuse Libs\\Pdic\\Pdic;\n\n....\n```\n\nEt c'est tout!\n\nPassons à l'utilisation.\n\n\u003cbr\u003e\n\n\u003ca name=\"injections\"\u003e\u003c/a\u003e\n\n## Utilisations\n\n**@Pdic** repose sur l'utilisation d'un conteneur de dépendances accessible partout au sein de l'application qui l'utilise. Par ailleurs, ce conteneur peut être alimenté tout au long de l'éxécution de celle-ci pour s'adapter aux situations facilement. Toutefois, et malgré une relative souplesse, des principes sont à respecter.\n\nNous allons en aborder les 3 principaux.\n\n\u003ca name=\"iselective\"\u003e\u003c/a\u003e\n\n### Injections sélectives\n\nL'*injection sélective* est le premier principe proposé par **@Pdic**. Ce principe rend accessible de partout toutes classes connues et instanciables dans votre application. Ceci permet donc de charger une classe et de réutiliser une seule et unique même instance à chaque fois que vous en auriez besoin.\n\nDans l'exemple proposé en [introduction](#introduction), nous avions créé deux classes *FirstTreatment* et *SecondTreatment*. Ce sont des outils de traitement, travaillant toutes deux sur le nom d'un utilisateur. Tantôt, pour le mettre en minuscule, tantôt pour le mettre en majuscule.\n\nEtant de simple outils fonctionnels, nous pourrions en avoir besoin à plusieurs reprises dans le code de l'application. Par exemple, nous pourrions avoir besoin de traiter plusieurs utilisateurs. Nous aurons aussi surement besoin de ranger proprement ces outils dans un dossier précis.\n\nCertains diront, un Design Pattern connu pourrait répondre à ce besoin: [**Le Singleton**](https://grafikart.fr/tutoriels/singleton-569). Certes. Mais celà ne resoudrait pas notre problème de dépendances courreuses de classes.\n\n**@Pdic** propose donc une solution pouvant regrouper ces 2 concepts.\n\nReprenons l'exemple ci-dessus:\n\n```php\nclass UserFormatter\n{\n\n    private User $user;\n\n    public function __construct(User $user) {\n        $this-\u003euser = $user;\n    }\n\n    public function toUpper(): string {\n        $treatment = new FirstTreatment($this-\u003euser);\n        return $treatment-\u003eexecute('@');\n    }\n\n    public function toLower(): string {\n        $treatment = new SecondTreatment($this-\u003euser);\n        return $treatment-\u003eexecute('@');\n    }\n\n}\n```\n\nLa classe *UserFormatter* instancie à chaque fois les 2 outils de traitement pour assouvir ses besoins. A chaque fois, nous griognotons un peu plus sur la mémoire et donc les performances de notre application.\n\nCes outils, non seulement, fixes, rangés, et surement regroupés au sein d'un espace de nom leur étant propre, nécessite qu'on leur passe en paramètre du constructeur une instance d'objet *User*!\n\nNous pourrions peut être simplifier par:\n\n```php\n// Définit un nouvel utilisateur puis stocke cette instance\n// pour être injectée partout où un type User sera demandé.\nPdic::set(new User('Christophe'));\n\n// Retourne l'instance de la class UserFormatter.\n// Comme on le constate, l'utilisateur n'a plus besoin d'être définit\n// à ce stade! Il vient d'être automatiquement injecté dans le constructeur\n// de l'objet UserFormatter lors de sa première instanciation!\n$formatter = Pdic::get(UserFormatter::class);\n\nvar_dump($formatter-\u003etoLower());\nvar_dump($formatter-\u003etoUpper());\n\n// le résultat est le même, victoire de canard!\n// string(11) \"@christophe\"\n// string(11) \"@CHRISTOPHE\"\n```\n\nSimplicité et performances réunies! Mais un gros bémol réside dans cette pratique...\nImpossible de formatter plusieurs utilisateurs différents!\n\n```php\nPdic::set(new User('Christophe'));\n\n$formatter1 = Pdic::get(UserFormatter::class);\nvar_dump('-\u003e formatter1');\nvar_dump($formatter1-\u003etoLower());\nvar_dump($formatter1-\u003etoUpper());\n\n$formatter2 = Pdic::get(UserFormatter::class);\nvar_dump('-\u003e formatter2');\nvar_dump($formatter2-\u003etoLower());\nvar_dump($formatter2-\u003etoUpper());\n\nvar_dump('-\u003e formatter1 === formatter2');\nvar_dump($formatter1 === $formatter2);\n\n// string(13) \"-\u003e formatter1\"\n// string(11) \"@christophe\"\n// string(11) \"@CHRISTOPHE\"\n// string(13) \"-\u003e formatter2\"\n// string(11) \"@christophe\"\n// string(11) \"@CHRISTOPHE\"\n// string(28) \"-\u003e formatter1 === formatter2\"\n// bool(true)\n```\n\nNous constatons, non seulement, que les 2 *$formatter* sont exactement la même instance de la classe *UserFormatter* (le principe du Singleton) mais qu'en plus, ils se partagent le même utilisateur!\n\nCe phénomène pouvant devenir une lacune dans certains cas c'est pourquoi **@Pdic** propose les 2 solutions suivantes.\n\n\u003ca name=\"iclasses\"\u003e\u003c/a\u003e\n\n### Dépendences dans les méthodes de classes - Autowiring\n\nPrenons un nouvel exemple:\n\n```php\nclass Renderer\n{\n    protected string $identity = \"i'm the common renderer\";\n\n    public function render(string $message)\n    {\n        var_dump($this-\u003eidentity);\n        var_dump($message);\n    }\n}\n\nclass HtmlRenderer extends Renderer\n{\n    protected string $identity = \"i'm the HTML renderer\";\n}\n\nclass JsonRenderer extends Renderer\n{\n    protected string $identity = \"i'm the JSON renderer\";\n}\n\nclass Response\n{\n    private Renderer $renderer;\n\n    public function __construct(Renderer $renderer)\n    {\n        $this-\u003erenderer = $renderer;\n    }\n\n    public function send(string $message = 'mon message')\n    {\n        $this-\u003erenderer-\u003erender($message);\n    }\n}\n\n$response = Pdic::get(Response::class);\n$response-\u003esend(\"bob est grand\");\n\n// string(23) \"i'm the common renderer\"\n// string(13) \"bob est grand\"\n```\n\nCet exemple simule une réponse que pourrait envoyer un *Controller* à la fin de son traitement.\n\nPour ce faire, nous déclarons utiliser 2 principaux objets, un *Renderer* chargé de convertir la réponse au format souhaité, et l'objet *Response* lui même contenant les actions disponibles pour le *Controller*.\n\n```php\n/*\nclass Response\n{\n    private Renderer $renderer;\n\n    public function __construct(Renderer $renderer)\n    {\n....\n*/\n\n$response = Pdic::get(Response::class);\n```\n\nNous instancions une nouvelle réponse. Mais comme vous le constatez, nous ne passons pas en paramètre du constructeur, l'instance d'un objet *Renderer* attendu. **@Pdic** s'occupe de tout!\n\nToutefois, **@Pdic** ne sait qu'instancier un objet dont il reconnait le type définit pour un argument du constructeur. Dans notre cas, le paramètre *$renderer* est un objet *Renderer*.\n\nAlors comment faire pour définir un moteur de rendu spécifique? Comment dire à **@Pdic** d'instancier tel ou tel moteur de rendu lorsqu'il reconnait un argument de type *Renderer* ?\n\nEncore une fois, simplicité de mise, il suffit juste de lui dire ;-) Et pour celà, nous avons a notre disposition, **les définitions**.\n\n\n```\nPdic::setDefinition($parentClass, $methodName, [\n    $paramClass =\u003e $classInstance,\n]);\n```\n\n```php\nPdic::setDefinition(Response::class, '__construct', [\n    Renderer::class =\u003e new HtmlRenderer(),\n]);\n\n$response = Pdic::get(Response::class);\n$response-\u003esend(\"bob est grand\");\n\n// string(21) \"i'm the HTML renderer\"\n// string(13) \"bob est grand\"\n```\n\nMagique !\n\nNotre réponse est désormais prise en charge par le moteur de rendu HTML ! Désormais **@Pdic** convertira automatiquement le paramêtre définissant le moteur de rendu en une instance du moteur de rendu HTML.\n\nBien évidement, nous pouvons dire à **@Pdic** d'injecter à tous les objets possédant la méthode *__construct* et un paramètre du type *Renderer*:\n\n```php\nPdic::setDefinition('*', '__construct', [\n    Renderer::class =\u003e new HtmlRenderer(),\n]);\n```\n\nNous pouvons aussi lui dire d'injecter le paramètre à toute les méthodes d'une classe possédant un argument de ce type!\n\n```php\nPdic::setDefinition(Response::class, '*', [\n    Renderer::class =\u003e new HtmlRenderer(),\n]);\n```\n\nEt même, ordonner à **@Pdic** d'injecter à toute les classes, et méthodes:\n\n```php\nPdic::setDefinition('*', '*', [\n    Renderer::class =\u003e new HtmlRenderer(),\n]);\n```\n\nCas pratique:\n\n```php\n// $_ENV['MyAppType'] = 'api';\n$_ENV['MyAppType'] = 'api';\n\n$envType = isset($_ENV['MyAppType'])\n    ? strtolower(trim($_ENV['MyAppType']))\n    : '';\n\n$renderer = new HtmlRenderer();\nif ($envType == 'api') {\n    $renderer = new JsonRenderer();\n}\n\nPdic::setDefinition(Response::class, '*', [\n    Renderer::class =\u003e $renderer,\n]);\n\n$response = Pdic::get(Response::class);\n$response-\u003esend(\"message to render\");\n```\n\n\u003ca name=\"imethodes\"\u003e\u003c/a\u003e\n\n### Dépendances dans les méthodes de classes - Paramètres personnels\n\nModifions la classe *Response* comme suit:\n\n```php\nclass Response\n{\n    private Renderer $renderer;\n\n    public function __construct(Renderer $renderer, string $commonParam)\n    {\n        $this-\u003erenderer = $renderer;\n        var_dump($commonParam);\n    }\n\n    public function send(string $message = 'mon message')\n    {\n        $this-\u003erenderer-\u003erender($message);\n    }\n}\n\n$response = Pdic::get(Response::class);\n$response-\u003esend(\"message to render\");\n```\n\nLe constructeur prend un nouvel argument *$commonParam*.\n\nSi nous executons le code tel quel, PHP vient nous répréhender:\n\n```\nFatal error: Uncaught Exception: Unknown param `commonParam` in /home/christophe/OneDrive/Documents/Projets/Php/Framel/libs/pdic/pdic.inc.php:177 Stack trace: #0 /home/christophe/OneDrive/Documents/Projets/Php/Framel/libs/pdic/pdic.inc.php(251): Framel\\Libs\\Pdic\\Pdic::resolve() #1 /home/christophe/OneDrive/Documents/Projets/Php/Framel/libs/pdic/pdic.inc.php(287): Framel\\Libs\\Pdic\\Pdic::instanciate() #2 /home/christophe/OneDrive/Documents/Projets/Php/Framel/framel.php(64): Framel\\Libs\\Pdic\\Pdic::get() #3 {main} thrown in /home/christophe/OneDrive/Documents/Projets/Php/Framel/libs/pdic/pdic.inc.php on line 177\n```\n\nEt il aura raison! A aucun moment nous definissons ce paramètre dans le constructeur!\n\nUne solution existe. Pour celà, il faut définir les paramètres personnels dans un tableau que l'on ajoutera aux méthodes *Pdic::get()* et *Pdic::invoke()*:\n\n```php\n....\n\n$response = Pdic::get(Response::class, [\n    Response::class =\u003e [\n        '__construct' =\u003e [\n            'commonParam' =\u003e \"yeah! i'm the commonParam and i'm defined!\",\n        ],\n    ]\n]);\n$response-\u003esend(\"message to render\");\n```\n\nNous pouvons traduire les lignes ci-dessus par:\n- Je créé une instance de la classe *Response*, et je definis pour la méthode *__construct* de la classe *Response*, le paramètre *commonParam* avec la valeur *\"yeah! i'm the commonParam and i'm defined!\"*.\n\n\u003cbr\u003e\n\n\u003ca name=\"parametres\"\u003e\u003c/a\u003e\n\n## Stockage des paramètres personnels\n\nPlus haut, je vous ai expliqué comment définir les paramètres personnels pour les méthodes d'instanciation et d'invocation. Nous passions directement comme argument de ces méthodes, un tableau contenant les informations personnelles à injecter.\n\nMais cette solution implique d'injecter ces paramètres à chaque fois que l'on peut en avoir besoin. \n\nSi dans votre code, vous ayez besoin ou soyez obligés de définir ces paramètres personnels en amont, **@Pdic** vous propose une nouvelle fois un outil bien pratique: **Le stockage des paramètres**.\n\n```php\npublic static function setParameters(string $class, array $parameters): void\n```\n\nCette fonction prend 2 arguments:\n- ***$class*** \n    - Classe / Objet qui sera concerné par les paramètres\n- ***$parameters*** \n    - Tableau associatif contenant les méthodes concernées et leurs paramètres, découpé comme suit:\n        ```php\n        [\n            'nom de la méthode1' =\u003e [\n                'nom du parametre1' =\u003e 'sa valeur',\n                'nom du parametre2' =\u003e 'sa valeur',\n            ],\n            'nom de la méthode2' =\u003e [\n                'nom du parametre1' =\u003e 'sa valeur',\n                'nom du parametre2' =\u003e 'sa valeur',\n            ],\n        ]\n        ```\n\nPour exemple nous pourrions avoir:\n\n```php\nclass MyClass1 {\n\n    public function myMethod1(string $theParam) {\n\n    }\n\n    public function myMethod2(string $theOtherOrSameParam) {\n        \n    }\n\n}\n\nPdic::setParameters(MyClass1::class, [\n    'myMethod1' =\u003e [\n        'theParam' =\u003e 'the first value',\n    ],\n    'myMethod2' =\u003e [\n        'theOtherOrSameParam' =\u003e 'the second value',\n    ],\n]);\n```\n\n\u003cbr\u003e\n\n\u003ca name=\"invoke\"\u003e\u003c/a\u003e\n\n## Invocation de méthodes\n\nDepuis le début nous voyons comment utiliser les classes et leurs instanciations. Mais parfois, une classe ne possède pas de constructeur! **@Pdic** y a pensé et propose sa solution: *Pdic::invokde()*\n\n```\npublic static function invoke(string $class, string $methodName, array $methodParams = [])\n```\n\nMaintenant que vous connaissez un peu mieux **@Pdic**, completons notre précédent exemple:\n\n```php\nclass Renderer\n{\n    protected string $identity = \"i'm the common renderer\";\n\n    public function render(string $message)\n    {\n        var_dump('renderer: ' . $this-\u003eidentity);\n        var_dump('rendered message: ' . $message);\n        var_dump('------------------------');\n    }\n}\n\nclass HtmlRenderer extends Renderer\n{\n    protected string $identity = \"i'm the HTML renderer\";\n}\n\nclass JsonRenderer extends Renderer\n{\n    protected string $identity = \"i'm the JSON renderer\";\n}\n\nclass Response\n{\n    private Renderer $renderer;\n\n    public function __construct(Renderer $renderer)\n    {\n        $this-\u003erenderer = $renderer;\n    }\n\n    public function set(string $message)\n    {\n        $this-\u003erenderer-\u003erender($message);\n    }\n}\n\nclass Engine\n{\n    public function __construct($name = 'engine')\n    {\n        $this-\u003ename = $name;\n    }\n}\n\nclass MyController1\n{\n    public function home(Engine $engine, Response $response, string $title)\n    {\n        var_dump('controller title: ' . $title);\n        var_dump('engine: ' . $engine-\u003ename);\n\n        $response-\u003eset(\"ma page home\");\n    }\n\n    public function contact(Engine $engine, Response $response, string $title)\n    {\n        var_dump('title: ' . $title);\n        var_dump('engine: ' . $engine-\u003ename);\n\n        $response-\u003eset(\"ma page contact\");\n    }\n}\n\n// préparation des injections\n\nPdic::setDefinition(Response::class, '*', [\n    Renderer::class =\u003e new HtmlRenderer()\n]);\n\nPdic::setDefinition(MyController1::class, 'home', [\n    Engine::class =\u003e new Engine(\"i'm the home engine\")\n]);\nPdic::setDefinition(MyController1::class, 'contact', [\n    Engine::class =\u003e new Engine(\"i'm the contact engine\")\n]);\n\nPdic::setParameters(MyController1::class, [\n    'home' =\u003e ['title' =\u003e 'page home'],\n    'contact' =\u003e ['title' =\u003e 'page contact']\n]);\n\n// puis au moment venu, appelons les différents *Controllers*\n\nPdic::invoke(MyController1::class, 'home');\nPdic::invoke(MyController1::class, 'contact');\n\n// var_dump\n// --------\n// string(27) \"controller title: page home\"\n// string(27) \"engine: i'm the home engine\"\n// string(31) \"renderer: i'm the HTML renderer\"\n// string(30) \"rendered message: ma page home\"\n// string(24) \"------------------------\"\n// string(19) \"title: page contact\"\n// string(30) \"engine: i'm the contact engine\"\n// string(31) \"renderer: i'm the HTML renderer\"\n// string(33) \"rendered message: ma page contact\"\n// string(24) \"------------------------\"\n```\n\n\u003cbr\u003e\n\n\u003ca name=\"licence\"\u003e\u003c/a\u003e\n\n## Licence et Utilisations\n\nLa licence donne à toute personne recevant le logiciel (et ses fichiers) le droit illimité de l'utiliser, le copier, le modifier, le fusionner, le publier, le distribuer, le vendre et le « sous-licencier » (l'incorporer dans une autre licence). La seule obligation est d'incorporer la notice de licence et de copyright dans toutes les copies.\n\n\n\u003e Copyright (c)2021 Christophe LEMOINE\n\u003e\n\u003e Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\u003e\n\u003e The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\u003e\n\u003e THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n\n\u003cbr\u003e\n\n\u003ca name=\"apropos\"\u003e\u003c/a\u003e\n\n## A propos\n\n\u003e *Auteur*: Christophe LEMOINE\u003cbr\u003e\n\u003e *Email*: pantaflex@hotmail.fr\u003cbr\u003e\n\u003e *Url*: [https://github.com/pantaflex44/Pdic](https://github.com/pantaflex44/Pdic)\u003cbr\u003e\n\u003e *Copyright*: Copyright (c)2021 Christophe LEMOINE\u003cbr\u003e\n\u003e *Licence*: [MIT License](https://github.com/pantaflex44/Pdic/LICENSE)\n\n\u003cbr\u003e","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpantaflex44%2Fpdic","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpantaflex44%2Fpdic","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpantaflex44%2Fpdic/lists"}