2013-05-22 65 views
1

我正在尝试创建一个对我的设计师非常灵活的Catalyst应用程序。我的意思是,如果他们需要添加一个静态内容的新页面,我不需要进入Catalyst并添加该动作,然后才能为该页面创建模板。如果他们添加了任何名为name.html的模板,那么即使没有name操作,Catalyst应用也可以显示http://www.domain.com/name.html。目前,我有在根控制器,看起来像这样的子程序:未找到催化剂模板工具包模板返回404

sub any_template :Regex('(.+)\.html$') { 
    my ($self, $c) = @_; 
    $c->stash(
     template => $c->action . '.html', 
    ); 
} 

,这使得它,以便以“.html”结尾的任何请求都将寻找该名称的模板。但是,如果对不存在的模板请求url,Template Toolkit会抛出一个错误,指出它无法呈现模板,这是合理的,因为它不存在。但是,如果模板不存在,我希望能够显示404未找到的页面。是否有可能做到这一点?或者有没有人有更好的方法,让你可以有模板页面,而无需添加一个空的动作到你的Catalyst应用程序?我知道可以使用perl的-e文件测试来查看模板是否存在于文件系统中,但有没有更好的方法可以做到这一点?谢谢!

UPDATE

这是我目前的包装是什么样子:

[% 
    debug("Applying HTML page layout wrappers to $template.name\n"); 
    content WRAPPER "$host/site/html" + "$host/site/layout"; 
-%] 

这主要是受TTSite产生。无论如何,我可以做类似于RET建议的东西,在那里我可以使用try catch块来使用404页面,如果失败了?

UPDATE

我试着更新我的包装的模板这样:

[%- 
    TRY; 
     content WRAPPER "$host/site/html" + "$host/site/layout"; 
    CATCH file; 
     "File Error! $error.info"; 
    CATCH; 
     "Error: $error.info!"; 
    END; 
-%] 

而且它会说,那里是当它无法找到页面文件错误:

Couldn't render template test.html: file error - test.html: not found 

但是,它不会去我的任何catch块。我应该把它放在别的地方吗?

UPDATE

Template Toolkit单证说:

Note that the DEFAULT option (disabled by default) allows you to specify a default 
file to be used any time a template file can't be found. This will prevent file 
exceptions from ever being raised when a non-existant file is requested (unless, 
of course, the DEFAULT file your specify doesn't exist). Errors encountered once 
the file has been found (i.e. read error, parse error) will be raised as file 
exceptions as per usual. 

这正是我期待的,但目前还没有如何使用这样的例子。有谁知道如何使用DEFAULT选项?

回答

0

所以我最终找出了一个解决方案,让我做我想做的事。不使用默认的RenderView的,我创建了自己:

#old end action 
#sub end : ActionClass('RenderView') {} 

sub end : Private { 
    my ($self, $c) = @_; 

    return if $c->res->body ne ''; 

    my $output; 
    eval { $output = $c->view($c->stash->{current_view})->render($c,$c->stash->{template})}; 

    unless([email protected]) { 
     $c->res->body($output); 
    } 
    else { 
     $c->res->status(404); 
     $c->stash->{template} = 'errors/404.html'; 
     $c->forward($c->view('NO_HTML')); 
    } 
} 

这可能是一个有点哈克,但它确实我想要的东西,让我用404的响应,每当一个页面同时显示404页没有找到,这使我可以保持灵活性,无需为我创建的每个模板定义一个操作。

1

您可能不需要为您的静态内容使用Catalyst。通常,图像,CSS,Javascript等静态内容由Web服务器(nginx或APache)直接提供。你可以用你的HTML静态文件做同样的事情。

如果你真的想混合静态和动态内容,请看Catalyst :: Plugin :: Static :: Simple] 1$c->serve_static_file($file_path)函数。

+0

但是后来我失去了使用模板系统的好处,其中只需要更改的内容位于页面中间。我希望我的设计师不必在任何地方重复相同的页眉,页脚等。所以它是'静态'的内容,但我仍然想要像Template Toolkit这样的模板系统的好处。 – srchulo

1

我已经提出了Julien的回答,因为他完全正确 - 这是处理真正静态资源的最佳方式。如果它只是HTML,请让它们放在静态区域,并根据您的Web服务器的需要设置别名或位置记录。但是,如果您的设计师正在制作需要放入WRAPPER或需要动态处理的模板,那么您将很快用这种方法达到一些限制。

,而不是处理模板一样,直接说,你可以做这样的事情:

=== Root.pm ===

sub any_template { 
    ... 
    $c->stash(template => 'static.tt'); 
} 

=== static.tt = ==

[%- WRAPPER foo.tt -%] 
[%- SET tmpl = c.action; 
    TRY; 
     # use either PROCESS if a template, or INCLUDE if it's HTML 
     PROCESS tmpl _ ".tt"; 
     # INCLUDE tmpl _ ".html"; # or this 
    CATCH; 
     PROCESS "404.tt"; 
    END -%] 
[%- END -%] 

因此,文件未找到是优雅地处理。使用404.tt模板意味着您的包装的页眉/页脚等仍然呈现。

+0

无论如何,我可以让'404.tt'显示没有相同的页眉和页脚? – srchulo

+0

我已经对上面的帖子进行了更新,显示了我当前的包装代码。有没有什么办法可以做出类似于你在这个例子中用来处理404.tt的东西,如果有错误? – srchulo

+0

你不能把这个逻辑放到包装器中,因为'content'是先生成的,然后是包装器 - 它是按设计完成的。所以你失败的模板渲染已经发生了。在回答你关于更改404上的页眉/页脚的问题时,只需在包装器中测试的404.tt内设置一个变量即可。或者在CATCH块中放置一个不同的'WRAPPER'。 – RET