我是PHP的新手。我想查看我使用过的变量的范围。特别是$model
。
$model = new LoginModel();
$controller = new LoginController($model);
$view = new LoginView($controller, $model);
下面附有我为登录而编写的代码。用户可以通过GET /login.php
访问该页面,然后将表单提交到POST /login.php?action=login
。在此过程中,LoginModel
会相应地更新LoginController
。
我想使用我在页面执行的后续部分更新的$model
。但是,我注意到$model
是"重置"一旦呼叫从LoginController.login()
返回。
我不确定是不是因为$model
在我的情况下是按值传递的。或者,如果还有其他事情,我做错了,但我不知道。有谁可以启发我这个?
<?php
class LoginModel {
public $username = "";
public $password = "";
public $message = "";
public $loginSuccess = false;
public function __construct() {
}
}
class LoginView {
private $model;
private $controller;
public function __construct($controller, $model) {
$this->controller = $controller;
$this->model = $model;
}
public function getUsernameField() {
return $this->makeInput("text", "username", "");
}
public function getPasswordField() {
return $this->makeInput("password", "password", "");
}
private function makeInput($type, $name, $value) {
$html = "<input type=\"$type\" name=\"$name\" value=\"$value\" />";
return $html;
}
}
class LoginController {
const HOME_URL = "http://localhost/";
private $model;
public function __construct($model) {
$this->model = $model;
}
public function login() {
$username = $_POST['username'];
$password = $_POST['password'];
if ($username === $password) {
$_SESSION['username'] = $username;
$model->username = $username;
$model->password = "";
$model->message = "Hello, $username!";
$model->loginSuccess = true;
header("Refresh: 3; URL=" + LoginController::HOME_URL);
} else {
$model->message = "Sorry, you have entered an invalid username-password pair.";
$model->loginSuccess = false;
}
}
public function handleHttpPost() {
if (isset($_GET['action'])) {
if ($_GET['action'] === 'login') {
$this->login();
}
} else {
// invalid request.
http_response_code(400);
die();
}
}
public function handleHttpGet() {
if (isset($_GET['action'])) {
// request for controller action
// No controller actions for HTTP GET
} else {
// display login page
}
}
public function redirectToHome() {
header("Location: " + LoginController::HOME_URL);
die();
}
}
$model = new LoginModel();
$controller = new LoginController($model);
$view = new LoginView($controller, $model);
if (isset($_SESSION['username'])) {
$controller->redirectToHome();
}
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$controller->handleHttpPost();
} else if ($_SERVER['REQUEST_METHOD'] === 'GET') {
$controller->handleHttpGet();
}
?>
<html>
<body>
<?php if ($model->loginSuccess) { ?>
<h1>Login Successful, Redirecting...</h1>
<p><?= $model->message; ?></p>
<?php
} else { ?>
<form action="login.php?action=login" method="POST">
Username: <br />
<?php echo $view->getUsernameField(); ?> <br/><br/>
Password: <br />
<?php echo $view->getPasswordField(); ?><br/><br/>
<input type="submit" value="Log In"/>
</form>
<p><?= $model->message; ?></p>
<?php
}?>
</body>
</html>
更新:已解决。感谢@RiggsFolly指出。
好吧,我弄错了$model
。
public function login() {
....
$model->username = $username; //referenced the wrong variable
$this->model->username = $username //should have done this.
}
另外,谢谢@Fred -ii - (抱歉,我离开了你)
public function login() {
....
header("Refresh: 3; URL=" + LoginController::HOME_URL); //not the right way to concat
header("Refresh: 3; URL=" . LoginController::HOME_URL); //should have been this.
}
答案 0 :(得分:2)
只是一个简单的陈述
代表because $model was passed by value
我们在$model
中有一个对象并将其传递给构造函数
$controller = new LoginController($model);
它将作为参考
$controller->model = $model
。
现在我们在控制器中有一个模型的参考。
如果您知道(如果可能,请允许,请说“是”):unset($controller->model);
你没有杀死$model
个实例,你刚刚删除了之前设置的$model
引用。
但现在反过来了:
#create an object
$model = new stdClass();
#create the holder
$b=new stdClass();
#bind the first obj
$b->model=$model;
#unset the first object
$model=null;
unset($model);
#oooh, what it is still there
print_r($b->model);
这里我们没有真正的unset($model)
,因为php知道稍后会使用该实例。所以php继续杀死$model
和真实对象之间的引用,而不是$b->model
和真实对象之间的引用。
在某种程度上,引用已经从一个ref指针移动到下一个。
关于
的最后一件事默认情况下,函数参数按值传递(因此,如果函数中的参数值发生更改,则不会在函数外部更改)。
来自php documentaion。
在这里写passed by value
时,它意味着它将如何运作。
但在实际过程中,它会在被操纵的那一刻复制。
所以它是passed by ref
,但就像passed by value
一样,只有对象在clone
之前始终是引用。
在这个答案中保留最重要的信息:
首先,标题(“Refresh:3; URL =”+ LoginController :: HOME_URL); 你试图用一个+连接,在PHP中它是一个点 需要使用。你似乎是来自C背景,因此 错误。
感谢Fred -iii -