Konstrukt PHP REST框架 教程二
入門 - 第2部分
在本教程中,我們假設(shè)你已經(jīng)完成了第一個教程,因為它的基礎(chǔ)上產(chǎn)生的代碼從該。
談判的Content-Type
在大多數(shù)情況下會發(fā)出一個Web應用程序的HTML。這是其中紙幅是由織物。不過,一旦在一段時間內(nèi),我們可能會產(chǎn)生其他類型的反應。在這種情況下,我們顯然不希望得到包裹在常規(guī)文檔渲染輸出。為此,我們需要一個不正常的反應。我們已經(jīng)看到異常反應的1種,與k_PageNotFound,但這個時候,我們需要一個更具體的一種。我們將擴大接觸元件的能力,呈現(xiàn)為一個電子名片。
要為不同的內(nèi)容類型提供一個的ressource,,我們使用Konstrukts,內(nèi)置支持內(nèi)容協(xié)商機制,這是一個經(jīng)常沒有得到充分利用的功能的HTTP協(xié)議。為了得到這個,我們需要編輯的“實體”的組成部分,因此,可以派生出的GET請求的HTML或vCard的處理程序。我們可以這樣做手動()方法,但有通用的掛鉤可用于這一目的。經(jīng)過修訂的組件,我們結(jié)束了這一點:
<?php class components_contacts_Entity extends k_Component {function renderHtml() {global $contacts;$contact = $contacts->fetchByName($this->name());if (!$contact) {throw new k_PageNotFound();}$this->document->setTitle($contact->full_name());$t = new k_Template("templates/contacts-entity.tpl.php");return $t->render($this, array('contact' => $contact));}function renderVcard() {global $contacts;$contact = $contacts->fetchByName($this->name());if (!$contact) {throw new k_PageNotFound();}$t = new k_Template("templates/contacts-entity-vcard.tpl.php");$response = new k_HttpResponse(200, $t->render($this, array('contact' => $contact)));$response->setContentType('text/x-vcard');return $response;} }正如你可以看到,我們現(xiàn)在有兩種渲染方法,而不是一個單一的get()方法。默認的GET()方法將使用這些映射分發(fā)到一個或另一個,使用內(nèi)容類型協(xié)商。從渲染的名字,你可以找到文檔中的內(nèi)容類型有一個默認的映射。
里面的vCard渲染,我們要創(chuàng)建一個正常的反應。正如上面所討論的,這就避免了的正常渲染管線,并允許我們細粒度控制的確切HTTP響應發(fā)送出去。
當然,我們需要的模板與在?templates/contacts-entity-vcard.tpl.php:
BEGIN:VCARD VERSION:3.0 N:<?php echo $contact->first_name(); ?>;<?php echo $contact->last_name() . "\n"; ?> FN:<?php echo $contact->full_name() . "\n"; ?> EMAIL;TYPE=PREF,INTERNET:<?php echo $contact->email() . "\n"; ?> REV:<?php echo date("Y-m-dTH:i:sZ") . "\n"; ?> END:VCARD現(xiàn)在,我們的組件可以呈現(xiàn)在兩個不同的內(nèi)容類型,這取決于客戶端的請求。看到這個動作,你可以使用命令行工具,卷曲。轉(zhuǎn)到命令行輸入:
curl --dump-header - --header "Accept: text/html" http://localhost/foo/www/contacts/jabba你會得到一個轉(zhuǎn)儲的HTTP響應,為text / html的。現(xiàn)在嘗試請求文本/ X-電子名片:
curl --dump-header - --header "Accept: text/x-vcard" http://localhost/foo/www/contacts/jabba正如你可以看到,相同的組件現(xiàn)在可以返回不同的表現(xiàn)形式,這取決于客戶端上的偏好。這是按照HTTP協(xié)議和客戶端都能夠處理它就好了,但最常見的客戶端-瀏覽器-一般都沒有。因為這一點,有一種替代方法。您可以指定的內(nèi)容類型后的組件名稱,由逗號分隔的(事實上,你應該使用的短名稱,而不是完整的MIME類型,名稱)。在這種情況下,你可以導航到“http://localhost/foo/www/contacts/jabba.vcard“,這將產(chǎn)生同樣的結(jié)果,如果你要求的頁面接受頭指定,它希望文本/ X-vcard的。試試吧:
curl --dump-header - http://localhost/foo/www/contacts/jabba.vcard請注意,Konstrukt的忽略了接受頭,當指定了一個簡短的名稱-短名優(yōu)先。因此,下面還給出了一個電子名片:
curl --dump-header - --header "Accept: text/html" http://localhost/foo/www/contacts/jabba.vcard整理的代碼了一下
正如你可能已經(jīng)注意到上面,有一些重復兩者之間的渲染功能。我們可以減少這由它的一部分移動到組件上的一個更一般的處理程序。在這種情況下,頂層(dispatch()中)適合:
<?php class components_contacts_Entity extends k_Component {protected $contact;function dispatch() {global $contacts;$this->contact = $contacts->fetchByName($this->name());if (!$this->contact) {throw new k_PageNotFound();}return parent::dispatch();}function renderHtml() {$this->document->setTitle($this->contact->full_name());$t = new k_Template("templates/contacts-entity.tpl.php");return $t->render($this, array('contact' => $this->contact));}function renderVcard() {$t = new k_Template("templates/contacts-entity-vcard.tpl.php");$response = new k_HttpResponse(200, $t->render($this, array('contact' => $this->contact)));$response->setContentType('text/x-vcard');return $response;} }這也可以作為一個機會,利用Konstrukt的一個強大的功能,被稱為包裝。下面的代碼片斷添加到/ var /網(wǎng)絡/富/ lib目錄/組件/聯(lián)系我們/ list.php的:
<?php class components_contacts_List extends k_Component {...function wrapHtml($content) {return ' <p><a href="' . htmlspecialchars($this->url()) . '">List contacts</a></p> <div id="content"> ' . $content . ' </div>';}... }這將是呈現(xiàn)的一個子組件(如components_contacts_Entity)時,響應將被裝飾。只適用于HTML的響應,因此,我們的的電子名片響應將不會受到影響。這提供了一個便捷的方式,將導航和類似的片段,HTML,涉及到的URL層次結(jié)構(gòu)中的位置。
現(xiàn)在我們已經(jīng)介紹了一些有關(guān)的調(diào)度過程的概念。但是,要了解它們是如何結(jié)合在一起的,什么是真正發(fā)生在庫中,我們將不得不退后一步:
間奏曲 - 組件的指揮鏈
(您可以跳過這一節(jié),如果你的腦袋是太滿)
上面的圖描繪的過程,通過在執(zhí)行過程中的一個組成部分。
一個組件啟動調(diào)度()方法處理。這確定是否有任何更多的元件,分派到或者如果這是在鏈中的最后。在嵌套的路徑,每個組件將進入調(diào)度()方法,然后委托給下一個,直到最后一段路徑到達。
如果有下一個組件,dispatch()中使用第一問map()的組件類名稱翻譯的路徑段。,然后調(diào)用()?,它實例化的組件和代表,在接下來的組件啟動過程。
鏈中的最后一個組成部分,將委托給其自己的execute()方法,而不是forward()方法。這將進一步委托給對應的HTTP方法的方法,通常是GET()?。最后,GET()方法調(diào)用的render(),它會嘗試找到一個合適的渲染派遣的方法,根據(jù)所請求的內(nèi)容類型(決定?接受標題或URL前綴)和-如果適用-子視圖。
當向前()方法調(diào)度到另一個組件,它會收到一個k_Response的的對象。這是發(fā)送到包()方法。包()會檢查是否有任何包裝相匹配的內(nèi)容類型的響應。如果是的話,它會通過這個管裝飾的響應。為使導航類的東西包裝是非常有用的。我對你看一看根組件(位于/ var /網(wǎng)絡/富/ lib目錄/組件/ root.php),你會看到,它有一個方法wrapHtml的。每次一個子組件返回一個HTML的響應,使用這種方法來裝飾它。包()只要求向前的execute()方法,進一步增強包裝dispatch()中的結(jié)果。因此,根包裝本身為HTML的反應。
所有這些方法可能看起來有點吃不消了,它可能是最復雜的部分Konstrukt的。你并不需要了解的細微差別,以便能夠使用Konstrukt的,但如果你想獲得最大的利益庫的,它需要的知識。有這么多的方法在調(diào)度點是,它給不同點鉤,這取決于你意圖。所以這是非常罕見的任何部件來使用所有這些功能在。的方式呈現(xiàn)()和地圖()的作品,對于初學者來說,是最重要的。
發(fā)帖和形式
大多數(shù)Web應用程序與用戶輸入的HTML的形式做。組件可以實現(xiàn)一個處理程序的任何HTTP方法-包括POST,這是密切相關(guān)的形式。您可以實現(xiàn)組件的POST()方法,來處理所有的POST請求,但就像你不應該實現(xiàn)GET()?,而是依靠渲染方法,你不應該直接執(zhí)行POST()?。相反,您可以實現(xiàn)postForm(),接受常規(guī)應用程序/ x - www的形式,進行了urlencoded類型多聯(lián)表格(通常用于文件上傳)請求(一個HTML表單的默認編碼),或postMultipart()?。如果你想支持其它輸 ??入格式,同樣的規(guī)則適用于-?postXml()會接受的Content-Type頭設(shè)置為text / xml的?POST請求。PUT類型的請求遵循相同的規(guī)則。
通過主體()方法的有效載荷中的請求-通常字段的一種形式-可被訪問。這相當于PHPS本地超全局變量$ _POST,就像查詢()對應于$ _GET。這種命名是比較正確的,因為查詢字符串是在所有的請求-不只是得到,可以與其他類型的請求,如PUT和有效載荷。
要繼續(xù)從我們的例子中,我們首先需要的是使一個HTML表單編輯聯(lián)系。表單可以被看作是對資源的不同的觀點。Konstrukt的子視圖的概念,以滿足。出“實體”組件中添加以下內(nèi)容:
<?php class components_contacts_Entity extends k_Component {function renderHtmlEdit() {$this->document->setTitle("Edit " . $this->contact->full_name());$t = new k_Template("templates/contacts-entity-edit.tpl.php");return new k_HtmlResponse($t->render($this, array('contact' => $this->contact)));}...的模板,在
?templates/contacts-entity-edit.tpl.php:
<h2>Edit <?php e($contact->short_name()); ?></h2> <form method="post" action="<?php e(url('', array('edit'))); ?>"> <?php if (isset($contact->errors)): ?> <?php foreach ($contact->errors as $error): ?><p style="color:red"><?php e($error); ?></p> <?php endforeach; ?> <?php endif; ?><p><label>First Name<input type="text" name="first_name" value="<?php e($contact->first_name()); ?>" /></label></p><p><label>Last Name<input type="text" name="last_name" value="<?php e($contact->last_name()); ?>" /></label></p><p><label>Email<input type="text" name="email" value="<?php e($contact->email()); ?>" /></label></p><p><input type="submit" /></p> </form>這顯然是一個原始的方式來呈現(xiàn)表單組件。HTML小部件的Konstrukt的范圍之外,但您可以使用第三方庫,如Zend_Form的生成html。如果您使用的是真正的模板引擎,它也提供了一個手段。
要訪問的形式,我們需要從頁面中添加一個鏈接,這樣編輯
templates/contacts-entity.tpl.php:
<h2><?php e($contact->short_name()); ?></h2> <dl><dt>First Name</dt><dd><?php e($contact->first_name()); ?></dd><dt>Last Name</dt><dd><?php e($contact->last_name()); ?></dd><dt>Email</dt><dd><?php e($contact->email()); ?></dd> </dl> <p><a href="<?php e(url('', array('edit'))); ?>">edit</a> </p>現(xiàn)在,您可以通過點擊網(wǎng)址聯(lián)系人/賈巴達到嗎?編輯。在內(nèi)部,Konstrukt的將其轉(zhuǎn)換為renderHtmlEdit,并派遣到該方法。
現(xiàn)在,我們有到位的形式呈現(xiàn),我們?nèi)匀恍枰幚鞵OST請求,它會產(chǎn)生。時間添加一些更多的方法,我們的組件:
<?php class components_contacts_Entity extends k_Component {function postForm() {if ($this->process()) {return new k_SeeOther($this->url());}return $this->render();}function process() {global $contacts;$this->contact = new Contact(array('short_name' => $this->contact->short_name(),'first_name' => $this->body("first_name"),'last_name' => $this->body("last_name"),'email' => $this->body("email")));if (!$this->contact->first_name()) {@$this->contact->errors[] = "Missing first_name";}if (!$this->contact->last_name()) {@$this->contact->errors[] = "Missing last_name";}if (!$this->contact->email()) {@$this->contact->errors[] = "Missing email";}if (!isset($this->contact->errors)) {try {$contacts->save($this->contact);} catch (Exception $ex) {@$this->contact->errors[] = $ex->getMessage();return false;}return true;}return false;}...由于本教程的模型層,在實施的過程中()是保持簡單。您可以測試失敗的情況下,通過省略的領(lǐng)域之一。否則,實體保存到數(shù)據(jù)庫中。
postForm()方法-而短暫的-值得幾句話的方式。如果處理順利的話,我們產(chǎn)生一個重定向。在這種情況下,它的電流分量的URL。這將需要用戶返回一個成功的手術(shù)后默認的表示。如果有失敗的,形式的,而不是重新顯示。需要注意的是,我們必須顯式調(diào)用render()方法結(jié)束時。沒有它,我們會得到一個空白頁。
這種模式通常被稱為“重定向”或“后后后Redirect-GET“(PRG)?。具體的方式做的事情,這意味著用戶瀏覽器的歷史記錄不會存儲POST操作的形式,一旦已經(jīng)完成。如果我們不這樣做,使用的瀏覽器中的“后退”按鈕,將嘗試重新提交表單。你可能已經(jīng)經(jīng)歷過這種令人討厭的行為,在網(wǎng)站上不止一次。請注意,這是已被成功處理后,方可形式的重定向發(fā)生。
posted on 2013-04-03 23:38 CW.Liu 閱讀(...) 評論(...) 編輯 收藏轉(zhuǎn)載于:https://www.cnblogs.com/cheman/archive/2013/04/03/2998925.html
總結(jié)
以上是生活随笔為你收集整理的Konstrukt PHP REST框架 教程二的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Firefox扩展开发 Hello Wo
- 下一篇: 【xinfanqie】五方面快速解决Wi