Laravel 4 - 使用依赖注入的子构造函数调用父构造函数 [英] Laravel 4 - Child constructor call parent constructor with dependency injection

查看:2820
本文介绍了Laravel 4 - 使用依赖注入的子构造函数调用父构造函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用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扩展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扩展AdminController {

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

//与之前相同
}

现在这在工作正常的功能;但是对我来说,将父类的依赖包括在每个具有构造函数的子类中看起来并不是非常有效。它也看起来很凌乱。 Laravel提供了一个方法,或者PHP支持一种调用父和子构造函数的方法,而不必从子进程调用 parent :: __ construct() / p>

我知道这是一个长期的问题,什么是有效地不是一个问题,但更多的我只是关于效率,但我喜欢任何想法和/或解决方案。 >

提前感谢!

解决方案


当BaseController自动解决它的依赖关系。

 使用Illuminate\Routing\Controller; 
使用Illuminate \Foundation\Application;

//依赖关系
使用Illuminate \Auth\AuthManager;
use Prologue\Alerts\AlertsMessageBag;

class BaseController extends Controller {

protected $ authManager;
protected $ alerts;

public function __construct(
//解析
所需的应用程序$ app,

//依赖关系
AuthManager $ authManager = null,
AlertsMessageBag $ alerts = null

{
static $ dependencies;

//获取参数
if($ dependencies === null)
{
$ reflector = new \ReflectionClass(__ CLASS__);
$ constructor = $ reflector-> getConstructor()
$ dependencies = $ constructor-> getParameters();
}

foreach($ dependencies as $ dependency)
{
//进程只忽略可选参数
if($ {$ dependency-> name} === null)
{
//分配变量
$ {$ dependency-> name} = $ app-> make($ dependency-> getClass > name);
}
}


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

//测试它
dd($ authManager);
}
}

所以在子控制器中你只传递Application instance: / p>

  class MyController extends BaseController {

public function __construct(
// BaseController
// ..

//应用程序
应用程序$ app

{
//逻辑在这里
/ / ..


//调用父级
parent :: __ construct($ app);
}
}

当然, p>

I'm building a CMS using Laravel 4 and I have a base admin controller for the admin pages that looks something like this:

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

Im using Laravel's IOC container to inject the class dependencies into the constructor. I then have various controller classes that control the different modules that make up the CMS and each class extends the admin class. For example:

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

Now this works perfectly however my problem, which is less of a problem and more of a efficiency issue, occurs when I add a constructor to the UsersController class. For example:

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

Since the child class now has a constructor it means the parent's constructor isn't getting called and thus things the child class is dependant on, such as this->user are no longer valid, causing errors. I can call the admin controller's construct function via parent::__construct() however since I need to pass it the class dependencies I need to set these dependencies in the child constructor resulting in something that looks like this:

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
}

Now this works fine in terms of its functionality; however it doesn't seem very efficient to me to have to include the parent's dependencies in every child class that has a constructor. It also looks quite messy. Does Laravel provide a way around this, or does PHP support a way of calling both the parent and child constructor without having to call parent::__construct() from the child?

I know this is a long question for what is effectively not a problem but more me just be ocd about efficiency, but I appreciate any ideas and/or solutions.

Thanks in advance!

解决方案

There's a way. When BaseController autoresolves it's dependecies.

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

So in child controller you pass only Application instance:

class MyController extends BaseController {

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

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


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

Of course, we could use Facade for application

这篇关于Laravel 4 - 使用依赖注入的子构造函数调用父构造函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆