适用于任意树结构的 Catalyst 调度程序
您好,
我是 Catalyst 的新手,我正在尝试实现一些调度逻辑。
我的数据库有一个项目表,每个项目都有一个唯一的 url_part
字段,并且每个项目在同一个表中都有一个父项,形成树结构。如果 baz
是 bar
的子级,而 bar
是 foo
的子级,而 foo
是根的子级,我想要 URL / foo/bar/baz
映射到该对象。树可以是任意深度,用户需要能够访问任何节点,无论是分支还是叶子。
我一直在查看链式调度程序的文档,但我不确定这是否可以达到我想要的效果。似乎链式调度程序中的每个步骤都必须为 PathPart
属性定义一个名称,但我希望我的 URL 仅由数据库结构确定。
使用现有的 Catalyst 调度程序很容易实现这一点,还是我需要编写自己的调度类?
谢谢! :)
ETA:
我发现我可以使用空的 Args 属性来捕获任意数量的参数。以下似乎成功捕获了根下的每个请求:
sub default :Path :Args() {
my ( $self, $c ) = @_;
my $path = $c->request->path;
$c->response->status( 200 );
$c->response->body( "Your path is $path" );
}
从那里我可以手动解析路径并获取我需要的内容,但是,我不知道这是否是完成我所追求的内容的最佳方式。
Greetings,
I'm new to Catalyst and I am attempting to implement some dispatch logic.
My database has a table of items, each with a unique url_part
field, and every item has a parent in the same table, making a tree structure. If baz
is a child of bar
which is a child of foo
which is a child of the root, I want the URL /foo/bar/baz
to map to this object. The tree can be any depth, and users will need to be able to access any node whether branch or leaf.
I have been looking through the documentation for Chained dispatchers, but I'm not sure if this can do what I want. It seems like each step in a chained dispatcher must have a defined name for the PathPart
attribute, but I want my URLs to be determined solely by the database structure.
Is this easy to implement with the existing Catalyst dispatcher, or will I need to write my own dispatch class?
Thanks! :)
ETA:
I figured out that I can use an empty Args
attribute to catch an arbitrary number of arguments. The following seems to successfully catch every request under the root:
sub default :Path :Args() {
my ( $self, $c ) = @_;
my $path = $c->request->path;
$c->response->status( 200 );
$c->response->body( "Your path is $path" );
}
From there I can manually parse the path and get what I need, however, I don't know if this is the best way to accomplish what I'm after.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
这取决于您的数据结构,从您的问题中我并不完全清楚这一点。
如果有固定数量的级别(或者至少是有限范围的级别数量),每个级别对应于一种特定类型的事物,那么 Chained 可以做你想做的事——拥有一个与
:CaptureArgs(1) PathPart('')
的链式操作将在路径中创建一个/*/
段 - 也就是说,它会吞噬路径的一个段路径,不需要显示任何特定的固定字符串。如果没有这样的事情——例如,您正在任意树上追逐无限数量的级别,那么可变参数
:Args
操作可能正是您想要的,并且使用它没有什么肮脏的地方。但您不需要自己解码$c->req->path
——您可以从$c->req-> 获取剩余的路径段;args
,或者简单地在您的操作中执行my ($self, $c, @args) = @_;
。您可以编写一个新的DispatchType,但它不太可能值得回报。
It depends on the structure of your data, which I'm not completely clear on from your question.
If there is a fixed number of levels (or at least a limited range of numbers of levels) with each level corresponding to a specific sort of thing, then Chained can do what you want -- it's valid (and downright common) to have a chained action with
:CaptureArgs(1) PathPart('')
which will create a/*/
segment in the path -- that is, it gobbles up one segment of the path without requiring any particular fixed string to show up.If there's not any such thing -- e.g. you're chasing an unlimited number of levels down an arbitrary tree, then a variadic
:Args
action is probably exactly what you want, and there's nothing dirty in using it. But you don't need to be decoding$c->req->path
yourself -- you can get the left-over path segments from$c->req->args
, or simply domy ($self, $c, @args) = @_;
in your action.You can write a new DispatchType, but it's just not likely to be worth the payoff.
在尝试了各种选择之后,我相信我已经找到了一个可以接受的解决方案。不幸的是,我无法使用
:Chained
进行递归调度(如果您尝试将处理程序链接到自身,Catalyst 会抱怨。这没什么好玩的。)所以我最终使用了一个带有大容量的处理程序 。
CaptureArgs
,如下所示:如果我在
/foo/bar/baz
上执行GET
,我就会得到我想要的。如果 URL 的任何部分与数据库中的对象不对应,我会得到 404。
这对于我的应用程序来说效果很好,它永远不会有十级深的东西,但我希望我能找到一个更通用的解决方案可以支持任意深度的树。
After playing around with various options, I believe I've arrived at an acceptable solution. Unfortunately, I couldn't get a recursive dispatch going with
:Chained
(Catalyst complains if you try to chain a handler to itself. That's no fun.)So I ended up using a single handler with a large
CaptureArgs
, like this:If I do a
GET
on/foo/bar/baz
I getwhich is what I want. If any part of the URL doesn't correspond to an object in the DB, I get a 404.
This works fine for my application, which will never have things ten-levels deep, but I wish I could find a more general solution that could support an arbitrary-depth tree.