入门-第2部分

回复 星标
更多

Konstrukt学习
«入门-第2部分»

在本教程中,我们认为你已经完成了第一个教程,它是建立在第一部分的。

协议内容类型»

大多数时候,Web应用程序将写出HTML这是由网络组织的虽然在一段时间后,我们可能会产生其他类型的反应。在这种情况下,我们显然不希望得到的输出里提示的是常规的文档。为此,我们需要一种不同的结果。我们已经看到了一个异常结果,通过k_PageNotFound,我们需要一个更具体的种类。我们将扩展呈现组件的输出结果。

提供一个为不同类型资源内容,我们可以使用Konstrukts内建的协议支持内容的谈判,HTTP的功能往往没有得到充分利用。为了得到这个,我们需要编辑实体部分,从而使GET请求可以分为HTML或vcard的处理程序。我们可以使用手动的get()方法,但可以用有通用的钩选达到这个目的。经过修改后的组件最终是

<?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());

$tnew 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();

}

$tnew 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;

}

}

正如你可以看到,我们现在有两种渲染方式,而不是单一get()方法。默认的GET()方法将利用内容协议类型使用这些映射到一个或另一个。有缺省映射到该站渲染器的名,就是你能找到的文件。

vCard渲染中,我们要创建一个不正常的响应。如上所述,这种绕过正常的渲染流水线,使我们的细粒级控制精确的HTTP响应发送出去。

当然,我们需要用到模板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

现在我们的组件可以呈现两种不同的内容类型,根据客户的要求。要看到这个动作,你可以使用命令行工具卷曲转到命令行,然后键入:

curl --dump-header - --header "Accept: text/html" http://localhost/foo/www/contacts/jabba

您将获得一个响应的HTTP转储,如text / html现在,尝试着请求text/x-vcard

curl --dump-header - --header "Accept:text/x-vcard" http://localhost/foo/www/contacts/jabba

正如你所看到的,同样的组件根据客户端的喜好返回了不同的表示。这是根据HTTP协议和一些客户端有能力处理的,但常见的客户端浏览器通常都不会。正因为如此,还有另外一种方式。你可以在内容内心的后面指定类型,用点隔开(实际上,你应该用简短的名字,而不是完整的mimetype名字)。这时,你可以浏览http://localhost/foo/www/contacts/jabba.vcard如果你有请求相应的页面标题,它将产生同样的结果,且你的请求中的包含Accept头部,并指定它为text/ x- vCard的页面。试一试:

curl --dump-header -http://localhost/foo/www/contacts/jabba.vcard

请注意,当指定一个简短的名称时,Konstrukt忽略了Accept头,简称优先。因此,下面还给出了一个vacrd:

curl --dump-header - --header "Accept: text/html" http://localhost/foo/www/contacts/jabba.vcard

整理了一下代码»

正如您可能已经注意到上面有一些职能重叠两者之间呈现。我们可以减少元件一般处理这个运动的一部分,成为一个更它。在这种情况下,顶层(派遣()将适用于:

<?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());

$tnew k_Template("templates/contacts-entity.tpl.php");

return $t->render($this,array('contact'=>$this->contact));

}

function renderVcard(){

$tnew 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强大的特性,被称为包装

这可能也作为使用Konstrukt强大的功能,被称为封装添加下面代码片段/var/www/foo/lib/components/contacts/list.php:

<?php

class components_contacts_List extends k_Component{

...

function wrapHtml($content){

return'

<p><ahref="'.htmlspecialchars($this->url()).'">Listcontacts</a></p>

<divid="content">

'.$content.'

</div>';

}

...

}

这需要做的就是,每当子组件(:components_contacts_Entity)呈现时,响应将被渲染。这只适用于HTML响应,所以我们的vcard响应不会被响应。这提供了一个便捷的方式划分导航和类似的HTML片断,涉及到的位置,相关网址(url)中的主机名称的层次结构。

我们现在已经介绍了一些调度的过程的相关概念。要了解它们要如何在一起,什么是library中真正发生的,我们将不得不返回到上一步:

Intermezzo-组件的结构»

你可以跳过这部分,如果你的脑袋太满

214822

上图描述的过程是一个组件的执行过程。

一个组件先从dispatch()方法开始处理。它判断是否存在更多的分支还是最后的流程中的最后一个节点,在嵌套的路径中,每一部分都将进入dispatch()方法,然后再到下一级,直到最后一段路径到达。

如果存在下一个组件,dispatch()将使用首先会让map()将路径段翻译成一个组件类的名字。然后调用forward()将组件实例化并开始进入到下一个组件的过程。

流程中的最后一个组件调的是自己的execute()方法,而不是forward()。这将进一步使用一个方法与HTTP相适应的方法,通常GET()。最后,GET()方法调用render(),在所请求的内容基础和适用的子视图上,将试图找到在一个合适的渲染方法迅速要求(取决于Accept头部或者URL前缀)

forward()方法调度另外一个组件时,它将接收到到k_Response对象。这是发送的wrap()method.方法。wrap()会检查是否有任何的封装与内容类型相匹配。如果是这样的话,它将通过这个通道允许渲染的响应。封装对渲染非常有用就像导航。你可以看看根元件(位于/var/www/foo/lib/components/root.php),你将见到它有一个方法wrapHtmlEach time a sub component returns a HTML response,this method is used to decorate it.每次子部件返回一个HTML响应,都会用这个方法渲染。因为wrap()只是调用前端,execute()方法则是进一步渲染了结果。因此,根封装就是HTML的响应。

所有这些方法可能看起来有点多,这可能是Konstrukt最复杂的部分。你并不需要了解的细微差异,就能够使用Konstrukt,但如果你想获得所有的知识,那么字典中都会有。有这么多的调度方法,要选择什么方法,这取决于你。所以,这是非常罕见的所有组件同时使用所有这些功能。对于初学者来说,render()map()如何工作是最重要的。

Posting和表单»

大多数的网络应用程序都需要用户从html-forms输入的信息。有一个组件能够处理任何HTTP方法,包括POST,与表单关系密切。你可以在该组件上实现POST()方法,You can implement the你可以实现POST(),处理所有的POST请求,但你不能直接实施GET()一样不能直接处理POST(),而是依靠渲染的方法。Instead, you can implement相反,你可以按照规范的application/x-www方式的postForm()来接受url类型的请求。(默认编码类型的HTML表单),或有为多种表单提供的postMultipart()(通常用于文件上传)。如果你想支持其他的输入格式,应用同样的规则postXml()为提交文章的输入Content-Type头为text/xmlPUT类型按照同样的规则。

通常一个表单域- -请求的加载可通过body()方法。这相当于PHP的本地超全局变量$ _POST,就像query()对应$_GET。这种命名是比较正确的,因为querystring是适用于所有的请求,不仅仅是GET和有效载荷其他的类型,如PUT请求。

继续我们运行的例子,我们首先需要提供一个用于编辑联系人HTML表单,继续从我校的办学的例子,我们首先需要的是将html表单进行编辑一个联络人。A form can be seen as an alternate view over theresource.一个表单可以被看作是一种能看到的资源。Konstrukt具有分层的概念,满足这一点。将以下内容添加到了'entity'的组件:

<?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 end foreach;?>

<?php end if;?>

<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>


本文下半节见:http://q.115.com/t-153332-57129.html

2015-04-28 20:31:00更新过
新窗口打开 关闭