这是不对的。控制器必须承担一项责任:接收http请求,从模型中获取一些数据并将其传递给视图。如果您的控制器必须与另一个控制器“交谈”,可能是因为您正在处理数据或通过它们读取数据,而您不应该因为处理数据而是模型而不是控制器的责任。
首先,看看SOLID和Single 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会给你一个很好的想法。它讨论可测试性,但不仅如此,您可以创建域存储库并在其中混合两个或更多模型,并在一个类中处理来自这些模型的数据。使用资源库模式A的代码将looke更像:
创建接口(合同):
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容器实例化,在方法中,存储库正在使用这两个模型生成数据并将其传递回控制器。
这一切都来自域驱动开发。域是一个复杂的模型,如Order,它是使用来自订单,用户,项目,出货和付款表的数据构建的。如果没有所有这些信息,您就没有订单显示在您的付款页面上,因此您创建了一个订单仓库,并将您的所有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会自动实例化类的实例,你不需要做别的事,使其工作。
我不明白在另一个使用控制器的行为。如果许多控制器使用相同的方法,请将其包含在基本控制器中或为其创建一个类,然后调用它。 – itachi
@itachi没有太多的控制器,例如2个控制器想要使用完整的非静态类。 – Webinan