2011-11-20 71 views
3

我不使用一種現成的,現成的框架,沒有特別想(也不d我想進入的原因......)。總之,在我的問題上,我希望它是有意義....PHP MVC原則

我試圖讓我的頭圍繞什麼,應該在模型中,哪些應該在控制器中去。最初我有這樣的印象,模型類應該代表一個實際的對象(例如 - 從汽車數據庫表中的汽車),模型屬性應該反映數據庫字段。然而,我現在感覺我有一個錯誤的想法 - 模型類的實例應該代表一個實際的物品,還是應該包含許多用於實現物品的方法 - 有時用於一輛汽車,有時用於多輛汽車基於我之前的例子。

比如我想從數據庫中獲取所有的車,並告訴他們在視圖中。我是否認爲它應該符合這一點?

控制器的文件

function list() { 
    $cars = $this->model->get_all(); 
    $this->view->add($cars); 
    $this->view->render('cars-list'); 
} 

模型文件

function get_all() { 
    // Use a database interaction class that I've written 
    $cars = Database::select(); 

    return $cars; 
} 

現在,如果車上有這樣的被存儲在數據庫中的整數的「狀態」欄,我想將其改爲字符串,應該在哪裏完成?通過在模型中的get_all()方法中循環SQL結果數組?

另外,應該在哪裏進行驗證生活?我寫了一個有效的驗證類:

$validator = new Validator();  
$validator->check('field_name', 'required'); 

如果檢查失敗,它會向驗證器中的數組添加錯誤消息。這個錯誤消息數組然後會傳遞給視圖。應該使用我的驗證器類進入模型還是控制器?

預先感謝任何幫助任何人都可以提供。如果您知道任何指向處理基本CRUD的簡單MVC示例/開放源碼應用程序的鏈接,他們將非常感激。

+1

如果你不想使用'現成的框架',爲什麼這被標記爲codeigniter? – Flukey

+0

在CI中,表單驗證通常在您的控制器中完成。這對我來說很合理,因爲你的控制器應該處理表單輸入,POST,GET等。 – MikeMurko

回答

1

如果你想在狀態字段將被視爲您的應用程序中的字符串,你不想讓它在你的數據庫的整數從汽車類爬出來的持久性細節。在它的界面中,它是一個字符串,因此應該對其進行處理。

所以,我會用在汽車類)一getStatus()方法,其中你會調用GETALL AFTER(,當你需要它。您將在項目級別下放演員。最好不要讓其他應用程序知道您的最低級別是整數。從汽車上暴露出一個字符串,並在應用程序的其餘部分中繼續使用它。

至於驗證,我會做它的控制器。你從視圖中獲得東西,並確保它足夠適合你的模型。除非在模型中特別需要進行檢查(IE業務相關約束)。

1

首先,如果你不希望使用任何PHP框架,你可以看看他們的來源和獲取有關的一些功能實現好主意。

有關驗證,我覺得這是一個業務邏輯功能,因此必須將其放置在控制器層。 (編輯:這是個壞主意)

+2

嗯......我不同意你的第二個陳述。如果它是商業邏輯功能,它可能更適合模型,而不是控制器。 IE如果你需要驗證一個SSN,你可以在控制器中檢查一個字符串是否傳遞給模型,但是在模型中代碼是正確的。有恕我直言2級的驗證。只是我的2美分... – maraspin

+0

是的,我同意你的看法。我錯了。 例如,現在我看看Yii的源代碼,並確信在這個框架驗證模型類的地方。我犯了一個錯誤。 –

+0

不用擔心。錯誤滋生進展。我很高興我過去犯過的所有錯誤。除非我重複一遍:-D – maraspin

4

我強烈建議你看看"Patterns of Enterprise Application Architecture"Martin Fowler。它很好地解釋了每個MVC組件的職責分工(以及其他有用模式的批次)。

在一個捏,維基百科有一個好的解釋MVC

總之,您設置的結構是正確的。您是控制器通知模型某事件已經發生,該模型對該事件作出反應,然後該視圖使用該模型向最終用戶表示該系統的狀態。驗證應在您的模型中執行,因爲它負責維護系統的正確狀態。您也可以進行一些客戶端驗證,嚴格限制網絡流量併爲用戶提供更好的界面。

有一點要記住的是,你想保持你的業務邏輯模型。你想盡量避免所謂的anemic domain model。當你的模型僅僅是一個數據庫的薄木板時,這是非常典型的。

我推薦的另一本書是Eric Evans的"Domain-Driven Design: Tackling Complexity in Software"DDD的重點是「主要關注點應該在域和域邏輯上」。

+1

我認爲hafichuk給了你一些非常好的資源,這些資源也是我推薦給我的。本質上有很多方法可以解決這個問題(從存儲庫,數據映射器等),所有這些都取決於你的解決方案需要多複雜。對我而言,你發佈的解決方案不僅僅是有效的。 如果你想完全OOP,你可以嘗試使用數據映射器模式(如Doctrine)...但頭痛並不值得上述簡單。 – MikeMurko

4

責任的MVC中的一般擊穿通常如下:

  • 型號:商業邏輯。很多人認爲模型只是數據庫的一個接口,但這是不正確的。系統中的模型應描述系統中的所有實體,它們的行爲方式以及它們如何交互。數據訪問只是其中的一小部分(甚至可以將其分成與模型,視圖或控制器分開的自己的數據訪問層)。例如,在博客應用程序中,博客將包含一系列帖子,並且每個帖子可能具有(取決於博客應用程序實現的功能)一系列評論。這意味着要實現一個博客類,一個職位類和一個評論類。如果您選擇刪除帖子,那麼這是帖子的責任,以確保它不會留下任何孤兒評論。你可以通過在post類中刪除帖子的方法以及類註釋中的類似方法來做到這一點。當帖子發送刪除消息時,它將作爲刪除過程的一部分向與所刪除的帖子相關聯的所有評論發送刪除消息。
  • 查看:演示邏輯。一個視圖基本上是一個網頁,一個RSS源,一個CSV文件,實際上是你的應用程序可能輸出給最終用戶的任何類型的數據。它應該只顯示已分配給它的變量。 (可以在視圖中實現一些邏輯,只要輸出數據就可以,視圖不必完全啞)
  • 控制器:膠水邏輯。控制器基本上有兩個工作要做:1)從模型中獲取數據,將其注入視圖並呈現給用戶。 2)從用戶處獲得輸入,將其發送到適當的模型進行處理並將結果呈現給用戶。這意味着控制器應該只包含很少的代碼,只是實現上面列出的兩個目標所需要的。

正如我已經提到的,很多人認爲模型只是一個數據訪問層。你通常可以知道人們什麼時候遵循這個設計原則,因爲結果是那些做得不好的模型和做得太多的控制器(所謂的Fat Controller反模式)。這種方法的問題在於,如果您想在其他項目中重用部分代碼庫,那麼您無法將模型轉移到新項目中,而無需將大部分控制器一起使用。控制器通常被認爲是特定於應用程序的,因此不可重用。另一方面,模型在應用程序中體現實體,並且您可能有多個應用程序需要使用相同類型的實體(博客軟件,電子商務店面和留言板都是非常不同的應用程序,但它們都需要實現用戶)。通常,你需要胖模型(可以很容易地重複使用,而不需要複製在模型本身中沒有實現的代碼)和瘦型控制器(當你需要你的模型來做其他事情時可以很容易地被替換)。

雖然驗證類型引發了扳手,但它是所謂的橫切關注點。 MVC的想法是將關注點分離出來,因爲它旨在將代碼描述爲三大類別之一(業務邏輯,表示邏輯,膠合邏輯),但驗證不容易適用於其中任何類別。如果您想向用戶顯示驗證錯誤,那麼可以將它作爲業務邏輯和膠合邏輯,從而獲得良好的參數,那麼它也具有表示邏輯的元素。一般來說,我在我的模型中實現了驗證級別,通常是相當基本的完整性檢查(例如要求整數實際上是值之間的等等),並且實現一組單獨的類來完整驗證輸入。我將調用我的控制器中的驗證類,如果驗證失敗,我會將結果呈現給視圖。如果成功,那麼數據將被髮送到相關模型進行處理。我想你可以調用驗證「實用邏輯」,你需要定期做的事情,你不能綁定任何模型,視圖或控制器。