我知道如何使用Mason::Plugin::RouterSimple为页面组件指定路由,例如给定一个url:
/archives/2015/07
我可以创建一个组件archives.mc
:
<%class>
route "{year:[0-9]{4}}/{month:[0-9]{2}}";
</%class>
Archives for the month of <% $.month %>/<% $.year %>
同样我可以创建一个news.mc
组件来处理以下网址:
/news/2012/04
这很好(非常优雅!)但现在我想要的是能够像以下那样处理网址:
/john/archives/2014/12
/john/news/2014/03
/peter/news/2015/09
/bill/archives/2012/06
等。我知道我可以将路线规则写成:
<%class>
route "{user:[a-z]+}/archives/{year:[0-9]{4}}/{month:[0-9]{2}}", { action=> 'archives' };
route "{user:[a-z]+}/news/{year:[0-9]{4}}/{month:[0-9]{2}}", { action=> 'news' };
</%class>
然后请求必须由两个不同的组件处理。如何将请求路由到不同的组件? Mason不会匹配archives.mc
和news.mc
,因为在组件名称之前有一个用户名。
答案 0 :(得分:1)
问题在于,虽然/archives/2014/12
组件可以轻松处理/archives.mc
之类的问题,但对于/john/archives/2014/12
和/bill/archives/2012/06
等网址来说,它并不清楚放置档案组件的位置。
梅森会尝试匹配以下组件(它是一个简化列表,请参阅Mason::Manual::RequestDispatch):
...
/john/archives.{mp,mc}
/john/dhandler.{mp,mc}
/john.{mp,mc}
但最后......
/dhandler.{mp,mc}
所以我的想法是在根目录中放置一个dhandler.mc
组件:
<%class>
route "{user:[a-z]+}/archives/{year:[0-9]{4}}/{month:[0-9]{2}}", { action=> 'archives' };
route "{user:[a-z]+}/news/{year:[0-9]{4}}/{month:[0-9]{2}}", { action=> 'news' };
</%class>
<%init>
$m->comp($.action.'.mi', user=>$.user, year=>$.year, month=>$.month);
</%init>
如果网址与第一条路线匹配,则会调用archives.mi
组件:
<%class>
has 'user';
has 'year';
has 'month';
</%class>
<% $.user %>'s archives for the month of <% $.month %>/<% $.year %>
(我使用了.mi
组件,因此只能在内部访问。
可以改进dhandler(更好的regexp,可以从数据库表中检查用户并拒绝请求等)。
由于我的档案和新闻组件可以接受POST / GET数据,而且由于我想接受任何数据,我可以通过以下方式传递所有内容:
$m->comp($._action.'.mi', %{$.args});
不是太强大,但看起来它确实有效。