2013-10-21 240 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