我正在尝试清理其中一个类中的代码,但它引发了一些问题。
我想做的是将类方法中的所有 SQL 查询放入方法可以根据需要引用的属性中。当 SQL 查询不依赖于任何变量时,这工作正常,但是当我尝试将变量合并到查询中时,它会抛出错误。
可能更容易显示代码来解释。
class Assignment {
//Properties
public $courseID;
public $userID;
public $date;
//SQL query as property
private $releaseAssignmentSQL = "UPDATE StudentCourses SET released = '1', dateReleased = '" . $this -> date . "' WHERE courseID = '".$this -> courseID."' AND userID = '".$this -> userID."'";
//Method
public function releaseAssignment(){
global $db;
$query = $db -> query($this -> releaseAssignmentSQL);
}
}
然后使用以下方法调用该方法:
$assignment = new Assignment();
$assignment -> courseID = $db -> escape_value($_POST['courseID']);
$assignment -> userID = $db -> escape_value($_POST['userID']);
$assignment -> date = date("Y-m-d H:i:s");
echo $assignment -> releaseAssignment();
我遇到的问题是,当我第一次加载页面(包括对此类的其他引用)时,它崩溃并出现以下错误:
Parse error: syntax error, unexpected '$this' (T_VARIABLE) in ... class.assignment.php on line 19
其中第 19 行是指上述$releaseAssignment
属性的声明
谁能解释为什么会发生这种情况?看起来好像不可能声明引用其他属性的新字符串属性,但我不敢相信这是真的 - 还是吗?
这一行是问题所在:
private $releaseAssignmentSQL = "UPDATE StudentCourses SET released = '1', dateReleased = '" . $this -> date . "' WHERE courseID = '".$this -> courseID."' AND userID = '".$this -> userID."'";
$this
变量引用当前实例。由于仍在声明属性,因此没有要引用的实例(因此没有$this
)。在类的生存期内可以为属性分配不同的值,因此这样的表达式不可能起作用。
要么对值进行硬编码(这可能不是你想要的),要么定义一个构造函数并在那里初始化私有属性:
public function __construct()
{
$this->releaseAssignmentSQL = "UPDATE StudentCourses SET released = '1', dateReleased = '" . $this -> date . "' WHERE courseID = '".$this -> courseID."' AND userID = '".$this -> userID."'";
}
除此之外,AFAIK,属性$date
,$courseID
和$userID
没有值(null
),这可能也不起作用。您真正想做的是初始化这些属性(在构造函数中或使用 setter),然后初始化字符串:
public function __construct($date, $course, $user)
{
$this->date = $date;
$this->userID = $user;
$this->courseID = $course;
$this->releaseAssignmentSQL = "UPDATE StudentCourses SET released = '1', dateReleased = '" . $this -> date . "' WHERE courseID = '".$this -> courseID."' AND userID = '".$this -> userID."'";
}
不过,由于属性在实例的生存期内可能会更改,因此连接它们的值可能不是您想要做的事情。我在这里要做的是定义一个带有占位符的常量,以及一个返回一个字符串的方法,其中填充了属性的值:
const REASSIGNMENT_QUERY = "UPDATE StudentCourses SET released = 1, dateReleased = '%s' WHERE courseID = %d AND userID = %d";
public function getQuery()
{
return sprintf(
self::REASSIGNMENT_QUERY,
$this->date,
$this->courseID,
$this->userID
);
}
这看起来已经好多了。但是在查询中使用变量时,学习如何使用预准备语句真的很值得......
附带说明:如果要编写 OO 代码,将类与 global
一起使用是最糟糕的事情。对象应该是独立的,永远不要依赖全局状态来完成它们的工作
解释为什么声明属性时没有$this
好吧,简单地说,当你声明一个类时,你只是在描述实例(实际对象)的样子。属性描述实例将保存哪些数据,方法描述实例可以执行的工作/操作类型。
当一个类需要访问它包含的数据,或者调用它自己的方法之一(私有/受保护的方法)时,你必须告诉PHP在哪里查找该数据。因为你在类里面,所以你告诉 PHP 查看当前对象:$this
.
阅读属性访问语句 ( $this->date
),如下所示:"从'this'实例中,获取'date'的值",或"在'this'中,查找'date',并给我它的值"。
就像我说的$this
指的是对象,类的实例。该对象的布局和功能由类定义,但实际数据由实例而不是类拥有。
因此,类声明不链接到实例。为什么?因为单个类可以无限次实例化。PHP 无法知道您在声明属性时指的是哪个$this
。
简而言之,这是一个类,您可以在以下位置使用$this
:
class Foo
{
private $declaration = 'This is part of the description, not an instance, no this';
public function __construct()
{
//__construct is called when a new instance is created,
//$this references our new instance
//what happens here only affects this one instance
$this->declaration = 'Not applicable anymore';
}
}//end of declaration
因此,您只能在方法中使用$this
,因为方法只有在实例存在时才会启动操作。 在方法之外$this
不起作用。曾。
如果您希望类声明设置将影响所有实例的数据,该怎么办?好吧,如果该数据是不可变的(即字符串),则声明一个常量:
class Foo
{
const THIS_CANNOT_CHANGE = 123;
public $instanceProperty = null;
public function __construct()
{
$this->instanceProperty = self::THIS_CANNOT_CHANGE;
}
}
PHP 也有 static
关键字,但鉴于您仍在学习,我不会深入探讨,因为static
往往会被滥用,尤其是那些仍在接受 OOP 概念的人。底线是,如果你用PHP编写类,并使用static
,退后一步。9/10次,这意味着你犯了一个错误,或者即将犯一个错误。
关键字$this
始终指向当前实例化的对象(对象上下文)。
您可以在实例化对象后访问$this
。
更改代码,如下所示:
class Assignment {
public $courseID;
public $userID;
public $date;
private $releaseAssignmentSQL;
public function __construct()
{
// setting other properties
// ....
$this->releaseAssignmentSQL = ($this->date && $this->courseID && $this->userID)? "UPDATE StudentCourses SET released = '1', dateReleased = '" . $this->date . "' WHERE courseID = '".$this->courseID."' AND userID = '".$this->userID."'" : "";
}
//Method
public function releaseAssignment(){
global $db;
$query = $db->query($this->releaseAssignmentSQL);
}
}
不能在 php 类中引用方法或函数之外的$this
private $releaseAssignmentSQL = "UPDATE StudentCourses SET released = '1', dateReleased = '" . $this -> date . "' WHERE courseID = '".$this -> courseID."' AND userID = '".$this -> userID."'";
尝试使用类中的方法构建 sql 查询:
public function makeQuery () {
$this->releaseAssignmentSQL = "UPDATE StudentCourses SET released = '1', dateReleased = '" . $this -> date . "' WHERE courseID = '".$this -> courseID."' AND userID = '".$this -> userID."'";
}
然后在__construct函数中调用它:
function __construct() {
$this->makeQuery();
}
或者,您可以在其他地方执行此操作,然后再获取查询。