2

Laravel은 의존성 주입을 권장합니다. 내 프로젝트에 laravel을 사용하고 있기 때문에이 방법을 사용해 보겠다 고 생각했습니다.생성자 주입 대 메소드 주입

저는 Laravel의 서비스 컨테이너를 type hinting my dependencies and letting it resolve them으로 이용하고 있습니다. 4 개의 컨트롤러가 있습니다. 모두 GlobalController라는 기본 클래스를 확장합니다. 나는 또한 두 가지 모델을 가지고있다. 이들 모두는 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에서 확장되는 컨트롤러 중 하나는 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 

    } 

이 작업은 정상적으로 작동하지만 요청 및 사용자는 여러 번 주입됩니다. 요청 구현 (예를 들어)을 변경해야한다면, 특정 요청 객체에 대한 힌트를 입력하기 위해 많은 함수를 수동으로 변경해야 할 것입니다. 별로 좋지 않다. 일반적으로 대부분의 함수에서 호출되므로 생성자 주입을 시도했습니다. 여기

는 GlobalController은 생성자 주입 사용 :

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이 같은 기능을 포함하는 생성자 주입을 사용하고 있습니다 : 이제

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를 사용하면 코드가 더 진절머리 나게됩니다.

너무 혼란 스럽습니다. 의존성 주입을 통해 얻을 수있는 이점을 이해하지만 메소드 주입과 생성자 주입에 대한 구현이 매우 잘못되었다고 확신합니다. 어떤 구현을 선택해야합니까? 아니면이 두 가지 중에서 하나를 선택해야합니까?

답변

1

저는 Laravel 컨트롤러의 첫 번째 방법을 선호합니다. 처음에는 모든 방법에 주입 된 모델이 필요하지 않습니다. (왜 당신은 인덱스 함수에 사용자 모델을 주입하겠습니까?).

두 번째로 RouteModelBinding의 이점을 더 이상 사용할 수 없으며 주어진 $ id가있는 모델이 실제로 있는지 여부를 수동으로 확인하고 그에 따라 조치를 취해야합니다. 또한 유효성 검사 및 권한 부여를 처리 할 수있는 CreateUserRequest와 같은 특정 FormRequest를 사용할 수 없습니다.(이것은 선택적인 기능 임)

또한 생성자에 삽입 된 모델은 절대로 사용자 데이터가있는 '실제'모델이 아닙니다. 따라서 이것은 단지 당신에게 엘레 오보 (eleoquent) 기능에 대한 액세스를 제공 할 것입니다. 따라서 코드에서 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 
} 

추가 정보 (조금 논외) : 그것은 매우 드문 일이며,이 같은 사용자 지정 요청 클래스를 생성하여이 작업을 수행 할 수있는 요청 클래스를 변경하는 데 필요한 적이 있지만 :

namespace App; 


use Illuminate\Http\Request; 

class MyRequest extends Request 
{ 
    // override request methods or add your new own methods 
} 

을 그리고 나서 글로벌 index.php :

+0

"왜 인덱스 기능에 사용자 모델을 주입하겠습니까?" - 인덱스 함수는 모든 데이터를 뷰로 가져옵니다. $ user-> all()을 수행하려면 $ 사용자가 필요합니다. 이거 나쁜거야? – morbidCode

+0

또는 User :: all()을 호출하면됩니다. 모든 사용자를 얻으려면 특정 사용자 인스턴스가 필요하지 않습니다. 또는 UserRepository를 사용하는 것이 좋습니다. –

+0

아, 네 말이 맞아. 나는 정면을 사용할 수있다! 하지만 외장재는 같은 것을하지 않습니까? 모든 사람에게 전화를 걸 때 Facade가 새로운 User 인스턴스를 생성하지 않는다는 것을 의미합니까? 나는 가능한 한 정면을 피하고 싶다. – morbidCode

1

대부분의 방법에서 모델을 사용하는 경우 생성자 삽입을 사용하십시오. 그리고 $ model과 $ this의 사용에는 아무런 문제가 없습니다. 하지만 여전히 코드를 정리하려면 저장소 패턴 (SRP)을 고려하십시오. 코드의 긴 행을 관리 할 수 ​​있습니다. 보기 stackoverflow answer - How can I organise classes in a Laravel 5 Project? 나는 이것이 당신의 혼란에 도움이되기를 바랍니다.