我有一个用PHP内置的上传类,它具有各种功能来检查文件并确保它符合正确的规范。但是,我有一个函数可以去除文件名并为其提供一个新名称,即数字。在此函数中,我包括我的连接包括以启动与数据库的连接。为了防止给两个文件提供相同的名称,我的数据库中有表,其中包含当前计数,该计数是指最后一个图像编号。当我上传图像时,它会从数据库中提取计数并向其中添加一个计数,并将该数字存储为图像的名称。然后,我通过再次查询数据库来使用新计数更新表。这工作正常,但是当我在另一个函数中查询数据库以输入文件的路径时,它告诉我我的连接变量没有声明。我已经发布了我的连接代码,包括下面以及我正在调用的两个函数。我很好奇我是否没有在正确的位置启动连接。我尝试释放结果并在调用函数后关闭连接,然后在另一个函数中再次打开连接以提交文件路径,但这似乎也不起作用。我知道有一条关于在任何时候打开一个连接的规则,但我认为您可以在该连接中多次查询数据库。
连接包括
// Create a database connection
$dbhost = "localhost";
$dbuser = "user";
$dbpass = "password";
$dbname = "new_db";
$connection = mysqli_connect($dbhost, $dbuser, $dbpass, $dbname);
// Test if connection occured.
if(mysqli_connect_errno()) {
die("Database connection failed: " .
mysqli_connect_error() .
" (" . mysqli_connect_errno() . ")"
);
}
第一个函数
//replaces the filename with an incremented number
public function trim_filename() {
require_once( 'includes/connection.php' );
$query = "SELECT * FROM image_count ";
$result = mysqli_query($connection, $query);
if (!$result) {
die("Database query failed. ");
}
$row = mysqli_fetch_assoc($result);
$count = 1 + $row["name"];
mysqli_free_result($result);
$query = "UPDATE image_count SET name = '{$count}' WHERE count = 1";
$result = mysqli_query($connection, $query);
if (!$result) {
die("Database query failed. ");
}
$file = $_FILES['image']['name'];
$file = explode(".", $file);
$file = end($file);
$file = $count . "." . $file;
$_FILES['image']['name'] = $file;
$this->final_check();
mysqli_free_result($result);
mysqli_close($connection);
}
第二个功能
public function database_query($in_path) {
$query = "INSERT INTO course (";
$query .= " course_name ";
$query .= ") VALUES (";
$query .= " '{$in_path}'";
$query .= ")";
$result = mysqli_query($connection, $query);
if (!$result) {
die("Database query failed. ");
}
mysqli_free_result($result);
mysqli_close($connection);
}
常见问题,特别是如果你以前有使用旧mysql_query()
API的经验,它依赖于从全局状态中提取的连接资源。 您需要在适当的范围内获取$connection
才能在函数中使用它。
处理此问题的最佳方法是根本不要在类内部执行require_once()
来建立连接。相反,请在类外部执行该操作,并将生成的 $connection
变量传递给类的 __construct()
方法。 然后将其存储在类的属性中,您可以在其中将其用作$this->connection
。 这称为依赖注入。
class ThisClass
{
// A public property for the connection
protected $connection;
// Modify your __construct() to accept the connection
public function __construct(/* existing params... , */ mysqli $connection)
{
// Whatever your constructor already does...
// Store the connection in a property
$this->connection = $connection;
}
// Then modify those two methods to use $this->connection
public function trim_filename() {
$query = "SELECT * FROM image_count ";
// Use $this->connection
$result = mysqli_query($this->connection, $query);
if (!$result) {
die("Database query failed. ");
}
// SNIP....
// Don't free/close the connection!
}
// Then modify those two methods to use $this->connection
public function database_query($in_path) {
$query = "INSERT INTO course (";
// SNIP...
// Use $this->connection
$result = mysqli_query($this->connection, $query);
if (!$result) {
die("Database query failed. ");
}
// Don't free/close the connection!
}
}
现在,要将类与连接依赖项一起使用:
// Done outside the class, defines $connection
require_once( 'includes/connection.php' );
// Then when you use the class
// give it the $connection as a parameter
$object = new ThisClass($connection);
$object->trim_filename();
没有关于随时打开一个连接的规则,但需要多个连接是罕见的,而且有些奇特。
一个不理想的选择:如果出于某种原因确实不想将连接存储在类属性中,则可以修改这两种方法以接受$connection
作为参数,例如
// Add a param to the functions that need it.
public function trim_filename($connection) {
// use $connection->query(...);
}
// Call outside the class as:
$object->trim_filename($connection);
你仍然在课外做require_once()
。但是,将其作为依赖项注入构造函数会更简洁,并为您提供了一条简单的路径来扩展需要访问数据库连接的类中的更多方法。
在需要它的方法中使用 global
关键字访问 $connection
变量是最不理想的方法,特别是如果您继续在其中一个类函数中建立它。 根据面向对象的原则,建立数据库连接不应该是类的责任。相反,如果类需要一个,则应将其从外部传递给对象。
你能在database_query函数中尝试"全局连接;"吗? 你也不应该关闭函数中的连接
public function database_query($in_path) {
global $connection;
$query = "INSERT INTO course (";
$query .= " course_name ";
$query .= ") VALUES (";
$query .= " '{$in_path}'";
$query .= ")";
$result = mysqli_query($connection, $query);
if (!$result) {
die("Database query failed. ");
}
mysqli_free_result($result);
mysqli_close($connection);
}
处理此类情况的最佳方法是将所有函数放在一个文件中,例如(例如:函数.php(,然后将连接.php文件包含在函数的顶部.php.使用全局变量在每个函数中获取连接对象
连接.php文件
// Create a database connection
$dbhost = "localhost";
$dbuser = "user";
$dbpass = "password";
$dbname = "new_db";
$connection = mysqli_connect($dbhost, $dbuser, $dbpass, $dbname);
// Test if connection occured.
if(mysqli_connect_errno()) {
die("Database connection failed: " .
mysqli_connect_error() .
" (" . mysqli_connect_errno() . ")"
);
}
函数.php文件
//inculing connnection.php file
require_once( 'includes/connection.php' );
//first funtion
public function trim_filename() {
globel $connection;
// code here
}
//second funtion
public database_query($in_path) {
globel $connection;
// code here
}