我正在玩CakePHP,建立一个只有帖子和评论的简单博客网站。我烘焙了模型,控制器和视图。当您查看帖子时,它会显示"相关评论"底部的部分,显示了所有帖子的评论。每个评论都有操作按钮("查看","编辑"和"删除")。我注意到,如果您编辑或删除评论,则不将被收回您正在查看的帖子。相反,您将被带到评论索引。当您查看帖子并点击"新评论时,会发生同样的事情。底部的按钮,并为该帖子添加新评论。我想修改此行为,以便在您查看帖子并编辑或删除现有评论或添加新评论时,您将重定向回帖子。我在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
文件中测试这种行为,所以我看起来像这样:
<?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.
即使测试在浏览器中工作正常,也知道为什么会在命令行上发生这种情况?我该如何解决?
答案 0 :(得分:1)
这并不能回答您的确切问题,但我相信您可以更快,更清晰地解决您的问题,并使其更容易理解和测试。
如果删除成功(以便不会导致404),则需要重定向到索引;如果失败则需要引用。
public function delete($id = null) {
if ($this->Comment->delete($id)) { //If comment deletion succeeds
return $this->redirect(array('action' => 'index'); //Redirect to index
}
return $this->redirect($this->referer()); //Else redirect to referrer
}
请注意return
将如何停止进一步执行,因此您实际上并不需要else
。这段代码现在只有3条简单的行,只有一个缩进级别。
此外,我认为此代码几乎不需要任何测试,因为它基于经过严格测试的核心功能。您可以相信Model::delete()
或Controller::redirect()
可以完成他们的工作,如果您信任那些您可以信任控制器方法也会按预期执行的人。我认为测试模型比控制器更重要(不是说控制器应该被排除在外,但我只是懒得去测试那些复杂或容易发生变化/错误的事情。)
因此,如果您仍然需要进入极端测试阶段,可以将$_SERVER['HTTP_REFERER']
设置为您喜欢的任何内容(CakeRequest
将$this->referer()
选为{{1}})并查看是否为{{1}}删除失败后重定向到的URL。