【发布时间】:2014-07-03 09:46:42
【问题描述】:
我正在使用 CakePHP,构建一个只有帖子和 cmets 的简单博客站点。我烘焙了模型、控制器和视图。当您查看帖子时,它在底部有一个“相关评论”部分,显示该帖子的所有 cmets。每个评论都有操作按钮(“查看”、“编辑”和“删除”)。我注意到,如果您编辑或删除评论,您不会返回您正在查看的帖子。相反,您将被带到 cmets 索引。当您查看帖子并单击底部的“新评论”按钮并为该帖子添加新评论时,也会发生同样的事情。我想修改此行为,以便在您查看帖子并编辑或删除现有评论或添加新评论时,您将被重定向回帖子。我在Comments 控制器中为这三个操作(“添加”、“编辑”和“删除”)中的每一个添加了代码。这个问题的重点是“删除”动作。这就是我所做的:
app/Controller/CommentsController.php中的原始代码
public function delete($id = null) {
$this->Comment->id = $id;
if (!$this->Comment->exists()) {
throw new NotFoundException(__('Invalid comment'));
}
$this->request->allowMethod('post', 'delete');
if ($this->Comment->delete()) {
$this->Session->setFlash(__('The comment has been deleted.'));
} else {
$this->Session->setFlash(__('The comment could not be deleted. Please, try again.'));
}
return $this->redirect(array('action' => 'index'));
}
修改代码app/Controller/CommentsController.php
public function delete($id = null) {
/*
* Same as above minus the redirect line (the following code replaces
* the redirect line).
*/
// Redirect to `$this->referer()` unless `$this->referer()`
// is this comment's "edit" or "view" action (we do not want to
// redirect the user to a 404 page), in which case redirect them
// to the comments index.
$referer = $this->referer();
if ($referer) {
$comingFromEditPage =
mb_strpos(
$referer,
Router::url(array('action' => 'edit', $id), true)
) === 0;
if (!$comingFromEditPage) {
$comingFromViewPage =
mb_strpos(
$referer,
Router::url(array('action' => 'view', $id), true)
) === 0;
}
if (!$comingFromEditPage && !$comingFromViewPage) {
$redirectUrl = $referer;
}
}
if (!isset($redirectUrl)) {
$redirectUrl = array('action' => 'index');
}
return $this->redirect($redirectUrl);
}
我想在我的 app/Test/Case/Controller/CommentsControllerTest.php 文件中测试这种行为,所以我让它看起来像这样:
CommentsControllerTest.php
<?php
App::uses('CommentsController', 'Controller');
class CommentsControllerTest extends ControllerTestCase {
public $fixtures = array(
'app.comment',
'app.post'
);
public function tearDown() {
parent::tearDown();
unset($this->Controller);
}
public function testDeleteReferer() {
// When the referer is the comment's "edit" action, deleting the
// comment should redirect to the comments index.
$this->Controller = $this->generate('Comments', array(
'methods' => array(
'referer'
)
));
$this->Controller->expects($this->any())->method('referer')->will(
$this->returnValue(
Configure::read('App.fullBaseUrl') .
$this->Controller->request->base .
Router::url(
array(
'controller' => 'comments',
'action' => 'edit',
'1',
)
)
)
);
$commentsIndexUrl =
Configure::read('App.fullBaseUrl') .
$this->Controller->request->base .
Router::url(
array(
'controller' => 'comments',
'action' => 'index',
)
);
$this->testAction(
'/comments/delete/1',
array('method' => 'post')
);
$this->assertEqual(
$this->headers['Location'],
$commentsIndexUrl
);
// When the referer is the comment's "view" action, deleting the
// comment should redirect to the comments index.
$this->Controller = $this->generate('Comments', array(
'methods' => array(
'referer'
)
));
$this->Controller->expects($this->any())->method('referer')->will(
$this->returnValue(
Configure::read('App.fullBaseUrl') .
$this->Controller->request->base .
Router::url(
array(
'controller' => 'comments',
'action' => 'view',
'2',
)
)
)
);
$this->testAction(
'/comments/delete/2',
array('method' => 'post')
);
// The following assertion fails on the command line!
$this->assertEqual(
$this->headers['Location'],
$commentsIndexUrl
);
}
}
如上面代码中所述,第二个assertEqual 在命令行上失败。当我运行cake test --stderr app Controller/CommentsController 时,输出如下:
Welcome to CakePHP v2.5.2 Console
---------------------------------------------------------------
App : app
Path: /Applications/MAMP/htdocs/blogtest/app/
---------------------------------------------------------------
CakePHP Test Shell
---------------------------------------------------------------
F
Time: 0 seconds, Memory: 18.50Mb
There was 1 failure:
1) CommentsControllerTest::testDeleteReferer
Failed asserting that two strings are equal.
--- Expected
+++ Actual
@@ @@
-'http://localhost/Applications/MAMP/htdocs/blogtest/lib/Cake/Console/comments'
+'http://localhost/Applications/MAMP/htdocs/blogtest/lib/Cake/Console/Applications/MAMP/htdocs/blogtest/lib/Cake/Console/comments/view/2'
/Applications/MAMP/htdocs/blogtest/lib/Cake/TestSuite/CakeTestCase.php:552
/Applications/MAMP/htdocs/blogtest/app/Test/Case/Controller/CommentsControllerTest.php:93
/Applications/MAMP/htdocs/blogtest/lib/Cake/TestSuite/CakeTestCase.php:82
/Applications/MAMP/htdocs/blogtest/lib/Cake/TestSuite/CakeTestRunner.php:60
/Applications/MAMP/htdocs/blogtest/lib/Cake/TestSuite/CakeTestSuiteCommand.php:96
/Applications/MAMP/htdocs/blogtest/lib/Cake/Console/Command/TestShell.php:274
/Applications/MAMP/htdocs/blogtest/lib/Cake/Console/Command/TestShell.php:259
/Applications/MAMP/htdocs/blogtest/lib/Cake/Console/Shell.php:440
/Applications/MAMP/htdocs/blogtest/lib/Cake/Console/ShellDispatcher.php:207
/Applications/MAMP/htdocs/blogtest/lib/Cake/Console/ShellDispatcher.php:66
FAILURES!
Tests: 1, Assertions: 2, Failures: 1.
知道为什么即使测试在浏览器中运行良好,为什么会在命令行上发生这种情况吗?我该如何解决?
【问题讨论】:
-
我不明白你为什么要经历这些麻烦。如果删除失败,只需重定向回引荐来源网址,如果删除成功,则重定向回
index非常简单。一个简单的 if/else 就足够了。将 if 条件拆分为多行也会使代码难以阅读。如果您确实需要帮助,请遵守约定。 -
@user221931 为什么我的目标是在删除失败时重定向回引荐来源网址,如果删除成功则重定向到
index?就个人而言,我认为我用于if语句的格式比这更容易阅读:if ($this->referer() && !(mb_strpos($this->referer(), Router::url(array('action' => 'edit', $id), true)) === 0) && !(mb_strpos($this->referer(), Router::url(array('action' => 'view', $id), true)) === 0)) {。你不同意吗?另外,我没有遵循哪些约定,这如何使获得帮助变得更加困难? -
那么你的目标是什么?不要以这种态度面对我,您可以阅读 cakephp 的预期编码标准是什么,也许反思为什么您没有得到任何答案。
-
@user221931 我的目标显示在“
app/Controller/CommentsController.php中的修改代码”部分中“删除”操作顶部的注释中。以这样的态度面对你?我说什么粗鲁了?此外,我通过CakePHP Code Sniffer 运行了我的代码,除了我的测试还没有函数 doc cmets 之外,这很好。所以我仍然不确定你指的是什么。最后,您似乎在暗示我的代码格式化方式与没有答案有关。我是否正确解释了您的评论? -
我认为您的回复过于激进,我深表歉意。这是陌生人之间书面交流的产物。你的代码中有
...,所以我不知道你在做什么,但我希望你删除评论。除非评论被删除,否则不想重定向到 404 是没有意义的。所以你的方法看起来很奇怪,如果你接受我的建议,可以更容易地解决/测试。分解if语句也是不好的做法。如果它变得太复杂并且不能这样做,否则使用临时变量。太难读的代码意味着更少的人会费心。
标签: cakephp