【问题标题】:Laravel 4 - Use a controller action in other controllers?Laravel 4 - 在其他控制器中使用控制器动作?
【发布时间】:2013-10-29 23:30:48
【问题描述】:

好吧,我有几个控制器在做我的工作,现在我创建了更多控制器;在新控制器中的某个操作中间,我只记得我已经在旧控制器中编写了正确的代码。

所以例如在 oldController@handyAction

some_good_codez();

在 newController@newAction 中

$myOldController = Load::controller('oldController'); // I wish Laravel had this?
$myOldController->handyAction();

【问题讨论】:

  • 我不明白在另一个中使用控制器的操作。如果许多控制器使用相同的方法,请将其包含在基本控制器中或为其创建一个类然后调用它。
  • @itachi 没有很多控制器,例如 2 个控制器想要使用完整的非静态类。

标签: php oop laravel laravel-4


【解决方案1】:

这是错误的。控制器必须只负责一项职责:接收 http 请求,从模型中获取一些数据并将其传递给视图。如果您的控制器必须与另一个控制器“对话”,这可能是因为您正在处理它们上的数据,或者通过它们读取数据,而您不应该这样做,因为处理数据是模型而不是控制器的责任。

首先,看看SOLIDSingle responsibility principle。如果你能买到Taylor Otwell's book: Laravel: From Apprentice To Artisan,就去做吧,它会让你很好地了解如何在 Laravel 中实现 SOLID 原理。

然后,如果您真的需要在两个不同的控制器上使用一个方法,请创建一个新类并在两个控制器上使用这个类。只需重构您的代码以执行以下操作:

class MyController1 extends Controller {

    public function __construct(MyClass $class)   
    {
        $this->myClass = $class;
    }

    public function store()
    {
        $this->myClass->doWhatever();
    }

}

class MyController2 extends Controller {

    public function __construct(MyClass $class)   
    {
        $this->myClass = $class;
    }

    public function update()
    {
        $this->myClass->doWhatever();
    }

}

class MyClass {

    public function doWhatever()
    {
        return 'done';
    }

}

这仍然是错误的,但要好一些。

更好的是在数据存储库中处理您的数据,因此请查看存储库模式,this Taylor's video 会让您对如何操作有一个很好的了解。它谈论可测试性,但不仅如此,您可以创建域存储库并在其中混合两个或多个模型,并在一个类中处理来自这些模型的数据。使用 Repository 模式的代码看起来更像:

创建接口(合约):

interface MyDataRepository {

    public function getInfoA();
    public function getInfoB($dataA);

}

创建一个实现该接口的类

class MyData implements MyDataRepository {

    public function __construct(MyModelA $dataA, MyModelB $dataB)   
    {
        $this->dataA = $dataA;
        $this->dataB = $dataB;
    }

    public function getInfoA()
    {
        return $this->dataA->processData();
    }

    public function getInfoB($dataA)
    {
        return $this->dataB->processData( $this->getInfoA() );
    }

}

[编辑]

将存储库想象成一个袋子,您可以在其中放置所需的所有内容并从中提取所需的内容。

在这个存储库中,我们使用了 2 个模型(MyModelA 和 MyModelB),由 Laravel 的 IoC 容器实例化,在方法 getInfoB 中,存储库使用这两个模型来生成数据并将其传递回控制器。

这一切都来自领域驱动开发。域是一个复杂的模型,例如订单,它是使用来自订单、用户、商品、运输和付款表的数据构建的。如果没有所有这些信息,您的付款页面上就不会真正显示订单,因此您创建了一个订单存储库并将所有 ORM 混合在一个类中,它具有从这些表中获取数据并将其发送回的单一责任你的控制器。

[/edit]

当它需要你的接口实例时,你必须告诉 Laravel 实例化该类:

App::bind('MyDataRepository', 'MyData ');

只有在你使用接口的时候才会这样做,这里我们使用一个具体的类来做同样的事情,我们不需要通知任何东西,Laravel 知道该怎么做:

public function __construct(MyClass $class)   
{
    $this->myClass = $class;
}

并使用存储库创建您的控制器:

    class MyController1 extends Controller {

    public function __construct(MyDataRepository $data)   
    {
        $this->data = $data;
    }

    public function store()
    {
        $this->data->getInfoA();
    }

}

class MyController2 extends Controller {

    public function __construct(MyDataRepository $class)   
    {
        $this->data = $data;
    }

    public function update()
    {
        $this->myClass->getInfoB();
    }

}

Laravel 会自动实例化你的类的一个实例,你不需要做任何其他事情来让它工作。

【讨论】:

  • 所以我应该在模型中编写数据处理器?在 codeigniter 中,我可以编写任何类型的数据处理,然后将其传递给控制器​​,但在 laravel 中,我觉得我仅限于 ORM 及其默认操作,它有一个 app/model 目录,但模型扩展 Eloquent 不是例如基本模型。所以在这里我可以对数据库进行 CRUD,而不是在将数据传递给控制器​​之前对其进行处理。再次在 CI 中,有一个 $this->load('modelName') 方法将模型类加载到控制器中。我认为这些差异让我提出了如此异常的问题。
  • 你可以(几乎)在 Laravel 中做任何你需要的事情,但是你可以区分 what you can dowhat you should do。而且你不需要“加载”任何东西,作曲家自动加载系统会为你处理一切,你只需使用它们,它们就会自动加载。
  • 是的,所以should I 在 app/models 中创建一个文件并扩展 Eloquent 并向该类添加我需要的操作?不应该将任何模型链接到一张表吗?如果我在该模型中需要几个数据库表怎么办?我可以(我应该!)在另一个模型中使用模型的动作吗?!!
  • 这就是仓库进入的地方,把仓库想象成一个袋子,你可以把你需要的东西放在那里,然后从中提取你需要的东西。在我编写的那个存储库中,我们有 2 个模型(MyModelA 和 MyModelB),在方法(getInfoB)中,存储库使用两者来生成数据并将其传递回控制器。这来自领域驱动开发。域是一个复杂的模型,例如订单,当您需要来自订单、用户、商品、付款等所有内容的数据以显示在您的付款页面上时,您只需创建一个订单存储库并将它们全部混合在一个类中。
  • 写得很好,但我相信你会想implements MyDataRepository 而不是extends
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-04-09
  • 1970-01-01
  • 2016-06-25
  • 2014-03-08
  • 2013-05-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多