名称

Mojolicious::辅助线::渲染-渲染内容

概述

本文档介绍了使用Mojolicious公司渲染器。

概念

Essentials每Mojolicious公司开发人员应该知道。

渲染器

渲染器是一个小黑匣子,它利用多个模板系统和数据编码模块将隐藏的数据转换为实际的响应。

{text=>“你好”}->200好的,text/html,“你好”{json=>{x=>3}}->200 OK,application/json,'{“x”:3}'{text=>“Oops.”,status=>“410”}->410 Gone,text/html,“Oops”

如果开发人员或路由提供了足够的信息,则可以自动检测模板。模板名称应跟随template.format.handler方案,具有模板默认为控制器/动作或路线名称,格式默认为html格式处理程序电动自行车.

{controller=>“users”,action=>“list”}->“users/list.html.ep”{template=>“foo”,format=>“txt”}->“foo.txt.ep”{template=>“foo”,handler=>“epl”}->“foo.html.epl”

这个控制器值转换自驼峰命名法蛇形外壳使用Mojo::Util中的“decamelize”-字符替换为/.

{controller=>“My::Users”,action=>“add”}->“My/Users/add.html.ep”{controller=>“my-users”,action=>“show”}->“my/users/show.html.ep”

所有模板都应位于模板应用程序的目录,可以使用自定义Mojolicious::Renderer中的“路径”,或数据节来自Mojolicious::Renderer中的“类”.

__数据__@@时间.html.ep%使用时间::件;%my$now=本地时间;<!DOCTYPE html><html>时间<body>时间是<%=$now->hms%></车身></html>@@问候语.txt.ep。。。

渲染器可以很容易地进行扩展,以支持带有插件的其他模板系统,但稍后会详细介绍。

嵌入式Perl

Mojolicious公司包括一个简约但功能强大的现成模板系统,名为Embedded Perl或电动自行车简而言之。它基于Mojo::模板并允许使用一组特殊标记和行首字符将Perl代码直接嵌入到实际内容中。对于所有模板严格的,警告,utf8接口和Perl 5.16特征将自动启用。

<%Perl代码%><%=Perl表达式,替换为XML转义结果%><%==Perl表达式,替换为结果%><%#注释,用于调试%><%%替换为“<%”,用于生成模板%>%Perl代码行,被视为“<%line=%>”(稍后解释)%=Perl表达式行,被视为“<%=line%>”%==Perl表达式行,被视为“<%==line%>”%#注释行,用于调试%%替换为“%”,用于生成模板

标签和行的工作原理基本相同,但根据上下文的不同,标签和行通常会看起来更好一些。分号会自动附加到所有表达式中。

<%my$i=10;%><ul><%表示我的$j(1..$i){%><li><%=$j%></li><% } %></ul>%我的$i=10;<ul>%对于我的$j(1..$i){<li>%=$j</li>% }</ul>

除了空白处理方面的差异外,这两个示例都生成类似的Perl代码,简单的翻译可能是这样的。

my$output=“”;我的$i=10;$output=‘<ul>';对于我的$j(1..$i){$output.='<li>';$输出。=xml_escape标量+$j;$output=‘</li>';}$output.='</ul>';返回$output;

可以使用另一个等号来禁用字符转义<,>,&,'"Perl表达式的结果,这是防止对应用程序进行XSS攻击的默认设置。

<%='我莫名其妙!“%><%=='<p>I莫名其妙</p> “%>

仅限Mojo::ByteStream对象被排除在自动转义之外。

<%=b('<p>I莫名其妙</p> ')%>

通过在标记末尾添加额外的等号,可以修剪标记周围的空白字符。

<%(1..3){%><%='删除此表达式周围的所有空白字符'=%><% } %>

换行符可以用反斜杠转义。

这是<%=1+1%>\单线

换行符前面的反斜杠可以用另一个反斜杠转义。

这将<%=1+1%>结果\\以倍数\\线

除非最后一个字符是反斜杠,否则每个模板都会自动附加一个换行字符。并且忽略模板末尾的空行。

此处末尾没有换行符\

在模板的开头,名称中没有无效字符的stash值将自动初始化为普通变量,控制器对象将同时初始化为这两个变量$self(美元)$c美元.

$c->stash(名称=>“tester”);来自<%=$c->tx->remote_address%>的您好。

像这样的前缀我的应用程序*通常用于不希望在模板中公开的隐藏值。

$c->stash('myapp.name'=>'tester');

还有许多帮助器函数可用,但稍后会详细介绍。

<%=转储器{foo=>“bar”}%>

基础

最常用的功能Mojolicious公司开发人员应该知道。

自动渲染

可以通过调用方法手动启动渲染器Mojolicious::Controller中的“render”,但这通常是不必要的,因为如果路由器完成工作后没有呈现任何内容,则会自动调用它。这也意味着您可以让路由只指向模板,而无需实际操作。

$c->渲染;

但有一个很大的区别,通过手动调用它,可以确保模板使用当前控制器对象,而不是使用属性指定的默认控制器Mojolicious中的“controller_class”.

$c->render_later;

还可以使用该方法禁用自动渲染Mojolicious::Controller中的“render_later”,这对于在必须首先执行非阻塞操作时延迟渲染非常有用。

渲染模板

渲染器将始终尝试检测正确的模板,但您也可以使用模板隐藏值以呈现特定值。最后一个斜杠之前的所有内容都将被解释为要在其中查找模板的子目录路径。

#foo/bar/baz.**$c->render(模板=>“foo/bar/baz”);

选择特定的格式处理程序就这么简单。

#foo/bar/baz.txt.epl$c->render(模板=>“foo/bar/baz”,格式=>“txt”,处理程序=>“epl”);

因为渲染特定模板是最常见的任务,所以它也有一个快捷方式。

$c->render('oo/bar/baz');

如果您事先不确定模板是否确实存在,也可以使用该方法Mojolicious::Controller中的“render_maybe”尝试多种选择。

$c->render_maybe('localized/baz')或$c->lender('oo/bar/baz]);

渲染为字符串

有时,您可能希望直接使用呈现的结果,而不是生成响应,例如,要发送电子邮件,可以使用Mojolicious::Controller中的“render_to_string”.

my$html=$c->render_to_string('mail');

不会执行任何编码,这样可以方便地在其他模板中重用结果或生成二进制数据。

my$pdf=$c->render_to_string('voice',format=>'pdf');$c->render(数据=>$pdf,格式=>'pdf');

传递的所有参数将自动本地化,并且仅在此呈现操作期间可用。

模板变体

要使您的应用程序在许多不同的设备上看起来很棒,您还可以使用变体隐藏值以在模板的不同变体之间进行选择。

#foo/bar/baz.html+phone.ep#foo/bar/baz.html.ep$c->render('oo/bar/baz',variant=>'phone');

这可以非常自由地完成,因为它仅适用于具有正确名称的模板实际存在的情况,否则将返回到通用模板。

渲染内联模板

一些渲染器,例如电动自行车允许传递模板内联.

$c->render(inline=>“结果是<%=1+1%>。”);

由于自动检测依赖于路径,因此您可能必须提供处理程序也是。

$c->render(inline=>“<%=shift->param('foo')%>”,handler=>'epl');

正在呈现文本

可以使用文本stash值,给定的内容将自动编码为Mojolicious::Renderer中的“编码”.

$c->render(文本=>'I“莫名其妙!”);

渲染数据

可以使用数据stash值,则不执行编码。

$c->render(数据=>$字节);

呈现JSON

这个json语言stash值允许您将Perl数据结构传递给渲染器,渲染器使用Mojo::JSON.

$c->render(json=>{foo=>[1,'test',3]});

状态代码

可以使用更改响应状态代码地位存储值。

$c->render(文本=>“Oops.”,状态=>500);

内容类型

这个内容类型响应的标头实际上基于格式隐藏价值。

#内容类型:文本/纯文本$c->render(text=>“你好”,format=>“txt”);#内容类型:image/png$c->render(数据=>$bytes,格式=>'png');

这些映射可以很容易地扩展或更改Mojolicious中的“类型”.

#添加新的MIME类型$app->types->type(md=>'text/markdown');

Stash数据

任何本机Perl数据类型都可以通过Mojolicious::Controller中的“stash”.

$c->stash(description=>“web框架”);$c->stash(frameworks=>['Catalyst','Mojolicios','mojo.js']);$c->stash(衍生产品=>{minion=>‘作业队列’});%=$描述%=$框架->[1]%=$spinoff->{minion}

因为一切都是Perl,所以正常的控制结构就可以工作。

%对于我的$框架(@$框架){<%=$framework%>是<%=$描述%>。% }%if(我的$description=$spinoffs->{minion}){仆从是<%=$description%>。% }

对于可能以不同方式呈现的模板,以及您不确定是否会实际设置隐藏值的模板,您可以只使用helperMojolicious::Plugin::DefaultHelpers中的“stash”.

%if(我的$spinoffs=存储“spinoffs”){仆从是<%=$spinoffs->{仆从}%>。% }

助手

助手是可以在模板以及应用程序和控制器代码中使用的小函数。

#模板%=自卸车[1,2,3]#应用程序我的$serialized=$app->dumper([1,2,3]);#控制器我的$serialized=$c->dumper([1,2,3]);

我们区分默认辅助对象,它们更通用,如Mojolicious::Plugin::DefaultHelpers中的“dumper”和标记助手,如Mojolicious::Plugin::TagHelpers中的“link_to”,它们是特定于模板的,主要用于生成HTML标记。

%=link_to Mojolicious=>'https://mojolicious.org'

在控制器中,您也可以使用该方法Mojolicous::控制器中的“助手”以完全限定helper调用并确保它们不会与现有方法冲突。

我的$serialized=$c->helpers->dumper([1,2,3]);

可以在中找到所有内置辅助对象的列表Mojolicious::Plugin::DefaultHelpersMojolicious::插件::TagHelpers.

静态文件

静态文件自动从公众的应用程序的目录,可以使用Mojolicious::Static中的“路径”,或其中一个数据节来自Mojolicious::Static中的“类”。如果这还不够,您还可以手动为其提供服务Mojolicious::Plugin::DefaultHelpers中的“reply->static”Mojolicus中的“回复->文件”::插件::DefaultHelpers.

使用Mojolicious::Lite签名;获取“/”=>子($c){$c->reply->static('index.html’);};获取“/some_download”=>sub($c){$c->res->headers->content_disposition('attachment;filename=bar.png;');$c->reply->static('foo/bar.png');};获取'/leak'=>sub($c){$c->reply->file('/etc/passwd');};应用程序->启动;

默认情况下,静态文件不使用前缀,只提供比路由更高的优先级。这可以通过以下方式进行更改Mojolicious::Static中的“前缀”.

#仅为带有“/static”前缀的静态文件提供服务$app->static->prefix('/static');

要允许动态配置前缀,可以使用Mojolicious::Controller中的“url_for_file”用它生成URL。许多标记帮助程序也会在有意义时自动使用前缀。

静态资产

虽然Mojolicious对前端框架没有任何特殊支持,比如Vue.js公司反应,的公共/资产目录是为捆绑程序创建的静态资产保留的,如网络包Rollup.js(滚动.js)提前。资产文件可以是任何类型,它们只需遵循[姓名]。[校验和]。[扩展]命名方案,如myapp.ab1234cd5678参考.js。然后您可以使用Mojolicus::控制器中的“url_for_asset”Mojolicious::Plugin::TagHelpers中的“asset_tag”生成URL而无需知道校验和。

#“/assets/myapp.ab1234cd5678ef.js”$c->url_for_asset('/myapp.js');#“<script src=”/assets/myapp.ab1234cd5678ef.js“></script>”$c->asset_tag('/myapp.js');

如果您的应用程序在中运行发展模式下,所有资产都将使用Cache-Control:无缓存头,通过防止浏览器缓存来加速开发。此外,以下所有资产[名称].开发。[扩展]命名方案,如我的应用程序开发.js的优先级高于具有校验和的资产。这样,您就可以在开发过程中覆盖资产,而不必在每次使用不同的校验和重建资产时手动删除它们。

#“/assets/foo/bar.development.js”$c->url_for_asset('/foo/bar.js');

网络包配置示例(webpack.config.js):

从“@mojojs/Path”导入路径;const isDev=进程env。MOJO_MODE===“开发”;导出默认值{输出:{文件名:isDev?'[name].development.js':'[name]。[chunkhash].js',path:path.currentFile().sibling('public','assets').toString(),公共路径:“”},//在此处添加您自己的规则和入口点};

汇总配置示例(滚动配置.js):

从“@mojojs/Path”导入路径;const isDev=进程env。MOJO_MODE===“开发”;导出默认值{输出:{entryFileNames:isDev?'[名称].开发。[ext]“:”[name]。[散列]。[ext]',dir:Path.currentFile().s兄弟姐妹('public','assets').toString(),格式:'life'},//在此处添加您自己的规则和入口点};

其他一切都取决于您选择的捆绑包,因此您需要查阅其文档以获取更多信息。以及您的资产来源,例如.vue(真空).jsx文件文件,并不重要,只要你的bundler能找到它们。使用名为资产前端但是,在应用程序中,根目录是一个很好的最佳实践。

内容协商

对于具有不同表示形式且需要真正RESTful内容协商的资源,您还可以使用Mojolicious::Plugin::DefaultHelpers中的“respond_to”而不是Mojolicious::Controller中的“render”.

#/hello(接受:application/json)->“json”#/hello(接受:application/xml)->“xml”#/hello.json->“json”#/hello.xml->“xml”#/你好_format=json->“json”#/你好_format=xml->“xml”$c->响应(json=>{json=>{hello=>“世界”}},xml=>{text=>'<hello>world</hello>'});

将自动从_格式 GET(获取)/邮政参数,格式存储值或接受请求标头并存储在格式存储值。更改的MIME类型映射接受请求标头或内容类型可以使用的响应标头Mojolicious中的“类型”.

$c->响应(json=>{json=>{hello=>“世界”}},html=>子{$c->content_for(head=>'<meta name=“author”content=“sri”>');$c->render(模板=>“hello”,消息=>“world”)});

回调可用于过于复杂的表示,无法放入单个渲染调用中。

#/hello(接受:application/json)->“json”#/hello(接受:text/html)->“html”#/hello(接受:image/png)->“任意”#/hello.json->“json”#/hello.html->“html”#/hello.png->“任何”#/你好_format=json->“json”#/你好_format=html->“html”#/你好_format=png->“任意”$c->响应(json=>{json=>{hello=>“世界”}},html=>{template=>“你好”,message=>“世界”},any=>{text=>“”,状态=>204});

如果找不到可行的代表任何将使用回退或为空204自动呈现的响应。

#/hello->“html”#/hello(接受:text/html)->“html”#/hello(接受:text/xml)->“xml”#/hello(接受:text/plain)->undef#/hello.html->“html”#/hello.xml->“xml”#/hello.txt->取消定义#/你好_format=html->“html”#/你好_format=xml->“xml”#/你好_格式=txt->undefif(my$format=$c->accepts('html,'xml')){。。。}

对于更高级的协商逻辑,您还可以使用helperMojolicious::Plugin::DefaultHelpers中的“接受”.

呈现异常和找不到页面(_F)

现在您可能已经遇到了内置404(未找到)和500(服务器错误)页面,当您出错时会自动呈现。当您自己的异常处理失败时,这些都是备用方法,这在开发期间尤其有用。您还可以使用助手手动渲染它们Mojolicious::Plugin::DefaultHelpers中的“reply->exception”Mojolicious::Plugin::DefaultHelpers中的“reply->not_found”.

使用Mojolicious::Lite签名;使用标量::Util qw(looks_like_number);get“/divid/:divider/by/:divisor”=>sub($c){我的$divide=$c->param('dividend');my$divisor=$c->param('divisor');# 404返回$c->reply->not_found,除非looks_like_number$被除数&&looks_like_number$divisor;# 500如果$divisor==0,则返回$c->reply->exception('Division by zero!');# 200$c->render(text=>$divider/$divisor);};应用程序->启动;

要更改异常的HTTP状态代码,可以使用Mojolicious::Controller中的“呈现”.

return$c->reply->exception('Division by zero!')->rendered(400)if$divisior==0;

您还可以更改这些页面的模板,因为您很可能希望向用户显示与生产中的应用程序更密切相关的内容。渲染器将始终尝试查找例外$模式$格式*未找到$模式$格式*在回到内置默认模板之前。

使用Mojolicious::Lite;get'/dies'=>sub{die'故意错误'};应用程序->启动;__数据__@@例外.production.html.ep<!DOCTYPE html><html><head><title>服务器错误</title></head><body><h1>例外</h1><p><%=$异常->消息%></p><h1>斯塔什</h1><pre><%=转储程序$snapshot%></pre></body></html>

默认的异常格式为html格式,但这可以在应用程序和控制器级别进行更改。默认情况下,有以下处理程序html格式,文本json语言可用。中还有各种异常帮助器Mojolicious::Plugin::DefaultHelpers让您重载以更改默认行为。

使用Mojolicious::Lite签名;app->exception_format('json');获取“/json”=>sub($c){死“只是一个测试”;};获取'/txt'=>sub($c){$c->exception_format('text');死“只是一个测试”;};应用程序->启动;

钩子Mojolicious中的“before_render”通过允许截取和修改传递给渲染器的参数,可以进行更高级的自定义。

使用Mojolicious::Lite签名;钩子before_render=>sub($c,$args){#确保我们正在呈现异常模板返回,除非我的$template=$args->{template};除非$template eq为“exception”,否则返回;#如果内容协商允许,则切换到JSON呈现除非$c->接受('json'),否则返回;$args->{json}={exception=>$c->stash(“exception”)};};get'/'=>sub{die“这本书……所有荣誉归于HYPNOTOAD!\n”};应用程序->启动;

布局

大多数时候使用电动自行车模板,您需要将生成的内容包装在一个HTML框架中,这要归功于布局,这绝对是微不足道的。

使用Mojolicious::Lite;获取'/'=>{template=>'foo/bar'};应用程序->启动;__数据__@@foo/bar.html.ep%布局“mylayout”;你好,世界!@@布局/mylayout.html.ep<!DOCTYPE html><html><head><title>MyApp</title></head><body><%=内容%></body></html>

您只需使用辅助对象选择正确的布局模板Mojolicious::Plugin::DefaultHelpers中的“布局”并使用助手放置当前模板的结果Mojolicious::Plugin::DefaultHelpers中的“内容”。您还可以将正常存储值传递给布局帮手。

使用Mojolicious::Lite;获取'/'=>{template=>'foo/bar'};应用程序->启动;__数据__@@foo/bar.html.ep%layout'mylayout',title=>“你好”;你好,世界!@@布局/mylayout.html.ep<!DOCTYPE html><html><head><title><%=$title%></title></head><body><%=内容%></body></html>

而不是布局您也可以使用布局隐藏值或调用Mojolicious::Controller中的“render”使用布局参数。

$c->render(template=>“mytemplate”,layout=>“mylayout”);

要设置布局可在应用程序范围内使用的存储值Mojolicious中的“默认值”.

$app->defaults(布局=>'mylayout');

布局也可以与Mojolicious::Controller中的“render_to_string”,但是布局值需要作为呈现参数传递(而不是存储值)。

my$html=$c->render_toString('reminder',layout=>'mail');

部分模板

您可以将较大的模板分解为更小、更易于管理的块。这些部分模板也可以与其他模板共享。使用助手即可Mojolicious::Plugin::DefaultHelpers中的“include”将一个模板包含到另一个模板中。

使用Mojolicious::Lite;获取'/'=>{template=>'foo/bar'};应用程序->启动;__数据__@@foo/bar.html.ep<!DOCTYPE html><html>%=包括“_header”,title=>“你好”<body>酒吧</body></html>@@_header.html.ep(_header.html)<head><title><%=$title%></title></head>

您可以随意命名部分模板,但前导下划线是常用的命名约定。

可重复使用的模板块

重复自己从来都不是件有趣的事,这就是为什么您可以在电动自行车它的工作方式与普通Perl函数非常相似开始结束关键字。请注意,这两个关键字都是周围标记的一部分,而不是实际的Perl代码,因此后面只能有空格开始和之前结束.

使用Mojolicious::Lite;get“/”=>“欢迎”;应用程序->启动;__数据__@@欢迎访问.html.ep<%my$block=begin%>%my$name=轮班;您好<%=$name%>。<%end%><%=$块->(“Wolfgang”)%><%=$块->(“Baerbel”)%>

模板到Perl代码的简单转换可能如下所示。

my$output=“”;my$block=子($name){my$output=“”;$output.='你好';$输出。=xml_escape标量+$name;$output.=“.”;return Mojo::ByteStream->new($output);};$输出。=xml_escape标量+$block->('Wolfgang');$输出。=xml_escape标量+$块->('Baerbel');返回$output;

虽然模板块不能在模板之间共享,但它们最常用于将模板的部分传递给帮助器。

添加助手

您应该始终尝试保持操作的小型化,并尽可能重用代码。帮助程序使这一点变得非常简单,它们将当前控制器对象作为第一个参数传递,您可以使用它们来完成一个操作可以完成的几乎所有操作。

使用Mojolicious::Lite签名;helper-debug=>sub($c,$str){$c->app->log->debug($str);};获取“/”=>子($c){$c->debug('你好,来自一个操作!');}=>“索引”;应用程序->启动;__数据__@@索引.html.ep%调试“Hello from a template!”;

助手还可以接受模板块作为最后一个参数,例如,这允许非常愉快地使用标记助手和过滤器。将辅助对象结果包装为Mojo::ByteStream对象可以防止意外的双重逃逸。

使用Mojolicious::Lite签名;使用Mojo::字节流;helper trim_newline=>sub($c,$block){我的$result=$block->();$result=~s/\n//g;return Mojo::ByteStream->new($result);};获取“/”=>“索引”;应用程序->启动;__数据__@@索引.html.ep%=trim_newline开始一些文本。%=1+1更多文本。%结束

与stash值类似,可以使用如下前缀我的应用程序*防止助手在模板中作为函数公开,并在应用程序增长时将其组织到命名空间中。每个前缀都会自动成为一个助手,该助手返回包含当前控制器对象的代理对象,您可以在其中调用嵌套的助手。

使用Mojolicious::Lite签名;helper'cache_control.no_cacheng'=>sub($c){$c->res->headers->cache_conrol('私有,最大age=0,no-cache')};helper'cache_control.five_minutes'=>sub($c){$c->res->headers->cache_conrol('public,max-age=300')};获取'/news'=>sub($c){$c->cache_control->no_cacheng;$c->render(text=>“总是最新”);};获取'/some_older_story'=>sub($c){$c->cache_control->5分钟;$c->render(text=>“这个可以缓存一点。”);};应用程序->启动;

虽然也可以重新定义助手,但这只能非常小心地避免冲突。

内容块

助手Mojolicious::Plugin::DefaultHelpers中的“content_for”允许您将整个内容块从一个模板传递到另一个模板。当您的布局有不同的部分(例如侧栏)时,这非常有用,其中内容应该由模板插入。

使用Mojolicious::Lite;获取“/”=>“foo”;应用程序->启动;__数据__@@foo.html.ep%布局“mylayout”;%content_for-header=>开始<meta http-equiv=“Content-Type”Content=“text/html”>%结束你好,世界</分区>%content_for-header=>开始<meta http-equiv=“Pragma”content=“no-cache”>%结束@@布局/mylayout.html.ep<!DOCTYPE html><html><head><%=内容“header”%></head><body><%=内容%></body></html>

形式

为了更有效地构建HTML表单,您可以使用以下标记助手Mojolicious::Plugin::TagHelpers中的“form_for”,如果提供了路由名称,它可以自动为您选择请求方法。由于大多数浏览器只允许提交表单GET(获取)邮政,但不请求类似的方法PUT(输出)删除,他们被一个_方法查询参数。

使用Mojolicious::Lite签名;获取'/'=>'form';#输出/无#发布/无_方法=PUTput“/nothing”=>sub($c){#防止使用重定向提交双表单my$value=$c->param(“whatever”);$c->flash(确认=>“我们没有使用您的价值($value)。”);$c->redirect_to('form');};应用程序->启动;__数据__@@表单.html.ep<!DOCTYPE html><html><body>%if(我的$confirmation=flash“确认”){<p><%=$确认%></p>% }%=form_fornothing=>开始%=text_field whatever=>“我莫名其妙!”%=提交按钮%结束</body></html>

帮手们Mojolicious::Plugin::DefaultHelpers中的“flash”Mojolicious::Plugin::DefaultHelpers中的“redirect_to”通常一起使用,以防止双重表单提交,使用户可以收到确认消息,如果他们决定重新加载重定向到的页面,该消息将消失。

表单验证

你可以使用Mojolicious::Plugin::DefaultHelpers中的“验证”以验证GET(获取)邮政提交给应用程序的参数。默认情况下,将忽略所有未知字段,因此您必须决定应该忽略哪个字段必修的可选择的然后才能对其值进行检查。每个检查都会立即执行,因此您可以立即使用结果来构建更高级的验证逻辑,方法如下Mojolicious::Validator::valid中的“is_valid”.

使用Mojolicious::Lite签名;获取“/”=>子($c){#检查参数是否已提交我的$v=$c->验证;返回$c->render('index'),除非$v->has_data;#验证参数(“pass_again”取决于“pass”)$v->必需(“用户”)->大小(1,20)->类似(qr/^[a-z0-9]+$/);$v->required('pass_again')->equal_to('pass’),如果$v->optional('passs')->size(7500)->is_valid;#检查验证是否失败如果$v->has_error,则返回$c->render('index');#渲染确认$c->render(“储罐”);};应用程序->启动;__数据__@@索引.html.ep<!DOCTYPE html><html><头部><样式>标签.field-with-error{color:#dd7e5e}input.field-with-error{背景颜色:#fd9e7e}</style></头><body>%=form_for-index=>开始%=label_for user=>'用户名(必需,1-20个字符,a-z/0-9)'<br>%=text_field“用户”,id=>“用户”%=提交按钮<br>%=label_for-pass=>“密码(可选,7-500个字符)”<br>%=password_field'pass',id=>'pass]<br>%=label_for-pass_again=>'再次输入密码(等于上面的值)'<br>%=密码字段“pass_again”,id=>“pass_again”%结束</body></html>@@谢谢。html.ep<!DOCTYPE html><html><body>感谢您<%=validation->param('user')%></车身></html>

使用标记帮助器生成的表单元素Mojolicious::插件::TagHelpers将自动记住以前的值并添加类现场无误用于验证失败的字段,以简化CSS样式。

<label class=“field-with-error”for=“user”>用户名(必需,仅包含字符e-t)</label><input class=“field-with-error”type=“text”name=“user”value=“sri”>

有关可用检查的完整列表,请参见Mojolicious::Validator中的“CHECKS”.

添加表单验证检查

验证检查可以注册到Mojolicious::Validator中的“add_check”如果成功,则返回错误值。可以使用真值传递附加信息,然后可以使用Mojolicious::Validator::Valid中的“error”.

使用Mojolicious::Lite签名;#添加“范围”检查app->validator->add_check(范围=>sub($v,$name,$value,$min,$max){返回$value<$min||$value>$max;});获取'/'=>'form';后“/test”=>子($c){#使用自定义检查验证参数我的$v=$c->验证;$v->必需(“数字”)->范围(3,23);#如果验证失败,则再次呈现表单如果$v->has_error,则返回$c->render('form');#防止使用重定向提交双表单$c->flash(数字=>$v->param(“数字”));$c->redirect_to('form');};应用程序->启动;__数据__@@表单.html.ep<!DOCTYPE html><html><body>%if(my$number=flash“数字”){<p>谢谢,号码<%=$number%>有效</p>(第页)% }%=form_for-test=>开始%if(my$err=验证->错误('number')){<p>%='值是必需的。'如果$err->[0]eq“必需”%=“值需要介于3和23之间。”如果$err->[0]eq“范围”</p>% }%=text_field“数字”%=提交按钮%结束</body></html>

跨站请求伪造

CSRF是一种非常常见的针对web应用程序的攻击,它诱骗您的登录用户提交他们不想发送的表单,而这些表单只是一个普通的链接。为了保护用户不受此影响,您只需在表单中添加一个额外的隐藏字段Mojolicious::Plugin::TagHelpers中的“csrf_field”,并使用进行验证Mojolicious::Validator::Valid中的“csrf_protect”.

使用Mojolicious::Lite签名;获取“/”=>{template=>“target”};帖子“/”=>子($c){#检查CSRF令牌我的$v=$c->验证;如果$v->CSRF_protect->has_error('CSRF_token'),则返回$c->render(text=>'Bad CSRF token!',status=>403);我的$city=$v->必需('city')->参数('city');$c->render(text=>“低轨道离子加农炮指向$city!”),除非$v->has_error;}=>“目标”;应用程序->启动;__数据__@@目标.html.ep<!DOCTYPE html><html><body>%=form_for-target=>开始%=csrf_field%=label_for-city=>“低轨道离子炮指向哪个城市?”%=text_field“城市”,id=>“城市”%=提交按钮%=结束</body></html>

对于Ajax请求等,还可以使用helper直接生成令牌Mojolicious::Plugin::DefaultHelpers中的“csrf_token”,然后将其与X-CSRF-标记请求标头。

高级

不太常用,功能更强大。

模板继承

继承将上述布局概念进一步深化,即helpersMojolicious::Plugin::DefaultHelpers中的“内容”Mojolicious::Plugin::DefaultHelpers中的“extends”允许您使用子模板可以覆盖的命名块构建骨架模板。

使用Mojolicious::Lite;#第一次>我的布局获取'/first'=>{template=>'first',layout=>'mylayout'};#第三个>第二个>第一个>我的布局获取'/tird'=>{template=>'third',layout=>'mylayout'};应用程序->启动;__数据__@@布局/mylayout.html.ep<!DOCTYPE html><html><head><title>你好</title><body><%=内容%></body></html>@@first.html.ep%=内容标题=>开始默认标题%结束你好,世界</div(分频)>%=内容页脚=>开始默认页脚%结束@@second.html.ep(秒)%扩展“first”;%content header=>开始新建页眉%结束@@third.html.ep(第三版)%扩展“second”;%content-footer=>开始新建页脚%结束

这个链可以继续下去,以允许非常高级别的模板重用。

自定义响应

大多数响应内容(静态和动态)通过Mojo::Asset::文件Mojo::Asset::Memory(内存)物体。对于一些静态内容,如缓存的JSON数据或临时文件,您可以创建自己的并使用helperMojolicious::Plugin::DefaultHelpers中的“reply->asset”为他们提供服务,同时允许与执行内容协商范围,If-修改自If-无匹配标题。

使用Mojolicious::Lite签名;使用Mojo::Asset::File;获取'/leak'=>sub($c){$c->res->headers->content_type('text/plain');$c->reply->asset(Mojo::asset::File->new(path=>'/etc/passwd'));};应用程序->启动;

为了获得更多的控制,您也可以跳过辅助对象并使用Mojolicious::Controller中的“呈现”告诉渲染器何时生成响应。

使用Mojolicious::Lite签名;使用Mojo::Asset::File;获取'/leak'=>sub($c){$c->res->headers->content_type('text/plain');$c->res->content->asset(Mojo::asset::File->new(path=>'/etc/passwd'));$c->渲染(200);};应用程序->启动;

助手插件

一些帮助程序可能足够有用,您可以在多个应用程序之间共享它们,插件使其变得非常简单。

软件包Mojolicious::Plugin::DebugHelper;使用Mojo::Base“Mojolicious::Plugin”,-signatures;子寄存器($self、$app、$conf){$app->helper(调试=>sub($c,$str){$c->app->log->debug($str);});}1;

这个登记方法将在加载插件时调用。要将助手添加到应用程序中,可以使用Mojolicious中的“助手”.

使用Mojolicious::Lite签名;插件“DebugHelper”;获取“/”=>子($c){$c->debug(“它有效!”);$c->render(text=>“你好!”);};应用程序->启动;

可以自动生成完全兼容CPAN的插件分发的框架。

$mojo生成插件DebugHelper

如果你有一个暂停账户(可在http://pause.perl.org),只需几个命令即可将其释放到CPAN。

$perl生成文件。损益$make测试$make清单$make发行$mojo cpanify-u USER-p传递Mojolicious-Plugin-DebugHelper-0.01.tar.gz

将资产与插件捆绑在一起

模板和静态文件等资产可以很容易地与插件捆绑在一起,即使您计划将它们发布到CPAN。

$mojo生成插件AlertAssets$mkdir Mojolicious-Plugin-AlertAssets/lib/Mojolicios/Plugin/AlertAsset$cd Mojolicious-Plugin-AlertAssets/lib/Mojolicios/Plugin/AlertAsset$mkdir公共$echo'警报(“Hello World!”);'>公共/警报资产.js$mkdir模板$echo“%=javascript”/alertassets.js“'>模板/alertassets.html.ep

只需给它们合理的唯一名称,最好是基于插件的名称,并在以下情况下将它们各自的目录附加到搜索路径列表中登记被调用。

软件包Mojolicious::Plugin::AlertAssets;使用Mojo::Base“Mojolicious::Plugin”,-signatures;使用Mojo::File qw(curfile);子寄存器($self、$app、$conf){#附加“模板”和“公共”目录my$base=curfile->sibling('AlertAssets');push@{$app->renderer->paths},$base->child('templates')->to_string;push@{$app->static->paths},$base->child('public')->to_string;}1;

两者都能正常工作模板公众的安装并加载插件后,目录的优先级稍低。

使用Mojolicious::Lite;插件“AlertAssets”;获取'/alert_me';应用程序->启动;__数据__@@警报_me.html.ep<!DOCTYPE html><html><头部><title>提醒我</标题>%=包括“警报资产”</头><body>您已收到警报</车身></html>

它对捆绑在数据插件的部分。

软件包Mojolicious::Plugin::AlertAssets;使用Mojo::Base“Mojolicious::Plugin”,-signatures;子寄存器($self、$app、$conf){#附加类push@{$app->renderer->classes},__PACKAGE__;push@{$app->static->classes},__PACKAGE__;}1;__数据__@@警报资产.js警报(“你好,世界!”);@@alertassets.html.ep%=javascript“/alertassets.js”

后处理动态内容

而使用钩子后处理任务通常非常容易Mojolicious中的“after_dispatch”,对于由渲染器生成的内容,使用它要高效得多Mojolicious中的“after_render”.

使用Mojolicious::Lite签名;使用IO::Compress::Gzip qw(Gzip);hook-after_render=>sub($c,$output,$format){#检查存储中是否设置了“gzip=>1”除非$c->stash->{gzip},否则返回;#检查用户代理是否接受gzip压缩返回除非($c->req->headers->accept_encoding//'')=~/gzip/i;$c->res->headers->append(变量=>“接受编码”);#使用gzip压缩内容$c->res->headers->content_encoding('zip');gzip$output,\my$compressed;$$output=$compressed;};get'/'=>{template=>'hello',title=>'hello',gzip=>1};应用程序->启动;__数据__@@你好.html.ep<!DOCTYPE html><html><head><title><%=title%></title></head><body>压缩内容</车身></html>

如果要压缩所有动态生成的内容,还可以激活Mojolicious::Renderer中的“压缩”.

流动

您不必一次呈现所有内容,方法Mojolicious::Controller中的“写入”也可以用于流式传输一系列较小的块。

使用Mojolicious::Lite签名;获取“/”=>子($c){#准备车身my$body=“你好,世界!”;$c->res->headers->content_length(长度$body);#使用drain回调直接开始写入my$drain=sub($c){my$chunk=substr$body,0,1,'';$c->write($chunk,length$body?__SUB__:undef);};$c->$排水;};应用程序->启动;

只要实际写入了前面的整个数据块,就会执行排出回调。

HTTP/1.1 200正常日期:2014年9月13日星期六16:48:29 GMT内容物长度:12服务器:Mojolicious(Perl)你好,世界!

而不是提供内容长度您也可以调用标题Mojolicious::Controller中的“finish”完成后手动关闭连接。

使用Mojolicious::Lite签名;获取“/”=>子($c){#准备车身my$body=“你好,世界!”;#使用drain回调直接开始写入my$drain=sub($c){my$chunk=substr$body,0,1,'';长度$chunk$c->write($chunk,__SUB__):$c->finish;};$c->$排水;};应用程序->启动;

虽然这相当低效,因为它会阻止keep-alive,但对于EventSource和类似的应用程序来说,这有时是必要的。

HTTP/1.1 200正常日期:2014年9月13日星期六16:48:29 GMT连接:关闭服务器:Mojolicious(Perl)你好,世界!

分块传输编码

对于非常动态的内容,您可能事先不知道响应内容的长度,这就是分块传输编码和Mojolicus::控制器中的“write_chunk”派上用场。常见的用法是发送提前将HTML文档的节加载到浏览器,并加快引用图像和样式表的预加载。

使用Mojolicious::Lite签名;获取“/”=>子($c){$c->write_chunk('<html><head><title>示例</title></head>'=>sub($c){$c->finish('<body>示例</body></html>');});};应用程序->启动;

可选的drain回调确保在继续处理之前已写入所有以前的块。要结束流,可以调用Mojolicious::Controller中的“finish”或写入空数据块。

HTTP/1.1 200正常日期:2014年9月13日星期六16:48:29 GMT传输编码:分块服务器:Mojolicious(Perl)29<html><head><title>示例</title></head>1亿<body>示例</body></html>0

特别是在长时间不活动超时的情况下,这对Comet(长轮询)非常有用。由于某些web服务器的限制,这可能无法在所有部署环境中完美工作。

编码

存储在文件中的模板应为UTF-8型默认情况下,但可以使用Mojolicious::Renderer中的“编码”.

$app->renderer->encoding('koi8-r');

中的所有模板数据节绑定到Perl脚本的编码。

使用Mojolicious::Lite;获取'/heart';应用程序->启动;__数据__@@心形.html.ep莫名其妙!

Base64编码数据文件

Base64编码的静态文件(如图像)可以轻松存储在数据部分,类似于模板。

使用Mojolicious::Lite;获取“/”=>{text=>'I“莫名其妙!”};应用程序->启动;__数据__@@favicon.ico(base64)…base64编码图像。。。

充气数据模板

存储在文件中的模板优先于来自数据部分,这允许您在应用程序中包含一组默认模板,用户可以稍后进行自定义。命令Mojolicious::命令::作者::inflate将从数据节中的实际文件模板公众的目录。

$ ./myapp.pl充气

自定义模板语法

您可以通过加载轻松更改整个模板语法Mojolicious::插件::EPrender使用自定义配置。

使用Mojolicious::Lite;插件EPrender=>{name=>“胡子”,模板=>{标记开始=>“{{”,标记结束=>'}}'}};获取“/:name”=>{name=>“匿名”}=>“索引”;应用程序->启动;__数据__@@index.html胡子你好{{=$name}}。

Mojo::模板包含可用选项的完整列表。

添加您喜爱的模板系统

也许你更喜欢不同的模板系统电动自行车,由提供Mojolicious::插件::EPrender,并且您最喜欢的CPAN上还没有插件。你所要做的就是添加一个新的处理程序具有Mojolicious::Renderer中的“add_handler”什么时候登记被调用。

软件包Mojolicious::Plugin::MyRenderer;使用Mojo::Base“Mojolicious::Plugin”,-signatures;子寄存器($self、$app、$conf){#添加“mine”处理程序$app->renderer->add_handler(mine=>sub($renderer,$c,$output,$options){#检查一次性内联模板我的$inlinetemplate=$options->{inline};#检查“templates”目录中的适当模板我的$template_path=$renderer->模板路径($options);#检查DATA部分中的适当模板my$data_template=$renderer->getdata_template($options);#此部分取决于您和您的模板系统:)。。。#将渲染结果传递回渲染器$$output=“你好,世界!”;#或者如果发生错误就直接死亡die“模板出现问题”;});}1;

内联模板(如果由用户提供)将与选项一起传递。你可以使用Mojolicious::Renderer中的“template_path”搜索模板应用程序的目录,以及Mojolicious::Renderer中的“get_data_template”搜索数据部分。

使用Mojolicious::Lite;插件“MyRenderer”;#渲染内联模板get'/inline'=>{inline=>'…',handler=>'mine'};#从DATA部分渲染模板获取'/data'=>{template=>'test'};应用程序->启动;__数据__@@test.html我的。。。

添加处理程序以生成二进制数据

默认情况下,渲染器假定处理程序生成需要自动编码的字符,但如果要生成字节,则很容易禁用此功能。

使用Mojolicious::Lite签名;使用可存储qw(nfreeze);#添加“可存储”处理程序app->renderer->add_handler(storable=>sub($renderer,$c,$output,$options){#禁用自动编码删除$options->{encoding};#对存储值中的数据进行编码$$output=nfreeze删除$c->stash->{storable};});#如果已设置“可存储”值,则自动设置“处理程序”值app->hook(before_render=>sub($c,$args){$args->{handler}=“storable”如果存在$args->{storable}||存在$c->stash->{storable};});获取“/”=>{storable=>{i=>'动人'}};应用程序->启动;

钩子Mojolicious中的“before_render”可以用来生成诸如可储存的特别的,这样他们就不再需要处理程序要显式设置的值。

#显式“handler”值$c->渲染(可存储=>{i=>'mojolicious“},handler=>”storable“);#隐式“handler”值(带有“before_render”挂钩)$c->render(可存储=>{i=>'mojolicious’});

更多

您可以继续Mojolicious::指南现在或者看看Mojolicuis维基,其中包含许多不同作者编写的更多文档和示例。

支持

如果您有任何文档可能还没有回答的问题,请毫不犹豫地在论坛,上的IRC公司,或矩阵.