如何访问应用程序中的其他控制器?
How to access other controllers in your application?
我有一个应用程序,其中包含多个控制器,每个控制器都专用于自己的部分,例如,"news"、"articles" 和 "shop"。他们没有相互联系,但他们应该是,因为我需要从他们那里插入数据,比如与当前商店类别相关的新闻。除了当前处理请求的控制器之外,我还没有找到一种访问控制器的干净方法。
模块的结构是:
Site.pm
是主项目文件。
Articles.pm
处理文章。
News.pm
处理新闻。
Shop.pm
处理店铺。
Site.pm
从模块名称数组中动态加载上述各项,并在启动时调用其 register
函数来设置路由和其他内容。文章、新闻等都从数据库中获取内容,并将其呈现为内联模板,因此,我不能只获取相关新闻并将它们猛烈地存储起来,因为并非商店中的所有条目甚至都需要该信息。
我没有在 Mojolicious 上工作过,但我认为这是最好的方法 -
您的站点控制器应该向它想要的任何其他控制器发送 GET 请求,这些控制器应该 return JSON 数据,然后可以在客户端呈现这些数据。看看Rendering JSON。希望对您有所帮助。
这是没有代码的理论答案。
您可能将数据库内容作为模型与实际控制器分离。那挺好的。
因此,假设我们在商店中并且想要显示与当前产品相关的新闻。至少有两种方法可以做到这一点。
你直接调用你的模型。您的新闻模型提供了一种获取产品新闻的方法。您在显示产品页面的商店控制器中执行此操作。此控制器需要将内容放入存储中,以便模板可以访问它。
您在新闻控制器中创建了一个无法从外部访问的方法。你让它获取一个产品 ID 并找到相关的新闻文章并将它们填充到存储中。您从商店控制器中的产品页面控制器转发到它。之后,产品页面控制器继续。这是更解耦的方式。
在这两种情况下,您的商店模板都包含另一个模板,该模板知道如何处理藏品中的物品以显示新闻。您或许可以在此处回收新闻模板。
根据我的经验、编码血统和对我的代码的很多耻辱,我建议:
控制器中的每个方法应该只调用一个函数并将结果传递给模板。这在某种程度上类似于@simbabque 的回答。
这将有助于您稍后测试控制器,编写API而不是提供html模板,甚至完全改变框架(只要是Perl)。
所以,我会在控制器和模型之间添加一个可选层:
$t->get('/books/:id')->to('books#get')
sub Books::get{ my $self = shift; my $book = FBooks::get($self->param('id')); # plus template call }
sub FBooks::get{ # here you call your Model }
# your Model calls your DB
只有在需要多次调用 model/s 时才提供 FBooks::get(也许这不是一个完美的例子,但我希望你明白我的意思)。我更喜欢这个而不是一大群助手。如果还有其他更好的方法,我很乐意学习。
我有一个应用程序,其中包含多个控制器,每个控制器都专用于自己的部分,例如,"news"、"articles" 和 "shop"。他们没有相互联系,但他们应该是,因为我需要从他们那里插入数据,比如与当前商店类别相关的新闻。除了当前处理请求的控制器之外,我还没有找到一种访问控制器的干净方法。
模块的结构是:
Site.pm
是主项目文件。Articles.pm
处理文章。News.pm
处理新闻。Shop.pm
处理店铺。
Site.pm
从模块名称数组中动态加载上述各项,并在启动时调用其 register
函数来设置路由和其他内容。文章、新闻等都从数据库中获取内容,并将其呈现为内联模板,因此,我不能只获取相关新闻并将它们猛烈地存储起来,因为并非商店中的所有条目甚至都需要该信息。
我没有在 Mojolicious 上工作过,但我认为这是最好的方法 -
您的站点控制器应该向它想要的任何其他控制器发送 GET 请求,这些控制器应该 return JSON 数据,然后可以在客户端呈现这些数据。看看Rendering JSON。希望对您有所帮助。
这是没有代码的理论答案。
您可能将数据库内容作为模型与实际控制器分离。那挺好的。
因此,假设我们在商店中并且想要显示与当前产品相关的新闻。至少有两种方法可以做到这一点。
你直接调用你的模型。您的新闻模型提供了一种获取产品新闻的方法。您在显示产品页面的商店控制器中执行此操作。此控制器需要将内容放入存储中,以便模板可以访问它。
您在新闻控制器中创建了一个无法从外部访问的方法。你让它获取一个产品 ID 并找到相关的新闻文章并将它们填充到存储中。您从商店控制器中的产品页面控制器转发到它。之后,产品页面控制器继续。这是更解耦的方式。
在这两种情况下,您的商店模板都包含另一个模板,该模板知道如何处理藏品中的物品以显示新闻。您或许可以在此处回收新闻模板。
根据我的经验、编码血统和对我的代码的很多耻辱,我建议: 控制器中的每个方法应该只调用一个函数并将结果传递给模板。这在某种程度上类似于@simbabque 的回答。
这将有助于您稍后测试控制器,编写API而不是提供html模板,甚至完全改变框架(只要是Perl)。
所以,我会在控制器和模型之间添加一个可选层:
$t->get('/books/:id')->to('books#get')
sub Books::get{ my $self = shift; my $book = FBooks::get($self->param('id')); # plus template call }
sub FBooks::get{ # here you call your Model }
# your Model calls your DB
只有在需要多次调用 model/s 时才提供 FBooks::get(也许这不是一个完美的例子,但我希望你明白我的意思)。我更喜欢这个而不是一大群助手。如果还有其他更好的方法,我很乐意学习。