CakePHP 与 beforeFilter 的奇怪行为:我无法将变量设置到视图
好的,这需要一些设置:
我正在研究一种在我的 cakePHP 支持的博客的 URL 中使用漂亮的帖子标题“slugs”的方法。
例如:/blog/post-title-here
而不是 /blog/view_post/123
。
由于我显然不会为每篇文章都编写一个新方法,因此我尝试巧妙地使用 CakePHP 回调来模拟 PHP 5 的 __call()
魔术方法的行为。对于那些不知道的人,CakePHP 的调度程序会检查方法是否存在,并在控制器中调用 __call()
之前抛出 cakePHP 错误。
到目前为止我所做的:
为了充分披露(因为我不知道为什么会遇到问题),我有两条路线:
Router::connect('/blog/:action/*', array('controller' => 'blog_posts'));
Router::connect('/blog/*', array('controller' => 'blog_posts'));
这些为 BlogPostsController 设置了一个别名,这样我的网址就不会'看起来像 /blog_posts/action
然后在 BlogPostsController 中:
public function beforeFilter() {
parent::beforeFilter();
if (!in_array($this->params['action'], $this->methods)) {
$this->setAction('single_post', $this->params['action']);
}
}
public function single_post($slug = NULL) {
$post = $this->BlogPost->get_post_by_slug($slug);
$this->set('post', $post);
//$this->render('single_post');
}
beforeFilter
捕获不存在的操作并将它们传递给我的 single_post
方法。 single_post
从模型中获取数据,并为视图设置变量 $post
。
还有一个 index
方法可以显示最近 10 篇帖子。
这是令人困惑的部分:
您会注意到上面有一个被注释掉的 $this->render
方法。
- 当我不调用
$this->render('single_post')
时,视图会渲染一次,但$post
变量不会放。 - 当我 do 调用
$this->render('single_post')
时,视图将使用$post
变量集进行渲染,然后渲染再次未设置。因此,实际上我在同一个文档中得到了两个完整的布局,一个接一个。一种有内容,一种没有内容。
我尝试使用名为 single_post
的方法和名为 __single_post
的方法,但两者都有相同的问题。我希望最终结果是一个名为 __single_post
的方法,这样就无法通过 URL /blog/single_post
直接访问它。
另外,
我还没有对帖子不存在时的错误处理进行编码(这样当人们在 url 中输入随机内容时,他们就不会获得 single_post 视图)。我打算在解决这个问题后这样做。
Okay, this will require some setup:
I'm working on a method of using nice post title "slugs" in the URL's of my cakePHP powered blog.
For example: /blog/post-title-here
instead of /blog/view_post/123
.
Since I'm obviously not going to write a new method for every post, I'm trying to be slick and use CakePHP callbacks to emulate the behavior of PHP 5's __call()
magic method. For those who do not know, CakePHP's dispatcher checks to see if a method exists and throws a cakePHP error before __call()
can be invoked in the controller.
What I've done so far:
In the interest of full disclosure ('cause I have no Idea why I'm having a problem) I've got two routes:
Router::connect('/blog/:action/*', array('controller' => 'blog_posts'));
Router::connect('/blog/*', array('controller' => 'blog_posts'));
These set up an alias for the BlogPostsController so that my url doesn't look like /blog_posts/action
Then in the BlogPostsController:
public function beforeFilter() {
parent::beforeFilter();
if (!in_array($this->params['action'], $this->methods)) {
$this->setAction('single_post', $this->params['action']);
}
}
public function single_post($slug = NULL) {
$post = $this->BlogPost->get_post_by_slug($slug);
$this->set('post', $post);
//$this->render('single_post');
}
The beforeFilter
catches actions that do not exist and passes them to my single_post
method. single_post
grabs the data from the model, and sets a variable $post
for the view.
There's also an index
method that displays the 10 most recent posts.
Here's the confounding part:
You'll notice that there is a $this->render
method that is commented-out above.
- When I do not call
$this->render('single_post')
, the view renders once, but the$post
variable is not set. - When I do call
$this->render('single_post')
, The view renders with the$post
variable set, and then renders again with it not set. So in effect I get two full layouts, one after the other, in the same document. One with the content, and one without.
I've tried using a method named single_post
and a method named __single_post
and both have the same problem. I would prefer the end result to be a method named __single_post
so that it cannot be accessed directly with the url /blog/single_post
.
Also
I've not yet coded error handling for when the post does not exist (so that when people type random things in the url they don't get the single_post view). I plan on doing that after I figure out this problem.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
这并没有明确回答您的问题,但我只是通过仅使用路线解决问题来放弃整个复杂性:
请注意,上述路线仅依赖于最近的错误修复,截至撰写本文时,合并到 Cake 中(请参阅 http: //cakephp.lighthouseapp.com/projects/42648/tickets/1197-routing-error-when-using-regex-on-action)。请参阅这篇文章的编辑历史以获得更兼容的解决方案。
至于可直接访问的
single_post
方法:我不会。由于/blog/:slug
路由捕获所有以/blog/
开头的 URL,因此它会捕获/blog/single_post
并调用BlogPostsController::single_post('single_post')
。然后,您将尝试查找带有“single_post”名称的帖子,该帖子可能不存在。在这种情况下,您可以抛出 404 错误:错误处理:完成。
This doesn't explicitly answer your question, but I'd just forego the whole complexity by solving the problem using only routes:
Note that the above routes depend on a bug fix only recently, as of the time of this writing, incorporated into Cake (see http://cakephp.lighthouseapp.com/projects/42648/tickets/1197-routing-error-when-using-regex-on-action). See the edit history of this post for a more compatible solution.
As for the
single_post
method being accessible directly: I won't. Since the/blog/:slug
route catches all URLs that start with/blog/
, it'll catch/blog/single_post
and invokeBlogPostsController::single_post('single_post')
. You will then try to find a post with the slug "single_post", which probably won't exist. In that case, you can throw a 404 error:Error handling: done.