2017-12-19 22 views
2

私はUserモデルで使用されているTimezoneTraitを持っています。私はまた、サービスプロバイダを介してロードされ、バインディングは問題ないはずですので、すべてのクラス間の良好な動作しますUserRepositoryInterfaceを持っている:特性コンストラクタのLaravel渡し引数

public function register() 
{ 
    $this->app->bind(UserRepositoryInterface::class, UserRepository::class); 
} 

public function provides() 
{ 
    return [ 
     UserRepositoryInterface::class, 
    ]; 
} 

今私が持っている問題は、私はそう、私の特性にそのリポジトリを使用しなければならないことです私は自然にこのでした:

private $userRepository; 

public function __construct(UserRepository $userRepository) 
{ 
    $this->userRepository = $userRepository; 
} 

をしかし、ダンプは、リポジトリがnullであることを示しています。形質に依存性を注入できないのですか?

+0

宣言 ';'それは私の知る限り、彼らは 'でuse'edしているクラスと一緒に注入することができない何も –

+0

ハズレを、働くことが、何もありません。あなたが他のクラスを注入しているどのクラスでも、あなたがその形質を使用するのを止めています。 – Norgul

+0

済みの特徴を、ない – Andrew

答えて

2

形質内に__constructorを定義するのは実際には間違っています。または単に悪いデザイン。 Constructors should be specific to a class to which they belong、形質ではありません。もう1つの問題は、Modelクラスで特性をインポートすることです。つまり、具体的にはどのようにしてa trait in a model is loadedのルールに従わなければならないかということです。

モデルの段階では、インポートされた特性をクラス内で再帰的に検索し、自動的にboot{TraitNameHere}命名規則を使用しているメソッドを静的に呼び出します。これは、モデルの形質がラーベルスの依存性注入サイクルに関与していないことを証明します。

Laravelグローバルヘルパーを使用して、ファサードApp::make(DefinedKeyHere)のように、コンテナ内に格納されたインスタンスをロードできます。割り当てられたインスタンスをの静的プロパティに保存して、実行時が終了するまで、およびリコールメソッドがstaticになるまで保持します。

trait TimezoneTrait 
{ 
    protected static $userRepository; 

    protected static function bootTimezoneTrait() 
    { 
     static::$userRepository = \App::make(UserRepositoryInterface::class); 
    } 
} 

現在、グローバルヘルパーの使用を避けようとしている場合は、モデル起動イベントをリッスンすることも役に立ちます。 EventServiceProvider、

Event::listen('eloquent.booting:*', function (Model $model) { 
    $model->setUserRepository($this->app[UserRepositoryInterface::class]); 
}); 

内側例次に特色は、私は、静的setUserRepositoryを定義していますが、あまりにも、それは非静的作ることができます注意してください、

trait TimezoneTrait 
{ 
    protected static $userRepository; 

    public function static setUserRepository(UserRepositoryInterface $userRepository) 
    { 
     static::$userRepository = $userRepository; 
    } 
} 

だろう。

モデルイベントについて少し詳しく説明すると、モデルには関連アクションが実行されるたびに起動するイベントがいくつかあります。 Laravel 5.5、

public function getObservableEvents() 
{ 
    return array_merge(
     [ 
      'creating', 'created', 'updating', 'updated', 
      'deleting', 'deleted', 'saving', 'saved', 
      'restoring', 'restored', 
     ], 
     $this->observables 
    ); 
} 

そしてbootingbootedあるそのインスタンス化時に起動され、他の2つのデフォルトのイベント(またシリアライズ)から

例イベント。そして、イベントを起動するために使用するメソッドは、イベント名を確認します。 $ userRepositoryを保護

protected function fireModelEvent($event, $halt = true) 
{ 
    // ... 

    return ! empty($result) ? $result : static::$dispatcher->{$method}(
     "eloquent.{$event}: ".static::class, $this 
    ); 
} 
+0

ブートと構築の違いは何ですか?コンストラクタは、クラスがインスタンス化されたときにのみ呼び出されますが、すべてのサービスプロバイダが登録された後は、最初にbootが呼び出されます。これは、クラスがインスタンス化されているかどうかに関係なく、ブートが独立して呼び出されることを意味しますか? – Norgul

+0

これは 'boot'とは異なりますが、あなたが参照しているのはアプリケーション' boot'strappingですが、これは単にモデル上で起こっている 'boot'なものです。モデルがインスタンス化されると、この 'boot'は上で述べたように、すべての特性を再帰的に呼び出すこと、静的なイベントを適用すること、およびその他のことを適用します。 'booted'を実行すると、' boot'ing stageがすでに完了したことを示す保持された値が保存されます。ですから、 'new Model'、' Model :: create'などのように、再度インスタンス化すると、そのハード・メモリ・ステージが回避されます。 – Chay22

関連する問題