程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 網頁編程 >> PHP編程 >> 關於PHP編程 >> Magento 開發筆記3

Magento 開發筆記3

編輯:關於PHP編程

我們在這個部分關注一下View裡Layouts和Blocks。   跟其他主流PHPMVC架構不一樣,magento 的ActionController不會把數據對象傳給view,也不會設置View對象裡的屬性。View是通過系統模塊去獲取它所需要的信息。   這個設計的結果是View被分為Blocks 和Templates。Blocks是PHP對象,Templates是PHP代碼和HTML的混合(也可以認為是PHP作為了模版語言)。每個Block綁定到一個Template文件。在一個Phtml文件裡,PHP的關鍵字$this會包含了對Temeplate對應Block的引用。   下面是一個快速的例子。查看模版文件app/design/frontend/base/default/template/catalog/product/list.phtml   會看到如下的代碼   <?php$_productCollection=$this->getLoadedProductCollection() ?>       <?phpif(!$_productCollection->count()): ?>    <divclass="note-msg">        <?php echo$this->__("There are no products matching the selection.")?>       </div>    <?php else: ?>     其中的getLoadedProudctController可以在對應的block文件找到   app/code/core/Mage/Catalog/Block/Product/List.php   public functiongetLoadedProductCollection()   {                        return$this->_getProductCollection();   }   其中的_getProductCollection會實例化models,並取到數據給對應template。   內嵌Block Blocks/Templates真正的強大的地方是getChildHtml方法。這可以讓我們包含次一級的Block/Template在主的Block/Template裡面(xml的格式)   Blocks調用Blocks是會組成我們整個HTMLlayout。看一個例子   App/design/frotend/base/default/template/page/1column.phtml   <!DOCTYPE htmlPUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <htmlxmlns="http://www.w3.org/1999/xhtml" xml:lang="?php echo$this->getLang() ?>" lang="<?php echo $this->getLang()?>"> <head> <?php echo $this->getChildHtml('head') ?></head> <body class="page-popup <?php echo$this->getBodyClass()?$this->getBodyClass():'' ?>">     <?php echo$this->getChildHtml('content') ?>    <?php echo $this->getChildHtml('before_body_end') ?>       <?php echo$this->getAbsoluteFooter() ?> </body> </html>    該文件不長,但是每個調用都是$this->getChildHtml(…),這會包含並渲染其他的block。這些block也可能會調用其他block 。   Layout                          盡管Block和Template很好,但是你可能會有下面的疑問   1.      我怎麼告訴Magento哪個Block在頁面中使用?   2.    我們怎麼告訴Magento是初始的   3.    我怎麼告訴每個Block去調用下面的block   這時候就需要Layout對象了。Layout對象是Xml格式,定義一個頁面裡包含哪些Blocks,並且哪些Blocks負責渲染頁面。   之前的Hello World項目我們直接在Action Method上做的。這次我們創建一個簡單的HTMLtemplate來為該模塊服務。   首先創建一個文件   App/design/frontend/base/default/layout/local.xml   然後寫入下面的內容   <layoutversion="0.1.0">        <default>            <reference name="root">                <block type="page/html"name="root" output="toHtml"template="simple_page.phtml" />           </reference>        </default>   </layout>       然後再創建一個文件   app/design/frontend/base/default/template/simple_page.phtml(注意和配置裡的template一致)   寫入以下內容   <!DOCTYPE html PUBLIC"-//W3C//DTD XHTML 1.0 Strict//EN"        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">   <htmlxmlns="http://www.w3.org/1999/xhtml">    <head>        <title>Untitled</title>        <metaname="generator" content="BBEdit 9.2" />        <styletype="text/css">            body {             background-color:#f00;         }       </style>   </head>   <body>     </body>   </html>    最後在Aciton Controller裡負責啟動layout過程。增加下面兩行代碼   public functionindexAction() {                    //remove our previous echo        //echo'Hello Index!';        $this->loadLayout();        $this->renderLayout();   }    清除緩存,重新加載Hello World controller頁面,可以看到頁面的背景hi紅色,並且Html源碼和simple_page.phtml也是對應的。   發生了什麼? 剛才的一切看上去很神秘。我們來仔細的看看這個過程。首先,我們想安裝Layoutviewer模塊。這個模塊和Configviewer很像。   一旦裝好了,就可以用下面的URL   http://localhost/magento/helloworld/index/index?showLayout=page   這個是一個layout xml對應於請求的頁面。由<block /> <refenece /> 和 <remove />標簽組成。當你調用loadLaout方法時,   1.      生成一個Layout xml   2.    實例化<block/> 和<reference />下面的Block類。查找用標簽name屬性的,在全局配置文件裡找到對應的,並儲存在Layout對象的internal_blocks數組裡。   3.     如果<block />標簽包含了輸出屬性,它的值也加入到Layout對象的internal_blocks數組裡。   這樣一來,當我們在Action Controller裡調用renderLayout時,Mageno 會迭代_blocks數組裡所有的Blocks, 並把它對應的輸出屬性作為回調函數。這相當於是向Html的轉化,意味著Block的Template就是輸出的起點。   下面的部分涉及到Block如何實例化,Layout文件如何生成,還有output的結束。   Block實例化 在LayoutXml裡,<block/>或者<reference/>有個類型相當於是URI   <block type=”page/html” …   <block type=”page/template_links”    URI會在全局配置文件指明一個地址。URI的第一個部分用來去查找全局配置文件,找到Page類名。第二部分跟在第一個部分後面成為新的類, 然後再實例化該類。   以page/html作為例子。首先Magento會在全局配置文件裡查找下面的   /global/blocks/page   然後找到   <page>               <class>                           Mage_Page_Block               </class>   </page>   這樣我們就得到了MagePageBlock類。然後,URI的第二部分會加在它後面成為MagePageBlock_Html。這個類隨後就會呗實例化。   Blocks也是Magento裡的組類,所有的共享類似的實例化方法。後面會有該部分的詳細介紹。   <block />和<reference />之間的不同 我們談到了<blocks/>和<references />都可以實例化Block,那他們有什麼不同呢。   先有   <blocktype="page/html" name="root" output="toHtml"template="page/2columns-left.phtml">     <!-- ... sub blocks ... --></block>       然後有   <layoutversion="0.1.0">        <default>            <reference name="root">                <block type="page/html"name="root" output="toHtml"template="simple_page.phtml" />           </reference>        </default>    </layout>       <reference />裡面的blocks不會替代blocks。相反,他們是增加,或者修改現有的blocks。上面的樣例中,是插入了一個新的叫root的block到現有的rootblock中。這在Magento Layout中是未定義的。最終結果是老的被替換掉了,但是靠此來保證一致性是很糟的主意。   Layout 文件如何生成 到現在我們對Layout XML應該有比較清晰的認識了。但是Layout XML從何而來?要解答這個問題,我們需要引入兩個新的概念,Handles和Package Layout。   Handles   Magento中的每個請求會生成幾個不同的Handles。Layoutview 模塊就可以給我們用URL展示這些   http://localhost/magento/helloworld/index/index?showLayout=handles   我們會看到類似   1.    默認   2.    STORE_bare_us   3.    THEME_frontend_default_default   4.    Helloworld_index_index   5.    Customer_logged_out   這些每個都是一個Handle。Handle在Magento的很多地方會被設置。我們需要關注其中兩個地方:default和helloworld_index_index.。默認的Handle是每個請求都會出現的。而Helloworld_index_indexHandle是通過合並frontName(helloworld),Actioncontroller (index), 和Action Controller Action Method(index)而成。這意味這每個ActionController方法都可能對應一個Handle。   記住“index”是Magento對每個Action Controller和ActionMethods的默認,因此下面的請求   http://localhost/magento/helloworld/?showLayout=handles   同樣會產生Handle的名字交helloworld_index_index   Package Layout   你可以認為PackageLayout等同於全局配置。他是一個大的XML文件,包含了Magento內每個可能的Layout配置。讓我們看一下   http://localhost/magento/helloworld/index/index?showLayout=package   這個可能會加載一會。如果浏覽器在xml下卡了,請換成text模式   http://localhost/magento/helloworld/index/index?showLayout=package&showLayoutFormat=text   你可以看到很大的XML文件。這就是Package Layout。它是綜合了所有當前主題下XMLLayout的文件。默認的安裝是   app/design/frontend/base/default/layout/   在全局文件裡面有個<updates />部分,節點中包含了所有要加載的名字。一旦配置文件中給出的文件合並了,Magento會合並到上一個xml文件,local.xml。這個可增加你想要的功能。   合並Hanldes和Packge Layout    如果你看到Package Layout, 你可以看到一些熟悉的標簽,例如<block />和<reference/>, 但是他們都類似這樣的標簽覆蓋   <default />   <catelogsearch_advanced_index/>   etc…   這些都是Handle標簽。一個請求的Layout是由所有匹配請求的Handles的Package Layout生成。因此,在上面的例子中,我們的layout是在下面的部分中生成   <default />   <STORE_bare_us />   <THEME_frontend_default_default/>   <helloworld_index_index/>   <customer_logged_out/>   還有一個標簽需要我們注意。<update />容許我們包含其他的Handle。例如   <customer_account_index>        <!-- ... -->        <update handle="customer_account"/>        <!-- ... -->    </customer_account_index>   這意味這請求到customeraccountindex時,應該包含<customer_account>下面的<reference/>和<block />.   學以致用         看夠了理論,我們來回顧一下之前的工作。   <layoutversion="0.1.0">        <default>            <referencename="root">                <blocktype="page/html" name="root" output="toHtml"template="simple_page.phtml" />           </reference>        </default>   </layout>    這個意味著我們重寫了root標簽。而<default/>部分保證了每次請求都會發生。這可能並不是我們想要的效果。   如果訪問任意其他頁面,我們同樣是空白頁面,或者是紅色背景(之前helloworl頁面的那樣)。所以我們改進一下local.xml,確保它只用於helloworld頁面。修改如下   <layout version="0.1.0">        <helloworld_index_index>            <referencename="root">                <blocktype="page/html" name="root" output="toHtml"template="simple_page.phtml" />           </reference>        </helloworld_index_index>    </layout>    清除cache,這個時候你的其他頁面應該恢復了。   然後應用到googbye Aciton Method   public function goodbyeAction() {     $this->loadLayout();     $this->renderLayout();           }        這個時候加載http://localhost/magento/helloworld/index/goodbye   會發現還是blank頁面。這個時候我們需要在local.xml增加一個actionname, 內容如下   <layout version="0.1.0">        <!-- ... -->        <helloworld_index_goodbye>            <updatehandle="helloworld_index_index" />        </helloworld_index_goodbye>   </layout>    清楚cache,這個時候,下面兩個頁面會有同樣的效果了。   http://localhost/magento/helloworld/index/index   http://localhost/magento/helloworld/index/goodbye   開始輸出並getChildHtml 在標准的配置中,輸出的開始是root命名的Block(這個是輸出的特性)。我們已經重寫了root的模版 template=”simple_page.phtml”   模版會從當前或者base主題的主目錄裡得到,如   app/design/frontend/base/default/template   通常你可以添加模版到你自己的主題或者默認主題   app/design/frontend/default/default/template   app/design/frontend/default/custom/template   base目錄是最後才會去查找的目錄,如果magento在其他主題下找不到,才會回到base目錄。可是,象之前提到的哪有,你不想加入到這樣的目錄,因為magento的更新會覆蓋他們。   增加內容block 紅色的悲劇很無聊。所以我們在頁面上增加點內容。改變local.xml裡的<helloworldindexindex />,如下   <helloworld_index_index>        <reference name="root">            <block type="page/html"name="root" template="simple_page.phtml">                <blocktype="customer/form_register" name="customer_form_register"template="customer/form/register.phtml"/>           </block>        </reference>    </helloworld_index_index>   我在root裡增加兩個內嵌的Block。Magento會分配它,並且展示一個客戶注冊的頁面。在root裡內嵌這個Block,我們要在simple_page.html裡面顯式的調用。所以我們用Block的getChildHtml方法,如下   <body>               <?php echo $this->getChildHtml(‘customr_form_register’); ?>   </body>   清除Cache,重新加載頁面。這個時候我們看到了注冊頁面在紅色的背景上。下面還有一個Block叫top.links。添加如下   <body>               <h1>Links</ht>               <?php echo $this->getChildHtml(‘top.links’); ?>   </body>   當我們重新加載頁面,就看到Links被渲染了,但是top.links沒有任何渲染。這是因為我們沒有在local.xml裡添加它。在Layout裡,getChildHtml只能包含顯示的作為子block的Blocks。這容許Magento實例化它想要的blocks,同時讓我們可以根據顯示內容為Block設置不同的模版   我們可以在local.xml裡為top.links增加Block   <helloworld_index_index>        <reference name="root">            <block type="page/html" name="root"template="simple_page.phtml">   <blocktype="page/template_links" name="top.links"/>                <block type="customer/form_register"name="customer_form_register"template="customer/form/register.phtml"/>           </block>        </reference>    </helloworld_index_index>   此時再清除cache,就可以看到top.links模塊的效果了        

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved