2017-11-25 2 views
0

私はLaravelには比較的新しいので、私は自分のプロジェクトで 'Ownable' Eloquentオブジェクトを扱うミドルウェアとポリシーを作成しました。基底クラスでのLaravel依存性注入

私はこの特性を利用していた:

class CheckRights 
{ 
    public function __construct(Route $route, Ownable $object) { 
     $this->route = $route; 
     $this->object = $object; 
    } 

    public function handle($request, Closure $next) 
    { 
     // @TODO handle request 
    } 
} 
:私のコントローラで正しいアクションに割り当てられ

class RightPolicy 
{ 
    use HandlesAuthorization; 

    public function update(User $user, Ownable $ownable) 
    { 
     return $ownable->created_by == $user->id; 
    } 
} 

そして、私のミドルウェア、:私は単にこれを行う私のポリシーで

trait Ownable 
{ 

    public function user(){ 
     return $this->belongsTo(User::class, 'created_by'); 
    } 
} 

次に、Ownable特性を使用してクラスを作成しました。

Target [App\Ownable] is not instantiable while building App\Http\Middleware\CheckRights

多分使用して(依存性注入器は、右のクラスをインスタンス化するために知っているようにする方法があります:私はこのような構造を持つプロジェクトを実行しようとすると

class Thread extends Model 
{ 
    use Ownable; 
} 

しかし、Laravelの依存関係のインジェクターは、エラーがtrhowsルートまたは何か他のもの)?

もしそうでなければ、正しいクラスがインスタンス化されていることを確かめるために、依存性インジェクタなしで何か他のことを行う便利な方法はありますか?

+0

特性は定義上インスタンス化できません。私はあなたがここで特徴があるとは思わない、それはクラスと拡張の詳細です –

+0

私はそれを理解しています、私はここで多形性のために形質を使用しています。スレッドはOwnableですが、Commentableですが、ForumRuleはOwnableではありませんが、Commentable(たとえば)です。だから私はこのタイプの構造を選んだのです。 @VincentDecaux – Joas

+0

特性を使用した結果は、常に独自の有効なクラスとして書き出すことができます。 Laravelがその特性で自動解像度を適用すると、動作しないinitを試みます。ですから、あなたが望むポイントに移動する場合は、ここで特性を使用する代わりに、あなたの方法はクラスに切り替えることです。 –

答えて

0

AppServiceProviderでapp :: bindメソッドを使用してこの問題を解決しました。

サービスプロバイダの登録メソッドでは、App \ Ownableインタフェースを、ルータに渡されたすべての注入されたEloquentオブジェクトをループする関数にバインドしました。私は正しいtypehintingためのインタフェースを備えたOwnable形質を組み合わせその後Binding

他のウェブサイト上のフォーラムに提案されているように、::私のミドルウェアに続いて

class Thread extends Model implements \App\Interfaces\Ownable 
{ 
    use Ownable; 
} 

について

namespace App\Providers; 

use App\Ownable; 
use Illuminate\Support\Facades\Route; 
use Illuminate\Support\ServiceProvider; 
use Illuminate\Support\Facades\Schema; 

class AppServiceProvider extends ServiceProvider 
{ 
    public function boot() 
    { 
     Schema::defaultStringLength(191); 
    } 

    public function register() 
    { 
     // Binding ownable trait/interface for correctly handling policy 
     $this->app->bind('App\Ownable', function() { 
      // Get all parameters passed to the current route 
      $array = Route::getCurrentRoute()->parameters; 

      $return = NULL; 
      foreach ($array as $object){ 
       if ($object instanceof Ownable){ 
        // Fetch the last ownable instance found passed to the route 
        $return = $object; 
       } 
      } 

      // return it 
      return $return; 
     }); 
    } 
} 

続きを読みますコンストラクタ私は所有可能なパラメータをオプションにしました(ストアまたは作成アクションが呼び出され、オブジェクトが与えられていない場合)、アクション名に基づいてリクエストを処理しました。オブジェクトが与えられた場合

class CheckRights 
{ 
    public function __construct(Route $route, Ownable $object = null) { 
     $this->route = $route; 
     $this->object = $object; 
    } 

    public function handle($request, Closure $next) 
    { 
     // Get the controller's action name 
     $action = $this->route->getActionName(); 
     $action = substr($action, strpos($action, '@') + 1); 

     // Check if an object is given in the request 
     if ($action != 'store' && $action != 'create' && isset($this->object)){ 
      // Check if gate allows user to update/delete object 
      if ($request->user()->can($action, $this->object)){ 
       return $next($request); 
      } 
     }elseif($action == 'store' || $action == 'create'){ 
      // Check if gate allows user to create object 
      if ($request->user()->can($action, Ownable::class)){ 
       return $next($request); 
      } 
     } 

     return back(); 
    } 
}