2013-05-22 69 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