vendredi 27 juin 2014

Service avec accès au container sans code 2

Dans un billet précédent ( http://steevan-barboyon.blogspot.fr/2014/05/service-avec-acces-au-container-sans.html ), je vous parlais de la class abstraite Symfony\Component\DependencyInjection\ContainerAware qui permet d'ajouter une propriété $container et une méthode setContainer.

Seulement voilà, PHP ne gère pas l'héritage multiple, donc si votre service étend déjà d'une classe vous ne pouvez pas utiliser ContainerAware. Un exemple tout simple : une extension Twig.

Symfony2 ne fournissant pas encore de trait avec la même fonctionnalité que ContainerAware, vous pouvez installer le bundle steevanb/utilsbundle, qui vous fournira ce trait.
# composer.json { "require": { "steevanb/utilsbundle": "1.*" } }
Définition du service, exactement la même qu'avec le ContainerAware fournit par Symfony 2 :
# Resources/config/services.yml services: myservice: class: Foo\BarBundle\Service\MyService calls: - [ setContainer, [ @service_container ] ]
Le code du service, qui ne fait que utiliser le trait steevanb\UtilsBundle\Model\ContainerAware :
# Service/MyService.php <?php namespace Foo\BarBundle\Service use steevanb\UtilsBundle\Model\ContainerAware; class MyService { use ContainerAware; }

9 commentaires:

  1. Je ne vois pas l'intérêt par rapport à la première méthode que tu décris dans ton billet précédent ?
    A ce que je comprends, tu remplaces juste 3 lignes de code par l'ajout d'un nouveau bundle

    RépondreSupprimer
  2. Je remplace surtout une classe abstraite par un trait, ce qui veut dire que même un service qui étend d'une classe peut avoir accès au container sans écrire un __construct contraignant.

    L'ajout d'un bundle n'est au final qu'un objet de plus, et ce bundle permettra dans le futur d'ajouter des tas de ptites choses qu'il manque dans Symfony2.

    RépondreSupprimer
  3. dans le fond c'est pas mal, mais je pense que ça résume bien :
    https://www.flickr.com/photos/steevan/5038769759/

    RépondreSupprimer
  4. Un tocard de marseillais qui se cache derrière un Anonyme, comme d'hab :p

    RépondreSupprimer
  5. Meme commentaire que @Guillaume. Difficile de voir l'utilité d'une telle librairie sachant que :
    - Ajouter un bundle pour 3 lignes de configurations... Bof
    - Le fait que Symfony 2 est prévu pour PHP 5.3 et que la tu nous obliges a passer en 5.4
    - Passer le container a un service n'est pas une best practice ;)

    RépondreSupprimer
  6. Des petites explications :

    - En sois le bundle aujourd'hui n'est pas "utile", puisqu'on peut très bien utiliser le trait sans installer le bundle. Mais j'ai préféré directement faire un bundle, puisque l'idée c'est d'ajouter des petites features qui ne sont pas intégrées dans SF2, et qui manquent à mes yeux. Le trait en est un exemple.

    - Je n'oblige personne à passer en 5.4, je permet à ceux qui ont arrêté d'utiliser un PHPqui date de plus de 5 ans d'avoir accès à un trait pratique pour eux. Les autres, ils n'utilisent pas le bundle ;)

    - Ok, donc pourquoi avoir mit une classe ContainerAware ? Tu veux dire que les best practice de SF2 ne sont pas respectées par SF2 ?
    Je pense au contraire que passer le container est utile dans énormément de cas, si par exemple mon service doit récupérer des paramètres. Si tu passes des paramètres à ton service, et que leur valeur change, ton service n'en aura pas l'information, et aura donc une valeur erronée.
    Ensuite, je préfère largement arriver sur un service qui a le container, pluttôt que de voir une déclaration de service avec 3 / 4 / 5 paramètres, et de voir un __construct qui stocke ces valeurs dans des propriétés privées. Chacun ses goûts :)

    RépondreSupprimer
  7. - Ok, je comprend la démarche de la creation d'un bundle. Mais la c'est plus un fourre-tout qu'un vrai bundle... Bref passons ce point ! Note juste que SF2 est un outils d'aide au développement pas un language. Les traits sont des instructions langage. Libre a chacun de les utiliser ou non, et ce n'est pas a Sensio de les rendre obligatoire ou non (et non stp, ne me dit pas "oui mais les namespaces"...)

    - Un peu quand même. C'est un peu "Hey les gars regardez, je vous fournis du code mais qui fonctionnera seulement si vous passer a 5.4, pour les autres, bah tant pis". On peut parfois demander une nouvelle dependance (curl par exemple) mais pas une telle mise à jour, surtout de php... Un peu dommage...
    Si tu souhaites vraiment faire une librairie utile par tous et pour tous, pense à ceux qui doivent rester en 5.3 et/ou qui ne peuvent utiliser les traits (hhvm par exemple).

    - SF2 est un outil d'aide au développement et doit influer le moins possible sur ton vrai code métier (model et services). Beaucoup trop de développeurs (moi le premier) faisons le contraire de cela.
    Dans les best practices, il est conseillé (pas obligé) d’éviter de passer le container a un service.
    Pourquoi ? La raison est simple : créer un service qui pourra être réutilise dans un autre framework sans trop de difficulté (ou via d'autre DI tel que Pimple). Le container est un élément du noyau même de SF. Vu que les controllers sont déjà trop liés au container, il est conseillé d'utiliser le plus possible les services (déportation du code métier des controllers vers les services) et de n'avoir qu'en entré de celui-ci des objets simples et facilement identifiable.
    Passer le container à un service signifie fournit un objet trop générique pouvant dépendre de l'environnement et du framework utilisé, soit une jolie boite noire qu'il faudra de plus recréer si tu déplace ton projet vers une autre sans container ou que tu modifies le contenu de ton/tes services pour que ça fonctionne. Il est vrai que la facilité est de balancer tout en une fois, mais il y a trop de contrainte a mon gout qui peuvent être prévue dès le début .
    Ton service doit travailler avec des entités : passe lui un manager
    Ton service a besoin d'un autre service (trad ou url) : passe lui.

    Pour ma part, je préféré voir une déclaration de service avec 3 / 4 / 5 paramètres, ou je peux surcharger facilement chacun d'entre eux ;) Oui chacun ses goûts et chacun sa responsabilité sur ce qui juge bon de faire pour son code mais un peu déçu des arguments "oui mais ça existe" ou encore "oui mais eux respectent rien".

    Il existe une fonction "rm -rf /" qui existe, mais je ne suis pas près de l'utiliser même si nous connaissons tous les deux, des personnes capables de le faire ;)

    PS1 : Un article sur les best practices serait le bienvenu
    PS2 : Ca fait plaiz d'avoir des nouvelles
    PS3 : La photo précédente n'est pas de moi
    PS4 : Ton profil google fait un peu flippay :D

    RépondreSupprimer
  8. Oula je viens de faire un sacré texte oO

    Excuse moi :D

    RépondreSupprimer
  9. Oui, c'est un fourre tout, d'où le nom ;)
    J'ai bien compris que SF2 n'est pas un langage. Mais je ne force personne à utiliser les traits, j'offre juste cette possibilité, qui manque dans SF2 et que j'utilise souvent. Du coup plutôt que recoder ça à tout va, ou d'avoir un __construct (ou et setContainer) codé dans chacun de mes services ...

    Et si, je vais parler des namespaces ou de ce que Sensio t'oblige à avoir quand tu as SF2. Ils font un framework compatible avec une certaine version de PHP et compagnie, mais libre aux bundles de changer ça si ils en ont besoin. Si on fait comme tu dis, on peut aussi se dire "hey merde, mais il marche pas avec PHP3 leur framework !".
    De plus, le bundle ne te force pas du tout une version de PHP, tu peux très bien l'installer et ne pas utiliser le trait.

    Je suis d'accord sur l'explication pour la réutilisabilité du code dans d'autres framework. Mais dans la pratique, soyons honnête, je m'en fou complètement. Je travaille avec SF2, pas avec Zend ou autres. Le jour ou je décide de changer de framework, c'est pas le container passé à unservice qui sera le problème ;)
    Ou alors à ce compte-là, SF2 n'offre pas de gestion de bundle, ce serait un projet externe utilisé par tous les frameworks (comme Twig, Doctrine etc). A ce compte-là, ok, mais là, un bundle est "forcément" ultra lié à SF2.

    Je n'ai rien affirmé concernant "ils respectent rien", je te pose la question : tu en pense quoi de cette best-practice, sachant que SF2 te fournit l'outil pour ne pas la respecter ?

    Aha, du coup maintenant j'en connais 2 qui sont capables de le faire rm -rf / ;)

    Honnêtement je ne pense pas avoir le niveau pour un article sur les best practice.

    Ouais clair ça fait plaisir :) J'avais envoyé un mail y'a quelques temps à Jo, il m'a pas répondu, je me suis dit que vous faisiez la tronche ...

    Te moque pas de mon profil Google, il me ramène du boulot ;)

    RépondreSupprimer