我知道如何使用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
组件来处理以下url:
/news/2012/04
,这很好(而且非常优雅!),但现在我想要的是能够处理像下面这些url:
/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>
,但是请求必须由两个不同的组件处理。如何将请求路由到不同的组件?archives.mc
和news.mc
不会被Mason匹配,因为组件名称前有一个用户名
问题是,虽然像/archives/2014/12
这样的url可以很容易地由/archives.mc
组件处理,但对于像/john/archives/2014/12
和/bill/archives/2012/06
这样的url,不清楚在哪里放置归档组件。
Mason将尝试匹配以下组件(这是一个简化的列表,请参阅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>
如果url匹配第一个路由,它将调用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});
不太优雅,但它看起来像它的工作