Laravel 4 - 在其他控制器中使用控制器操作


Laravel 4 - Use a controller action in other controllers?

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

所以例如在oldController@handyAction

some_good_codez();

并在newController@newAction

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

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

首先,看看坚实和单一责任原则。如果你能买到Taylor Otwell的书: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';
    }
}

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

更好的是在数据存储库中处理数据,所以看看存储库模式,这个 Taylor 的视频会让你很好地了解你是如何做到的。它谈到了可测试性,但不仅如此,您还可以创建域存储库并在其中混合两个或多个模型,并在一个类中处理来自这些模型的数据。使用存储库模式的代码看起来更像:

创建接口(合约):

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 e MyModelB),由 Laravel 的 IoC 容器实例化,并且在getInfoB存储库使用这两种模型来生成数据并将其传递回控制器的方法中。

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

[/编辑]

你必须告诉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将自动实例化您的类的实例,您无需执行任何其他操作即可使其工作。