標籤:

Joomla MVC 組件開發 (1)

Joomla MVC 組件開發 (1)

docs.joomla.org

譯者: Danny Zhou 2011年01月05日 13:58 原作者: danny_zhou

通過開發一個簡單的Hello world 組件,來引導讀者學習如何開發Joomla組件,並展示Joomla的強大功能及MVC設計模式的通用性。

頻道: 科技 類別: 文章 標籤: 開發,建站,joomla,組件

  • 譯文
  • 雙語閱讀
  • 原文閱讀
  • 全屏顯示
  • 介紹

    軟體框架是一個可由開發人員使用的應用基礎。Joomla 1.5框架為開發人員開放了強大的功能。Joomla 代碼採用了可擴展的設計。本教程引導你使用框架來開發一個組件的全過程。

    項目的範圍是開發一個簡單的Hello world 組件。在後續的教程中,將通過這個簡單的組件來展示Joomla強大的功能和MVC設計模式的通用性。

    需求

    本教程需要Joomla 1.5或更高版本。

    介紹MVC Model-View-Controller

    雖然這個組件的設想比較簡單,但是隨著功能特性的添加或自定義界面,程序代碼將很快會變得非常複雜。

    Model-View-Controller(以下簡寫為MVC)是一種軟體設計模式,它被用來組織業務邏輯和數據存儲分離的程序代碼。在將業務邏輯封裝到一個模塊的前提下,修改和定製用戶界面和用戶交互數據時,就不在需要重新編寫業務邏輯。最初MVC被用來將傳統的輸入、處理和輸出映射為GUI架構。

    而這三個主要的角色就是Joomla MVC的基礎。在這裡將對它們進行簡要的描述,更加詳細的資料,請參與本教程結尾處提供的鏈接。

    模型(Mode

    模型是組件中封裝應用程序數據的部分。除了從模型中獲取數據外,它通常還提供有效的方法來管理和操作數據。在我們的例子中,模型包含了用來增加、刪除和更新資料庫中greetings信息的方法。還包括從資料庫中檢索greetings列表的方法。一般來說,底層的數據訪問技術應該被封裝在模型中。這樣,如果將應用程序從順序文件存儲系統遷移到資料庫系統,則僅僅需要改變模型單元,而不是視圖或控制器。

    視圖(View

    視圖是組件中在用戶交互模型中以恰當的方式向用戶呈現數據的部分。對於基於WEB的應用程序,視圖通常指的是返回數據的HTML頁面。視圖從模型獲取數據(通過控制器傳遞給視圖),將數據注入到合適模板,並呈現給用戶。視圖不會引起任何數據變更,它僅顯示從模型中獲取的數據。

    控制器(Controller

    控制器負責響應用戶的動作。在WEB應用程序的案例中,用戶動作(通常)是一個頁面請求。控制器將決定用戶建立那些請求,通過激活合適的數據操作模型來對請求做出恰當的響應,並將模型傳遞給視圖。控制器不直接在模型中顯示數據,它僅僅觸發修改數據的模型方法,然後將模型傳遞給顯示數據的視圖。

    MVC 連接

    右邊的簡圖描繪了Joomla中MVC的基本構成。除了模型、視圖和控制器外,加入了一個用小圓圈表示的入口。增加了連接到視圖的模板。藉助這五個部分,你應該能夠理解製作基本Joomla MVC組件的教程。

    本教程的第一節僅關注於控制器和視圖(也會使用模板),圖中藍色標記的部分。第二節和第三節增加、擴展了模型的抽象數據操作功能,圖中標記綠色的部分。

    請記住,這個簡圖僅適用於網站部分(即前端部分)。與之類似的簡圖適用於管理部分(即後端部分。本組件開發教程的4-6節中將關注管理部分。網站和管理部分都將通過基於XML的安裝文件(通常叫做manifest文件)來維護和配置。

    Joomla! MVC 實現

    在Joomla中,MVC模式使用三個類來實現:JModel, JView and JController。如需這些類更詳細的信息,請參閱API參考文檔(WIP)。

    出於學習目的和調試,尤其是在開發(教程)組件的過程中,將運行時調試器加入到您的Joomla網站應該是一個好的做法。一個很好的例子是社區項目J!Dump,它具有在不影響原輸出的情況下彈出調試窗口的優點。J!Dump系統不僅允許您查看開發屬性,還能夠查看方法的屬性。

    建立組件

    對於基本的組件,我們僅需要五個文件:

    <!--[if !supportLists]-->§ <!--[endif]-->site/hello.php – 這個文件是我們組件的入口

    <!--[if !supportLists]-->§ <!--[endif]-->site/controller.php – 這個文件是組件的主控制器

    <!--[if !supportLists]-->§ <!--[endif]-->site/views/hello/view.html.php – 這個文件獲取必要的數據並注入到模板

    <!--[if !supportLists]-->§ <!--[endif]-->site/views/hello/tmpl/default.php – 這個是輸出模板

    <!--[if !supportLists]-->§ <!--[endif]-->hello.xml – 這是用於Joomla安裝的XML(manifest)配置文件

    請記住,入口的文件名和組件的名字必須相同。例如,如果在安裝的時候調用組件」 Very Intricate Name Component」,則Joomla會建立目錄com_veryintricatenamecomponent,並且入口php文件必須被命名為veryintricatenamecomponent.php,否則該組件將無法正常運行。請注意,一些特殊的字元,特別是下劃線」_」,對Joomla來說有特殊的含義,應該盡量避免在組件和文件名字中使用。

    這裡的網站目錄是指所安裝組件的前端部分。

    命名約定

    主要文章:Naming conventions

    預留一些詞用於組件或類的命名這點是很重要的,而違反這些命名將產生嚴重的調試錯誤。其中之一就是用於view類(JView的子類)和controller類(JController的子類)的」 view」(不區分大小寫),因為view類的名稱需要與controller類名、component名稱有相同的第一部分(儘管最後一個只不過是常用的約定,違反它不會產生錯誤)。

    所有的模型、視圖和控制器的文件名和目錄名必須小寫,以能夠在Unix/Linux中方便地使用。

    創建入口點

    Joomla一直通過簡單的入口來訪問:網站應用使用index.php或者管理員應用使用administrator/index.php。之後,應用將根據URL或POST數據中的』option』的值,來載入請求的組件。對於調用我們的組件,URL應該是:

    index.php?option=com_hello&view=hello

    這將載入主文件,該文件可以被看作我們組件的一個簡單的入口點:components/com_hello/hello.php。

    該文件的源代碼在組件中相當典型。

    入口點site/hello.php的源代碼:

    <?php

    /**

    * @packageJoomla.Tutorials

    * @subpackage Components

    * components/com_hello/hello.php

    * @linkhttp://docs.joomla.org/Developing_a_Model-View-Controller_Component_-_Part_1

    * @licenseGNU/GPL

    */

    // No direct access

    defined( "_JEXEC" ) or die( "Restricted access" );

    // Require the basecontroller

    require_once( JPATH_COMPONENT.DS."controller.php" );

    // Require specificcontroller if requested

    if($controller = JRequest::getWord("controller")) {

    $path = JPATH_COMPONENT.DS."controllers".DS.$controller.".php";

    if (file_exists($path)) {

    require_once $path;

    } else {

    $controller = "";

    }

    }

    // Create thecontroller

    $classname = "HelloController".$controller;

    $controller = new $classname( );

    // Perform the Requesttask

    $controller->execute( JRequest::getWord( "task" ) );

    // Redirect if set bythe controller

    $controller->redirect();

    第一行語句是安全檢查。

    JPATH_COMPONENT是當前組件的絕對路徑,在本例中是components/com_hello。如果需要特別指定是網站組件還是管理員組件,你可以使用JPATH_COMPONENT_SITE或JPATH_COMPONENT_ADMINISTRATOR。

    DS是系統的目錄分隔符:』/』 或 』』。它由框架自動設置,因此開發者不需要關心為不同的操作系統開發不同版本的問題。當使用本地文件時,也應該一直使用』DS』常數。

    在載入主控制器後,檢查是否需要特定的控制器。在本例中,因只有主控制器,我們略過這個條件,在將來使用時再檢查。

    JRequest:getWord()用來獲取URL或POST數據中的字元變數。如果URL是index.php?option=com_hello&controller=controller_name,則我們能夠獲取組件所使用控制器的名字:echo JRequest::getWord("controller");

    現在,我們有了com_hello/controller.php中的主控制器"HelloController",並且若需要可以添加控制器,如com_hello/controllers/controller1.php中"HelloControllerController1"。使用標準的命名方式將使後面的工作變得簡單:

    "{Componentname}{Controller}{Controllername}"

    控制器建立之後,調用控制器執行任務,在URL中定義為:index.php?option=com_hello&task=sometask。若沒有設置具體的任務,則執行默認任務"display"。當執行display任務時,』view』 變數將判斷顯示什麼內容。其它一些常見任務是保存(save)、編輯(edit)、新建(new)…

    完成任務(如:"save")後,通常控制器會決定重定向的頁面。最後一行語句來確定實際的重定向頁面。

    本質上講,主入口點(hello.php)將控制權交給了控制器,控制器來執行在請求中指定的任務。

    注意:我們沒有在該文件中使用php關閉標記:?>。這樣做的原因是,在輸出代碼中我們不會有任何不必要的空格。這是自Joomla 1.5以來用於所有PHP文件的默認做法。

    創建控制器

    我們的組件僅有一個任務 - greet the world。因此,控制器非常簡單。沒有數據操作請求。需要做全部工作就是載入合適的視圖。控制器也只有一個方法:display()。JController內置了大多數必須的功能,因此我們只要調用JController::display()方法即可。

    主控制site/controller.php的源代碼:

    <?php

    /**

    * @package Joomla.Tutorials

    * @subpackageComponents

    * @linkhttp://docs.joomla.org/Developing_a_Model-View-Controller_Component_-_Part_1

    * @license GNU/GPL

    */

    // No direct access

    defined( "_JEXEC" ) or die( "Restricted access" );

    jimport("joomla.application.component.controller");

    /**

    * Hello WorldComponent Controller

    *

    * @package Joomla.Tutorials

    * @subpackageComponents

    */

    classHelloController extends JController

    {

    /**

    * Method todisplay the view

    *

    * @access public

    */

    functiondisplay()

    {

    parent::display();

    }

    }

    除非特別指定(使用registerDefaultTask()方法),JController構造函數總是註冊display()任務,並將其設置為默認任務。

    重寫方法display()並不是完全必要的,因為它所要做的就是調用父類的構造方法。不過,這是個好的做法,這能夠提示控制器中所發生的事情。

    JController::display()方法根據請求來決定視圖的名稱和布局,並載入視圖和設置布局。當為組件建立菜單項時,菜單管理器將允許管理員選擇我們想要的視圖,就是菜單鏈接所顯示和指定的布局。視圖通常會關聯一個特定的數據集合(如汽車列表、事件列表、一個車、一個時間等)。布局是視圖組織的方式。

    在我們的組件中,我們有個簡單的視圖叫做hello,和一個簡單的布局(默認的)。

    創建視圖

    視圖的任務非常簡單。獲取用來顯示的數據並且將其注入到模板。使用JView::assignRef方法將數據注入到模板。(注意:傳遞給assignRef方法的鍵值(第一個參數)不能以下劃線開頭,即$this->assignRef("_greeting",$greeting)。這樣做assignRef方法會返回false,並無法將變數值注入到模板中)

    視圖site/views/hello/view.html.php 的源代碼:

    <?php

    /**

    * @package Joomla.Tutorials

    * @subpackageComponents

    * @linkhttp://docs.joomla.org/Developing_a_Model-View-Controller_Component_-_Part_1

    * @license GNU/GPL

    */

    // no direct access

    defined( "_JEXEC" ) or die( "Restricted access" );

    jimport( "joomla.application.component.view");

    /**

    * HTML View classfor the HelloWorld Component

    *

    * @package HelloWorld

    */

    classHelloViewHello extends JView

    {

    functiondisplay($tpl = null)

    {

    $greeting = "HelloWorld!";

    $this->assignRef( "greeting", $greeting );

    parent::display($tpl);

    }

    }

    創建模板

    Joomla模板/布局是常規的PHP文件,其用特殊的方式來布局視圖中數據。使用JView::assignRef方法綁定的變數,在模板中能夠通過$this->{propertyname}的方式來訪問(見下面模板代碼例子)。

    模板非常簡單:僅僅顯示從視圖傳遞來的greeting變數值。文件是site/views/hello/tmpl/default.php:

    <?php

    // No direct access

    defined("_JEXEC") or die("Restrictedaccess"); ?>

    <h1><?php echo $this->greeting; ?></h1>

    組合起來創建 hello.xml 文件

    通過FTP複製文件和修改資料庫表,手工安裝組件是可以的。不過,通過創建包文件,讓Joomla為你安裝組件更為高效。包文件包括一些信息:

    <!--[if !supportLists]-->§ <!--[endif]-->組件的基本描述信息(即名字等)、及選項、說明、版權和許可信息。

    <!--[if !supportLists]-->§ <!--[endif]-->需要複製文件的清單。

    <!--[if !supportLists]-->§ <!--[endif]-->可選,執行額外安裝和卸載操作的PHP文件。

    <!--[if !supportLists]-->§ <!--[endif]-->可選,在安裝/卸載過程執行資料庫查詢的SQL文件。

    hello.xml文件的 XML格式如下:

    <?xml version="1.0" encoding="utf-8"?>

    <install type="component" version="1.5.0">

    <name>Hello</name>

    <!-- The following elements are optionaland free of formatting constraints -->

    <creationDate>2007-02-22</creationDate>

    <author>JohnDoe</author>

    <authorEmail>john.doe@example.org</authorEmail>

    <authorUrl>http://www.example.org</authorUrl>

    <copyright>CopyrightInfo</copyright>

    <license>LicenseInfo</license>

    <!--The version string is recorded in the components table -->

    <version>1.01</version>

    <!-- The description is optional anddefaults to the name -->

    <description>Descriptionof the component ...</description>

    <!-- Site Main File Copy Section -->

    <!-- Note the folder attribute: Thisattribute describes the folder

    to copy FROMin the package to install therefore files copied

    in thissection are copied from /site/ in the package -->

    <files folder="site">

    <filename>controller.php</filename>

    <filename>hello.php</filename>

    <filename>index.html</filename>

    <filename>views/index.html</filename>

    <filename>views/hello/index.html</filename>

    <filename>views/hello/view.html.php</filename>

    <filename>views/hello/tmpl/default.php</filename>

    <filename>views/hello/tmpl/index.html</filename>

    </files>

    <administration>

    <!-- Administration Menu Section -->

    <menu>HelloWorld!</menu>

    <!-- Administration Main File Copy Section-->

    <files folder="admin">

    <filename>hello.php</filename>

    <filename>index.html</filename>

    </files>

    </administration>

    </install>

    這個xml文件也叫做manifest,將該文件放置到包的根目錄(因為安裝程序會以此作為其它文件的根目錄)

    不包括xml文件自身。

    你可能已經注意到,manifest文件中提到了我們還沒有討論過的文件。這就是index.html文件和admin文件。為防止窺探用戶獲取目錄列表,需要將index.html文件放置在每一個目錄。如果沒有index.html文件,一些WEB伺服器將列出目錄內容。這是不安全的。這些文件只有簡單的一行:

    <html><body bgcolor="#FFFFFF"></body></html>

    僅簡單地顯示空白頁面。

    在admin目錄下的hello.php文件是組件管理單元的入口點。目前組件還沒有管理員需求,所以該文件的內容和index.html文件的內容相同。

    如果你完成了上述步驟,可以訪問index.php?option=com_hello來查看成果。


    推薦閱讀:

    談談 Vue 業務組件

    TAG:組件 |