web-dev-qa-db-fra.com

Comment puis-je faire en sorte que mes PHP IDE comprennent les conteneurs d'injection de dépendances)?

Situation actuelle: J'ai des dépendances dans mon projet que je résous en utilisant l'injection de dépendances. Je veux passer à la prochaine étape logique en utilisant un conteneur d'injection de dépendance (DIC) pour faciliter la gestion de mes dépendances et des classes de chargement différé.

J'ai regardé Bucket , Pimple , et sfServiceContainer , j'ai effectué un test et j'ai vraiment apprécié le fonctionnement de DIC. Je choisirais probablement Pimple en raison de sa simplicité et de sa puissance brute. Si je n'ai pas eu ce problème:

En raison de l'abstraction que propose DIC, le IDE que j'utilise (PHPStorm) ne comprend plus ce qui se passe dans mon code. Il ne comprend pas que $ container ['mailer'] ou $ sc-> mailer contient un objet de classe. J'ai aussi essayé Netbeans IDE: même problème.

C'est vraiment un problème pour moi parce que mon IDE devient inutile. Je ne veux pas programmer sans outils de code, d'auto-complétion et d'outils de refactoring lors du traitement des classes. Et je ne veux pas que mon = IDE pour trouver toutes sortes de faux positifs lors de la validation du code.

Ma question est donc la suivante: quelqu'un a-t-il résolu ce problème et trouvé une solution?

64
Blaise

Vous pouvez définir la classe de la variable "manuellement":

/** @var YourClassType $mailer */
$mailer = $container['mailer'];

Dans PhpStorm (et par standards ), utilisez deux astérisques et écrivez le type de données avant le nom de la variable.

Vous pouvez écrire le type de données sans le nom de la variable (mais pas le nom sans le type de données).

57
OZ_

Bien que vous puissiez certainement indiquer à votre IDE le type d'objet retiré de votre conteneur à chaque fois que vous y accédez, il vaut mieux le faire une fois. Les deux solutions suivantes impliquent de sous-classer le conteneur. Je viens de commencer à utiliser Pimple qui recommande de le faire quand même.

Pour les conteneurs qui utilisent des membres d'instance accessibles avec -> ou exposé via la magie __get méthode, vous pouvez dire à votre IDE quel type ils contiennent. C'est très bien car cela n'implique aucune analyse supplémentaire lorsque le code est exécuté - seulement le IDE en est gêné.

/**
 * My container. It contains things. Duh.
 *
 * @property MyService $service
 * @property MyDao $dao
 */
class MyContainer extends Container { }

Pour Pimple et d'autres conteneurs qui agissent comme des tableaux, vous pouvez créer des fonctions d'accesseur pour les objets de niveau supérieur dont vous aurez besoin. Bien que cela signifie plus d'analyse lorsque le conteneur est créé, il doit être effectué une fois et conservé dans APC. De toute façon, je préfère largement une méthode à un accès au tableau car elle place la clé de tableau facile à oublier dans une méthode auto-complétée.

class MyContainer extends Pimple
{
    /**
     * @return MyService
     */
    public function getMyService() {
        return $this['service'];
    }
}

BTW, pour l'indication de type des variables en ligne avec @var dans NetBeans, vous devez utiliser /* avec n astérisque. Ce n'est pas un commentaire de bloc document et ne fonctionne pas avec /** ou //. En outre, le nom précède le type.

public function foo() {
    /* @var $service MyService */
    $service = $container['service'];
    ...
}
44
David Harkness

Comme les IDE n'exécutent pas le code, ils ne savent pas et ont besoin d'aide pour vous. Je sais que cela fonctionne aussi pour Eclipse et d'autres IDE: Indiquez le type de la variable.

Exemple Netbeans/Phpstorm/PDT/ZendStudio

/* @var $mailer MailerInterface */
$mailer = $sc->mailer

Le code terminé recommence à fonctionner sur $mailer.

Pour PDT, il est important que:

  1. Le commentaire commence par un * seulement.
  2. D'abord le nom de la variable, puis l'indice.

Variantes de commentaires alternatives

Comme il a fait l'objet de nombreuses discussions, il peut différer d'un IDE à l'autre. Cependant, la plupart des IDE prennent en charge l'indication de variable pour les variables de code en ligne de la manière ci-dessus. Donc, selon le IDE cela peut être écrit différemment mais similaire, comme ici avec deux astérisques devant:

/** @var $mailer MailerInterface */

Compatibilité PHPDoc

Les analyseurs PHPDoc peuvent avoir un problème si vous imitez la classe var doc-comment pour le code en ligne comme suit:

/** @var MailerInterface $mailer  */

Cette documentation est normalement utilisée pour les variables de classe ( @ var - Documenter le type de données d'une variable de classe ). PHPDoc manque alors la définition de la variable de classe après le commentaire qui implique une charge pour le contrôle qualité.

Cependant, certains IDE offriront également la complétion de code pour les variables simples lorsqu'ils sont écrits dans le style de variable clas PHPDoc. Je ne sais pas si cela a des effets secondaires pour la complétion de code de la classe actuelle, puisqu'un nouveau membre pourrait être introduit qui n'existe pas.

13
hakre

Pour ceux qui sont venus ici de Google.

PHPStorm fournit en fait un moyen de résoudre ce type de problème au lieu d'écrire PHPDocs encore et encore - en créant et en définissant .phpstorm.meta.php fichier en quelque sorte décrit ici gagne des inspections automatiques de saisie semi-automatique et de type.

7
woo

Je sais que la question concerne uniquement le DIC, mais il existe un fournisseur de services Silex Pimple Dumper qui vide le conteneur dans un fichier json. Le même auteur a écrit un plugin pour PHPStorm qui peut lire ce fichier et ouvrir la saisie semi-automatique avec les noms de service et son type (classe, chaîne et etc.). J'utilise ces deux composants et je peux dire que ce sont de bonnes options pour la complétion automatique pour Silex/Pimple.

1
Tales Santos

Pimple vient de présenter le principe du constructeur de conteneurs. Si vous le comprenez, vous n'avez plus besoin de Pimple:


class Container
{
    private $shared = array();

    public function getService() {
        return new Service(
            this->getFirstDependence(),
            this->getSecondDependence()
        );
    }

    protected function getFirstDependence() {
        return new FirstDependence(
            this->getSecondDependence()
        );
    }

    protected function getSecondDependence() {
        return isset($this->shared[__METHOD__]) ? $this->shared[__METHOD__] : $this->shared[__METHOD__] =
        new SecondDependence(
        );
    }
}

De cette façon, Pimple ne cache pas le type d'objet dans $ c ['une clé'] mixte. Vous auriez des suggestions de saisie semi-automatique lors de la modification de votre conteneur. Phpstorm est capable de résoudre automatiquement le type de retour de méthode à partir de votre code. Et vous auriez un récipient clair. Vous pouvez toujours remplacer le conteneur:


class TestContainer extends Container
{
    protected function getFirstDependence() {
        return new FirstDependenceMock(
        );
    }
}

Pour être honnête, un conteneur écrit en langage de programmation n'est pas la bonne solution. La responsabilité du conteneur consiste à apporter un graphique d'objets initialisé à l'appelant. L'accès au "langage de programmation" permet de violer facilement cette responsabilité. Une certaine DSL pour configurer la dépendance est meilleure. De plus, la plupart des informations de dépendance d'origine (types d'arguments des constructeurs) sont simplement ignorées par Pimple et sfDepenencyContainer, ce qui rend votre configuration gonflée et fragile.

0
palex