2

Laravelは依存性注入を促します。私は自分のプロジェクトにlaravelを使用しているので、私はこのアプローチを試してみることにしました。コンストラクタインジェクションとメソッドインジェクション

私はLaravelのサービスコンテナをtype hinting my dependencies and letting it resolve themで利用しています。私は4つのコントローラを持っています。それらのすべては、GlobalControllerという基本クラスを拡張しています。私には2つのモデルもあります。それらのすべてが、GlobalModelという基本クラスを拡張しています。

私の最初の試みは、メソッド注入を使用して(並べ替え)です。 GlobalControllerは、次のようになります。

namespace App\Http\Controllers; 

use Illuminate\Http\Request;; 
use App\Models\GlobalModel; 

class GlobalController extends Controller 
{ 

    public function __construct() 
    { 
     $this->middleware(['authenticate', 'token']); 
    } 

    // functions that handle normal http requests and ajax requests 

    } 

GlobalControllerから継承するコントローラーの1つをUserControllerと呼びます。その機能のいくつかは、次のとおりです。

  • インデックス - ショーの編集フォーム
  • アップデート - - データベースへの更新

編集や更新に使用route-model-binding

  • 編集のすべてのデータを表示します。

    namespace App\Http\Controllers; 
    
    use Illuminate\Http\Request;; 
    use App\Models\User; 
    
    class UserController extends GlobalController 
    { 
    
        public function index(User $user) 
        { 
         $users = $user->all(); 
         return view('pages/view_users')->with('users', $users); 
        } 
    
        public function edit(User $user) 
        { 
         return view('pages/edit_user')->with('user', $user); 
        } 
    
        public function update(Request $request, User $user) 
        { 
         $data = $request->all(); 
         if ($user->validate($data)) 
         { 
          $user->update($data); 
          return $this->successResponse($request, 'users', 'Successfully edited user'); 
         } 
         return $this->failedResponse($request, $user); 
        } 
    
        // other functions 
    
        } 
    

    これはうまくいきますが、リクエストとユーザーは何回も注入されます。リクエストの実装(例えば)を変更する必要がある場合、その特定のRequestオブジェクトをヒントするために多くの関数を手動で変更する必要があります。まあまあです。通常はほとんどの関数で呼び出されるので、コンストラクタインジェクションを試みました。

    namespace App\Http\Controllers; 
    
    use Illuminate\Http\Request;;; 
    use App\Models\GlobalModel; 
    
    class GlobalController extends Controller 
    { 
        protected $request; 
        protected $model; // use polymorphism 
    
        public function __construct(Request $request, GlobalModel $model) 
        { 
         $this->request = $request; 
         $this->model = $model; 
         $this->middleware(['authenticate', 'token']); 
        } 
    
        // functions that handle normal http requests and ajax requests 
    
    } 
    

    そして、ここではUserControllerでは、同じ機能を含むコンストラクタ・インジェクション使用している:ここで

    はコンストラクタ・インジェクションを使用してGlobalControllerで今

    namespace App\Http\Controllers; 
    
    use Illuminate\Http\Request;; 
    use App\Models\User; 
    
    class UserController extends GlobalController 
    { 
    
        public function __construct(Request $request, User $user) // use polymorphism 
        { 
         parent::__construct($request, $user); 
        } 
    
        public function index() 
        { 
         $users = $this->model->all(); 
         return view('pages/view_users')->with('users', $users); 
        } 
    
        public function edit(int $id) 
        { 
         $this->model = $this->model->find($id); 
         return view('pages/edit_user')->with('user', $this->model); 
        } 
    
        public function update(int $id) 
        { 
         $this->model = $this->model->find($id); 
         $data = $this->request->all(); 
         if ($this->model->validate($data)) 
         { 
          $this->model->update($data); 
          return $this->successResponse('users', 'Successfully edited user'); 
         } 
         return $this->failedResponse(); 
        } 
    
        // other functions 
    
    } 
    

    を、私はそれに私の指を置くことはできませんが、私はこの実装が正しくないと思う。それは読みにくくなった。 $ modelと$ thisの使い方はコードをより嫌にしています。

    私はとても混乱しています。私は依存性注入から得られる利点を理解していますが、私はメソッド注入とコンストラクタ注入の実装が非常に間違っていると確信しています。どのような実装を選択する必要がありますか?あるいは、私はこれらの2つの中からいずれかを選ぶべきですか?

  • 答えて

    1

    私はLaravel Controllersの最初の方法を間違いなく推奨します。最初は、すべてのメソッドで注入モデルは必要ありません。 (なぜ、あなたはインデックス関数にユーザーモデルを挿入しますか?)

    第2に、RouteModelBindingの利点をもう使用できず、指定された$ idを持つモデルが実際に存在するかどうかを手動でチェックし、それに応じてアクションを実行する必要があります。また、検証と承認を処理できるCreateUserRequestのような特定のFormRequestを使用することはできません。(これはオプションですが)

    また、コンストラクタに挿入されたモデルは決してユーザーデータを持つ「本当の」モデルではありません。だから、これはあなたに象徴的な機能へのアクセスを与えるだけです。だから、あなたのコードでもUser :: find($ id)を使うことができます。これは常にあなたに虚偽を与えるでしょう。

    public function __construct(User $user) 
    { 
        dd($user->exists); 
    } 
    

    オブジェクトを抽象化したい場合は、コンポジターにリポジトリを挿入できます。

    public function __construct(UserRepository $userRepository) 
    { 
        $this->userRepository = $userRepository; 
        // then the Repository is responsible for retrieving users 
        // and you are not coupled to Eloquent. If you later want, you can Read 
        // users from an XML File if you need 
    } 
    

    追加情報(ビットofftopic):それは非常にまれであると私はあなたがこのようにカスタムリクエストクラスを作成することによってこれを行うことができ、要求クラスを変更するために必要なことはありませんが:

    namespace App; 
    
    
    use Illuminate\Http\Request; 
    
    class MyRequest extends Request 
    { 
        // override request methods or add your new own methods 
    } 
    

    そして、グローバルindex.php:

    $response = $kernel->handle(
        // instead of Illuminate\Http\Request::capture() 
        $request = \App\MyRequest::capture() 
    ); 
    
    +0

    "なぜあなたはインデックス関数にユーザーモデルを挿入しますか?" - インデックス関数はすべてのデータをビューに渡します。 $ user-> all()を実行するには$ userが必要です。これは悪いですか? – morbidCode

    +0

    か、単にUser :: all()を呼び出してください。すべてのユーザーを取得する場合は、特定のユーザーインスタンスは必要ありません。これがあなたにとってより良いと思えば、UserRepositoryを使用してください。 –

    +0

    ああ、そうです。私はファサードを使うことができます!しかしファサードは同じことをしないのですか?ファサードがallを呼び出すときに新しいUserインスタンスを作成しないと言っていますか?私はファサードを可能な限り避けたいと思う。 – morbidCode

    1

    モデルがほとんどのメソッドで使用されている場合は、コンストラクタインジェクションを使用します。 $ modelと$ thisの使用には何も問題ありません。しかし、まだコードを消去したい場合は、リポジトリパターン(SRP)を検討してください。コードの長い行を管理することができます。 これを見るstackoverflow answer - How can I organise classes in a Laravel 5 Project?私はこれがあなたの混乱を助けることを願っています。

    関連する問題