32

Laravel 4 を使用して CMS を構築しています。次のような管理ページ用のベース管理コントローラーがあります。

class AdminController extends BaseController {

    public function __construct(UserAuthInterface $auth, MessagesInterface $message, ModuleManagerInterface $module)
    {
        $this->auth = $auth;
        $this->user = $this->auth->adminLoggedIn();
        $this->message = $message;
        $this->module = $module;
    }
}

Laravel の IOC コンテナーを使用して、クラスの依存関係をコンストラクターに注入します。次に、CMS を構成するさまざまなモジュールを制御するさまざまなコントローラー クラスを用意し、各クラスは管理クラスを拡張します。例えば:

class UsersController extends AdminController {

    public function home()
    {
        if (!$this->user)
        {
            return Redirect::route('admin.login');
        }
        $messages = $this->message->getMessages();
        return View::make('users::home', compact('messages'));
    }
}

UsersControllerこれは完全に機能しますが、クラスにコンストラクターを追加すると、問題が少なく効率の問題が多くなる私の問題が発生します。例えば:

class UsersController extends AdminController {

    public function __construct(UsersManager $user)
    {
        $this->users = $users;
    }

    public function home()
    {
        if (!$this->user)
        {
        return Redirect::route('admin.login');
        }
        $messages = $this->message->getMessages();
        return View::make('users::home', compact('messages'));
    }
}

子クラスにはコンストラクターがあるため、親のコンストラクターが呼び出されないため、子クラスが依存してthis->userいるものが無効になり、エラーが発生します。ただし、管理コントローラーのコンストラクト関数を呼び出すことができますがparent::__construct()、クラスの依存関係を渡す必要があるため、子コンストラクターでこれらの依存関係を設定する必要があるため、次のようになります。

class UsersController extends AdminController {

    public function __construct(UsersManager $user, UserAuthInterface $auth, MessagesInterface $message, ModuleManagerInterface $module)
    {
        parent::__construct($auth, $messages, $module);
        $this->users = $users;
    }

    // Same as before
}

これで機能的には問題なく動作します。ただし、コンストラクターを持つすべての子クラスに親の依存関係を含める必要があるのは、あまり効率的ではないようです。見た目もかなり雑です。Laravel はこれを回避する方法を提供していますか、それとも PHP はparent::__construct()、子から呼び出さなくても親と子の両方のコンストラクターを呼び出す方法をサポートしていますか?

私はこれが事実上問題ではないことについての長い質問であることを知っていますが、私は単に効率についてはうんざりしていますが、アイデアや解決策に感謝します。

前もって感謝します!

4

6 に答える 6

3

方法があります。BaseController が自動解決するとき、それは依存関係です。

use Illuminate\Routing\Controller;
use Illuminate\Foundation\Application;

// Dependencies
use Illuminate\Auth\AuthManager;
use Prologue\Alerts\AlertsMessageBag;

class BaseController extends Controller {

    protected $authManager;
    protected $alerts;

    public function __construct(
        // Required for resolving
        Application $app,

        // Dependencies
        AuthManager $authManager = null,
        AlertsMessageBag $alerts = null
    )
    {
        static $dependencies;

        // Get parameters
        if ($dependencies === null)
        {
            $reflector = new \ReflectionClass(__CLASS__);
            $constructor = $reflector->getConstructor()
            $dependencies = $constructor->getParameters();
        }

        foreach ($dependencies as $dependency)
        {
            // Process only omitted optional parameters
            if (${$dependency->name} === null)
            {
                // Assign variable
                ${$dependency->name} = $app->make($dependency->getClass()->name);
            }
        }


        $this->authManager = $authManager;
        $this->alerts = $alerts;

        // Test it
        dd($authManager);
    }
}

したがって、子コントローラーでは Application インスタンスのみを渡します。

class MyController extends BaseController {

    public function __construct(
        // Class dependencies resolved in BaseController
        //..

        // Application
        Application $app
    )
    {
        // Logic here
        //..


        // Invoke parent
        parent::__construct($app);
    }
}

もちろん、Facade をアプリケーションに使用することもできます

于 2014-06-28T13:08:13.747 に答える
0

私もこの問題に遭遇し、子クラスでコンストラクターを呼び出さず、関数パラメーター内で必要な追加の依存関係を使用しないことで、この混乱を解消しました。

これらの関数を手動で呼び出す必要がなく、そこにすべてを注入できるため、コントローラーで動作します。そのため、一般的な依存関係は親に行き、メソッド自体には必要のないものが追加されます。

于 2020-10-13T20:27:57.920 に答える