Although Model-View-Controller (MVC) is known by nearly every Web developer, how to properly use MVC in real application development still eludes many people. The central idea behind MVC is code reusability and separation of concerns. In this section, we describe some general guidelines on how to better follow MVC when developing a Yii application.php
雖然幾乎每一個Web開發人員都知道MVC模型 - 視圖 - 控制器(MVC),可是正確地在實際應用中使用它的可能寥寥無幾。 MVC核心是代碼的重用和關注點的分離。在本節中,咱們描述了「如何在一個Yii應用中更好地遵循的MVC開發應用的」通常性的指導方針。前端
To better explain these guidelines, we assume a Web application consists of several sub-applications, such asweb
爲了更好地解釋這些準則,咱們假定Web應用程序由幾個子應用,如數據庫
The sub-applications may be implemented in terms of modules, or as a Yii application that shares some code with other sub-applications.後端
這些子應用可能爲其餘模塊提供接口或者是使用其餘yii應用的一些代碼。api
Models represent the underlying data structure of a Web application. Models are often shared among different sub-applications of a Web application. For example, a LoginForm model may be used by both the front end and the back end of an application; a News model may be used by the console commands, Web APIs, and the front/back end of an application. Therefore, models瀏覽器
模型是Web應用程序的底層數據結構。模型每每在不一樣的Web應用程序的子應用之間共享。例如,一個LoginForm的模型可能會被前端和後端應用程序使用;news模型可能同時被控制檯程序,webAPIs,和應用程序的前端/後端使用。所以,模型應該有一下特色:數據結構
should contain properties to represent specific data;app
應提供屬性來存儲特定的數據;框架
should contain business logic (e.g. validation rules) to ensure the represented data fulfills the design requirement;
應該包含業務邏輯(例如驗證規則)確保數據的有效性,以及確保符合設計要求;
may contain code for manipulating data. For example, a SearchForm model, besides representing the search input data, may contain a search method to implement the actual search.
可能包含操做數據的代碼。例如,一個SearchForm模式,除了表明搜索輸入數據,可能包含一個search方法來實現實際的搜索。
Sometimes, following the last rule above may make a model very fat, containing too much code in a single class. It may also make the model hard to maintain if the code it contains serves different purposes. For example, a News model may contain a method named getLatestNews which is only used by the front end; it may also contain a method named getDeletedNews which is only used by the back end. This may be fine for an application of small to medium size. For large applications, the following strategy may be used to make models more maintainable:
有時候,上述最後一條規則可能使一個模型變的冗長,在一個類中包含太多的代碼。它也可能使模型難以維持,由於可能它包含的代碼有不一樣的目的。例如,News模型可能包含名爲前端只使用getLatestNews一個方法,它也可能包含名爲getDeletedNews方法,爲後端使用。對於這多是中小規模的應用程序的能夠理解。可是在乎一個大型應用程序中就不適用了。可使用如下策略,以使模型更易於維護:
Define a NewsBase model class which only contains code shared by different sub-applications (e.g. front end, back end);
定義NewsBase模型類,只包含由不一樣的子應用程序(如前端,後端)共享的代碼;
In each sub-application, define a News model by extending from NewsBase. Place all of the code that is specific to the sub-application in this News model.
在每一個子應用中,例如定義News模型繼承NewsBase。將全部的和這個模型相關的代碼,放在News模型中。
So, if we were to employ this strategy in our above example, we would add a News model in the front end application that contains only the getLatestNews method, and we would add another News model in the back end application, which contains only the getDeletedNews method.
因此,若是上面的例子採用這一戰略,咱們應在前端應用程序增長News模型僅包含getLatestNews方法,在後端的應用程序中,新建另外一個News模型,其中包含只有getDeletedNews方法。
In general, models should not contain logic that deals directly with end users. More specifically, models
在通常狀況下,模型不該該包含與最終用戶直接交互的邏輯。更具體地說,模型應該具有以下特色:
should not use $_GET, $_POST, or other similar variables that are directly tied to the end-user request. Remember that a model may be used by a totally different sub-application (e.g. unit test, Web API) that may not use these variables to represent user requests. These variables pertaining to the user request should be handled by the Controller.
不該該使用$ _GET,$ _POST或其餘相似變量,例如直接關係到最終用戶的請求的數據。請記住,一個模型多是被用於多個徹底不一樣的子應用(例如,單元測試,Web API),因此不能使用這些表示用戶request的變量。和用戶相關的變量,應當由控制器處理。
should avoid embedding HTML or other presentational code. Because presentational code varies according to end user requirements (e.g. front end and back end may show the detail of a news in completely different formats), it is better taken care of by views.
應避免嵌入HTML或其餘層(例如視圖層)的代碼。由於視圖的代碼會根據不一樣用戶的需求而變化。(如前端和後端可能顯示的信息的格式徹底不同)。這樣的代碼更爲通用,能夠提供給不一樣的代碼層使用。
Views are responsible for presenting models in the format that end users desire. In general, views
視圖負責以最終用戶指望的樣式格式來顯示其餘模型的數據。通常狀況下,視圖應該具有以下特色:
should mainly contain presentational code, such as HTML, and simple PHP code to traverse, format and render data;
應主要包含控制顯示格式的代碼,如HTML,和簡單的PHP代碼來遍歷,格式和呈現數據;
should avoid containing code that performs explicit DB queries. Such code is better placed in models.
應避免包含執行明確的數據庫查詢的代碼。這樣的代碼是更好地放置在模型中。
should avoid direct access to $_GET, $_POST, or other similar variables that represent the end user request. This is the controller's job. The view should be focused on the display and layout of the data provided to it by the controller and/or model, but not attempting to access request variables or the database directly.
應避免直接訪問的$ _GET,$ _POST或其餘相似變量,表明最終用戶的請求的變量。這是控制器的工做。應側重於視圖,爲控制器和/或模型提供的數據顯示和佈局,但不試圖直接訪問請求變量或數據庫。
may access properties and methods of controllers and models directly. However, this should be done only for the purpose of presentation.
固然也能夠直接的使用控制器和模型的屬性和方法。可是不管怎樣這種用法僅用於演示目的。
Views can be reused in different ways:
視圖層重用的幾種方法
Layout: common presentational areas (e.g. page header, footer) can be put in a layout view.
Layout:一些公共的視圖區域(例如頁頭,頁腳)能夠在佈局視圖中。
Partial views: use partial views (views that are not decorated by layouts) to reuse fragments of presentational code. For example, we use _form.php partial view to render the model input form that is used in both model creation and updating pages.
使用局部視圖僅限於(不受佈局裝飾限制)重用的視圖代碼片斷。例如,在這兩個模型的建立和更新頁面中咱們可使用_form.php局部視圖來呈現模型的輸入形式。
Widgets: if a lot of logic is needed to present a partial view, the partial view can be turned into a widget whose class file is the best place to contain this logic. For widgets that generate a lot of HTML markup, it is best to use view files specific to the widget to contain the markup.
部件Widgets:若是在局部視圖中涉及到大量的邏輯,能夠建立一個widget,其中來存放全部的處理邏輯。對於widget,產生了大量的HTML標記,最好是使用特定的widget來包含這些標記的視圖文件。
Helper classes: in views we often need some code snippets to do tiny tasks such as formatting data or generating HTML tags. Rather than placing this code directly into the view files, a better approach is to place all of these code snippets in a view helper class. Then, just use the helper class in your view files. Yii provides an example of this approach. Yii has a powerful CHtml helper class that can produce commonly used HTML code. Helper classes may be put in an autoloadable directory so that they can be used without explicit class inclusion.
Helper類:在視圖中,咱們經常須要一些代碼片斷作微小的任務,如數據格式或生成HTML標記。這個代碼直接放置到視圖文件,不是一個更好的辦法。最好的方式是把全部這些代碼片段放在一個Helper類中。而後,只需在視圖文件中使用這個helper類。 Yii提供了不少這種helper。 例如YII具備強大的CHTML的助手類,它能夠產生經常使用的HTML代碼。 Helper類,可在一個autoloadable目錄中。
Controllers are the glue that binds models, views and other components together into a runnable application. Controllers are responsible for dealing directly with end user requests. Therefore, controllers
控制器是把模型,視圖和其它組件集成在一塊兒的,造成一個可運行的應用程序。控制器負責處理最終用戶的直接請求。所以,控制器應該具有以下特色:
may access $_GET, $_POST and other PHP variables that represent user requests;
可以使用$ _GET,$_POST和其餘表明用戶請求的PHP變量,;
may create model instances and manage their life cycles. For example, in a typical model update action, the controller may first create the model instance; then populate the model with the user input from$_POST; after saving the model successfully, the controller may redirect the user browser to the model detail page. Note that the actual implementation of saving a model should be located in the model instead of the controller.
用於建立模型實例和管理其生命週期。例如,在一個典型的模型更新操做,控制器可先建立模型實例,而後獲取用戶輸入的$ _POST數據,模型成功保存以後,控制器可能會重定向用戶瀏覽器的顯示模型的詳細信息頁面。須要注意的是實際執行處理過程應改位於模型中,而不是位於控制器中。
should avoid containing embedded SQL statements, which are better kept in models.
應避免含有嵌入式的SQL語句,這些應該放在模型中。
should avoid containing any HTML or any other presentational markup. This is better kept in views.
應避免包含任何HTML或任何其餘的視圖層的標記。這些應該放在視圖層完成。
In a well-designed MVC application, controllers are often very thin, containing probably only a few dozen lines of code; while models are very fat, containing most of the code responsible for representing and manipulating the data. This is because the data structure and business logic represented by models is typically very specific to the particular application, and needs to be heavily customized to meet the specific application requirements; while controller logic often follows a similar pattern across applications and therefore may well be simplified by the underlying framework or the base classes.
在一個設計良好的MVC應用程序中,控制器,每每是很是簡單的,可能只含有幾十行的代碼,而模型是很是龐大複雜的,含有大部分業務邏輯和操作數據的代碼。這是由於數據結構和業務邏輯一般須要很是具體的,特定的應用,須要大量定製,以知足特定的應用需求,而每每控制器邏輯一般在大部分的應用程序中都是一個相似的模式,因此應當儘量被簡化底層框架或基類。