致命错误:在非对象上调用成员函数prepare()

时间:2009-11-27 07:47:33

标签: php mysql file loops file-io

我们有一个文档管理应用程序。我在mysql DB中加载了5000个图像文件。在客户端删除文件夹时需要删除它们。

使用以下代码

public function delete($dbh){

    $sql = "DELETE FROM fileTable WHERE FID=:fid;
            DELETE FROM file_blobTable WHERE FID=:fid";
    $stmt = $dbh -> prepare($sql);
    $stmt -> bindParam(":fid", $this->fid, PDO::PARAM_INT);
    $this -> fdid = -1; //
    if ($stmt -> execute()) {
        return 0;
    }
    return 1;
}

以这种方式循环调用上述函数,

// Loop through the folder and delete all the files it contains.

foreach ($files as $fileID) {
     // Get DB handle
     $dbh1 = DB::getWriteDB();

      $f = new File($fileID);
      $f -> delete($dbh1);
}

如果数据库中的图像数量小于500,则删除时会很有效。 如果更多,我遇到了可怕的,

  

“致命错误:在非对象上调用成员函数prepare()”。

2 个答案:

答案 0 :(得分:2)

为每次调用function delete生成预准备语句不仅效率低下,而且可能是导致错误的原因。您只需准备一次查询,这是它们存在的两个主要原因之一。您可以使用静态变量:

public function delete($dbh) {
    static $sql = "DELETE FROM fileTable WHERE FID=:fid;
        DELETE FROM file_blobTable WHERE FID=:fid";
    static $stmt = $dbh -> prepare($sql);

或者,既然您仍在使用对象,请使用类变量:

static protected function getDeleteQuery($dbh) {
    static $sql = "DELETE FROM fileTable WHERE FID=:fid;
        DELETE FROM file_blobTable WHERE FID=:fid";
    if (is_null(self::$queries['delete'])) {
        self::$queries['delete'] = $dbh->prepare($sql);
    }
    return self::$queries['delete'];
}
public function delete($dbh) {
    $stmt = self::getDeleteQuery($dbh);
    ...

答案 1 :(得分:1)

作为outis'解决方案的替代方案,如果您像我一样,希望避免使用静态函数和变量,则可以重新设计类以仅准备语句一次,并允许您在多个文件上使用一个实例。

class FileManager
{
    private $db_link;
    private $delete_stmt;
    private $file_id;

    public function __construct($db_link, $file_id=null)
    {
        $this->db_link = $db_link;
        $this->file_id = $file_id;
    }

    public function setFileID($file_id)
    {
        $this->file_id = $file_id;
    }

    public function delete()
    {
        if(!$this->delete_stmt)
        {
            $sql = "DELETE FROM fileTable WHERE FID=:fid;
                           DELETE FROM file_blobTable WHERE FID=:fid";
            $this->delete_stmt = $this->db_link->prepare($sql);
        }

        $this->delete_stmt->bindParam(":fid", $this->file_id, PDO::PARAM_INT);
        if ($this->delete_stmt->execute()) {
            return true;
        }
        return false;
    }
}

您可以这样使用:

$file = new FileManager($dbh);
foreach($files as $file_id)
{
    $file->setFileID($file_id);
    $file->delete();
}
$file = null;