2017-11-25 348 views
0

我對Laravel比較新,我創建了一箇中間件和策略來處理我的項目中的'Ownable'雄辯對象。Laravel依賴注入基類

我該使用特點做:

trait Ownable 
{ 

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

在我的政策,我只是這樣做:

class RightPolicy 
{ 
    use HandlesAuthorization; 

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

而我的中間件,在我的控制器分配到正確的動作:

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

    public function handle($request, Closure $next) 
    { 
     // @TODO handle request 
    } 
} 

然後我創建了一個使用Ownable特徵的類:

class Thread extends Model 
{ 
    use Ownable; 
} 

然而,當我嘗試運行具有這種結構的項目,Laravel的依賴注入trhows錯誤:

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

有沒有辦法讓依賴注入知道實例權類(可能使用路線或別的東西)?

如果沒有,是否有一個方便的方式來做別的事情,而不依賴注入器來確保正確的類被實例化?

+0

根據定義,特徵不是可實例化的。我不認爲你需要特質在這裏,它更多關於類和擴展 –

+0

我明白,我在這裏使用特徵爲多態性原因。一個線程是可持有的,但也是可以評論的,但是,一個ForumRule不是可持有的,但是可以評論(例如)。這就是我選擇這種結構的原因。 @VincentDecaux – Joas

+0

使用Trait的結果總是可以作爲有效的類自行編寫出來。當Laravel在該特性中應用自動解析時,它會嘗試初始化哪個不起作用。因此,如果你想要達到你想要的水平,你的方法是轉換到一個班級,而不是在這裏使用特質。 –

回答

0

我使用AppServiceProvider中的app :: bind方法解決了這個問題。

在服務提供者的註冊方法中,我將App \ Ownable接口綁定到一個函數,該函數將所有注入的Eloquent對象傳遞給路由器。

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; 
     }); 
    } 
} 

瞭解更多關於:Binding

然後我再加上正確typehinting的接口可擁有特質,作爲一個論壇上提出的其他網站上:在我的中間件

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

然後構造函數我使可選參數成爲可選參數(用於在調用存儲或創建動作時未給出對象)並基於動作名稱處理我的請求並且如果給定對象

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(); 
    } 
}