我有一个PHP类,我必须调用PHP header
函数来显示一个网页。正如this post所指出的那样,标题后应跟exit
回调。由于这种情况在我的课程中很常见,我在父类中定义了一个方法:
class ParentClass
{
protected function header($url)
{
header('Location:'.$url);
exit;
}
}
我想从子类中调用此方法:
class ChildClass extends ParentClass
{
public function someFunc()
{
$this->header($some_url);
}
}
PHP documentation说exit
终止当前脚本。我的问题是:退出函数是否终止子脚本,即使它包含在父类中?
修改
在我的具体情况下,我使用的是MVC设计模式,而ChildClass
是一个控制器。在其中,有时我需要显示一个视图,有时我需要重定向到另一个URL。让我用一个实际的例子来解释它。
假设有一个包含登录部分的网站。当向用户显示登录页面(登录数据未提交)时,登录控制器应显示登录视图。此视图包含一个带有action="login.html"
之类操作的表单。提交数据时,将调用登录控制器并检查登录数据:如果登录成功,则会将用户重定向到其管理部分。
class UsersController extends BaseController
{
public function login()
{
try
{
if(isset($_POST['submit']))
{
// check login data, throw exception in case of error
// if success, redirect to admin section
$this->header('admin.html');
}
else
{
// show login view
}
}
catch(Exception $e)
{
// show login view (with error)
}
}
}
class BaseController
{
protected function header($url)
{
header('Location:'.$url);
exit;
}
}
由于这种情况在我的控制器中很常见,我更倾向于在header
中定义BaseController
方法而不是每次都输入
header('Location:someURL.html');
exit;
在我的OP中,我只想确保$this->header('admin.html');
回调会终止当前login
方法,即使它是在BaseController
脚本中定义的。
希望现在有点清楚。
答案 0 :(得分:1)
正如评论中已经描述的那样,退出将终止所有内容,即网页立即停止执行,包括清理功能和最后阻止。
因此,您应该非常谨慎地考虑使用exit,因为可能会发生许多事情:当您不使用自动提交时,数据不会写入数据库(除非您在调用exit之前提交数据)。默认情况下,PHP的MySQL模块中没有启用自动提交(据我所知)。
这是一个例子:
class B extends A {
public function someFunc() {
# you might wanna use partent instead as
# pointed out by Ding in the comments, but
# maybe someFunc does more that just doing
# the redirect.
$this->header("http://google.com");
}
}
try {
print("Ok...");
$obj = new B();
$obj->someFunc();
print("Nahh..."); # doesn't get called/
} finally {
print("Cleaning up."); # doesn't get called, either.
}
而不是调用exit方法,而应该实现清晰的MVC设计模式。这是一个非常简单的例子:
<?php
class Response {
# use private here and use appropriate
# getters and setters.
public $status_code = 200;
public $content = "";
public $headers = array();
}
class HomeView extends View {
# called when a get request is made.
public function get() {
$response = new Response();
$response->content = "Hello world."
}
}
class RedirectionView {
public function get() {
$response = new Response();
$response->status_code = 301; # use 302 if moved only temporarily.
$response->headers["Location"] = "http://google.com";
}
}
function processRequest() {
# load appropriate view programatically
$view = new RedirectionView();
$response = $view->get();
http_response_code($response->status_code);
foreach ($response->headers as $headerName => $headerValue) {
header(sprintf("%s: %s", $headerName, $headerValue));
}
print($view->content)
}
?>
请注意,这不是一个真正的MVC设计模式(模型缺失,而且,不清楚控制器是什么,但是,这也是django(Pyhton框架)使用的)。你可能想看看PHP MVC框架(一个快速的谷歌搜索会做的伎俩)或实现自己的(我的例子可能是一个良好的开端)。
编辑1:
使用exit
可能没问题(但我不会使用它,因为我认为这是不好的做法)。如果你能够编辑你正在使用的设计方法,我会创建你的View BaseClass get / post方法(或者你返回响应对象的方法。注意:如果你使用print来显示响应用户,尝试添加一个响应,其中包含您要求显示的所有数据。这比在您的代码中到处都有print
s(或echo
s)更好。登记/>
使用响应对象,您的代码就可以只设置位置标头(如果它是重定向)或显示消息。因此,您不需要“杀死”网页的任何部分,并且在执行结束时它将终止。但同样:你可能很高兴在你的方法中使用exit
调用(除非你遇到代码的任何问题(未提交的数据库事务,未更新的统计数据)(因为它在exit
语句之后。Exit
将完全终止您的脚本。