2013-10-21 306 views
1

好吧,我有几个控制器在做我的工作,现在我创建了几个控制器;在新控制器中的一些动作中,我只记得我已经在旧控制器中编写了正确的代码。Laravel 4 - 在其他控制器中使用控制器操作?

因此对于例如在oldController @ handyAction

some_good_codez(); 

和newController @ newAction

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

我不明白在另一个使用控制器的行为。如果许多控制器使用相同的方法,请将其包含在基本控制器中或为其创建一个类,然后调用它。 – itachi

+0

@itachi没有太多的控制器,例如2个控制器想要使用完整的非静态类。 – Webinan

回答

8

这是不对的。控制器必须承担一项责任:接收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会给你一个很好的想法。它讨论可测试性,但不仅如此,您可以创建域存储库并在其中混合两个或更多模型,并在一个类中处理来自这些模型的数据。使用资源库模式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会自动实例化类的实例,你不需要做别的事,使其工作。

+0

所以我应该在模型中写入数据处理器?在codeigniter中,我可以在数据上编写任何类型的流程,然后将其传递给控制器​​,但是在laravel中,我觉得我仅限于ORM及其默认操作,它具有应用程序/模型目录,但模型扩展了Eloquent而不是例如baseModel。所以在这里我可以对数据库执行CRUD,而不是在将数据传递给控制器​​之前处理数据。再次在CI中有一个$ this-> load('modelName')方法,它在控制器中加载模型类。我认为这些差异让我问这样的异常问题。 – Webinan

+0

你可以(非常)在Laravel中做你需要的任何事情,但你可以区分'你可以做什么'和'你应该做什么'。你不需要'加载'任何东西,作曲家自动加载系统负责转换给你,你只需使用它们,它们就会自动加载。 –

+0

是的,所以'我应该'在app/models中创建一个文件并且扩展Eloquent并添加需要该类的操作?不应该将任何模型链接到一张表上?如果我需要那个模型中的几个db表呢?我可以(我应该!)在另一个模型中使用模型的动作吗?! – Webinan