Laravel: injection de dépendance vs façades?

ce que j'avais fait auparavant était de injecter seulement mes modèles en utilisant le constructeur et utiliser façades pour les Laravel fournis classes c.-à-d. Session , Auth , Validator etc, par exemple. Est - ce que ce sera une bonne idée si j'injecte chaque classe (soit la mienne ou celle de Laravel) par la construction et l'utiliser par la syntaxe $this->.. ou si j'injecte mes propres classes en utilisant le constructeur et utiliser des façades pour quoi que ce soit fourni par Laravel?

pour être plus précis, voici à quoi ressemblent habituellement mes contrôleurs:

class MyController extends BaseController 
{
    public function __construct( User $user, Bookmark $bookmark ) {
        $this->user = $user;
        $this->bookmark = $bookmark
    }

    public function foobar ( ) {
        $user_id = Input::get('bar');
        ...
        Session::get('someInfo');
        ...
        return Redirect::to('/');
    }
    ...
}

est-ce que je devrais structurer mes méthodes comme controller comme suit, à la place?

class MyController extends BaseController 
{
    public function __construct( User $user, Bookmark $bookmark, Input $input, Session $session, Redirect $redirect ) {
        $this->user = $user;
        $this->bookmark = $bookmark
        $this->input = $input;
        $this->session = $session;
        $this->redirect = $redirect;
    }

    public function foobar ( ) {
        $user_id = $this->input->get('bar');
        ...
        $this->session->get('someInfo');
        ...
        return $this->redirect->to('/');
    }
    ...
}
7
demandé sur Kamran Ahmed 2014-11-22 21:10:19

4 réponses

Laravel supporte maintenant la même fonctionnalité d'injection pour les méthodes de classes (pas seulement les constructeurs) qui sont liées à la route, comme les contrôleurs et les middlewares.

vous pourriez prévenir les injections inutiles en n'injectant que des méthodes où la dépendance est unique, laissant peut-être des dépendances plus communes dans le constructeur:

class MyController extends BaseController 
{
    public function __construct( Input $input, Session $session, Redirect $redirect ) {
        $this->input = $input;
        $this->session = $session;
        $this->redirect = $redirect;
    }

    public function foobar ( User $user, Bookmark $bookmark ) {
        $user_id = $this->input->get('bar');
        ...
        $this->session->get('someInfo');
        ...
        return $this->redirect->to('/');
    }
    ...
}

quant à savoir si vous devez le faire de cette façon, c'est à vous de forçage toutes les dépendances à apparaissent dans les définitions de méthode semble plus propre à moi, et plus facile à tester à l'unité.

1
répondu tjbp 2016-01-27 01:44:43

il est élégant et utile d'injecter certaines classes, comme Request. À mon avis, ils devraient être spécifiés dans les méthodes de contrôle où ils sont nécessaires, car ils sont ensuite logiquement liés à la mise en œuvre de la méthode. Impressionnant jusqu'à présent.

je trouve que deux façades sont problématiques - App et Log. Ni sont logiquement connectés à un contrôleur ou de ses actions. App et Log ne sont pas des entrées dans n'importe quel contexte. Comme App et Log sont des classes d'utilité, elles sont pertinentes pour les services et les dépôts ainsi, et il devient carrément désagréable si vous tapez des indices dans les controllers et puis les passer sur comme constructeur ou paramètres de méthode à vos classes de soutien.

un autre problème est que App facade n'implémente pas L'interface Illuminate\Contracts\Auth\Guard qu'elle mandate, de sorte que mon IDE s'allume avec des avertissements car l'analyse statique n'est pas possible.

par souci de cohérence et de séparation globale des préoccupations, je par conséquent instanciate App et Log à l'intérieur d'un constructeur ou d'une méthode, en fonction de l'étendue de leur utilisation dans une classe. Pour rendre mon IDE heureux j'ai créé la classe ci-dessous pour me donner une instance correctement tapée où que j'en ai besoin:

<?php namespace App\Components;

use Illuminate\Contracts\Auth\Guard;
use Psr\Log\LoggerInterface;

/**
 * Get the underlying object instances of facades from the container.
 */
class AppGlobal
{
    /**
     * Returns the global logger instance.
     *
     * @return LoggerInterface
     */
    public static function log()
    {
        return app('log');
    }

    /**
     * Returns the global auth instance, which internally proxies a guard.
     *
     * @return Guard
     */
    public static function auth()
    {
        return app('auth');
    }

}
0
répondu Dion Truter 2017-02-04 10:34:06

si vous avez besoin d'un objet avec des propriétés - mettez-le comme une injection (E. G entrée, Session...), sinon, si vous ne stockez pas de données dans l'objet et assez heureux en utilisant la classe, que d'aller avec les façades (E. G Log::..., Rediriger.::..).

0
répondu Yevgeniy Afanasyev 2017-02-27 00:10:21

Laravel a remplacé beaucoup de sa façade avec des aides par exemple

use Auth;

et

Auth::user()

est maintenant juste

auth()->user()

cela rend la chose plus simple et plus propre (empêche également de faire des erreurs)

je suggérerais d'utiliser les helpers lorsque c'est possible et si aucun helper n'existe, d'utiliser la façade parce qu'il est plus facile de se moquer qu'une instance injectée.

0
répondu lucidlogic 2017-11-13 19:56:14