【问题标题】:Using PDO with other classes将 PDO 与其他类一起使用
【发布时间】:2013-08-10 15:37:30
【问题描述】:

我一直在强迫自己进入更多的 OOP。直到现在我都讨厌这一切。当我在另一个类中的 PDO 中使用一些简单的准备语句作为方法时,它永远不会起作用。我通过做显而易见的事情来解决它:将 PDO 对象全球化到方法中。它可以工作,并且可以满足我的要求-但是如果我有很多来自不同类的方法,请添加“global $db;”作为所有功能/方法的第一行,它似乎很乏味。有没有办法将 PDO 集成到所有类中?或者至少是每个类——而不是每一个血腥的方法?

这是一个非常简单的例子,说明当前的工作原理,但正如我所说的乏味:

<?php
 $db = new PDO("mysql:host=localhost;dbname=blaa;", "blaa", "blaa");
class test{

function show($col, $id){
    global $db;
    $result = $db->prepare("SELECT ".$col." FROM products WHERE id = :id");
    $result->execute(array("id"=>$id));
    $row = $result->fetch();
    echo $row[$col];
}
}

$show = new test();
$show->show("price", 1);
?>

..所以我可以在方法“show()”中使用我的 PDO,但如果我要添加另一个方法,我将不得不输入“global $db;”又进去了……

那么我如何不只用一种方法来全球化它,而是用所有类来全球化呢? 我尝试将 PDO 类继承到“测试”类中,但没有奏效;我尝试使用如下构造函数:

<?php
$db = new PDO("mysql:host=localhost;dbname=blaa;", "blaa", "blaa");
class test{
    public $db;
function __construct($db){
           $this->db = $db;
    }
function show($col, $id){
    $result = $db->prepare("SELECT ".$col." FROM products WHERE id = :id");
    $result->execute(array("id"=>$id));
    $row = $result->fetch();
    echo $row[$col];
}
}

$show = new test($db);
$show->show("price", 1);
?>

但这没有用..

任何帮助将不胜感激!

谢谢 -怀利

【问题讨论】:

  • 在第二种情况下,$db PDO 对象超出了类的范围。类的公共 $db 与 PDO 对象 $db = new PDO(...) 不同。在第二种情况下,您可能希望将测试作为 PDO 的扩展类。您还可以通过引用查看传递对象。
  • 你的 show 函数容易受到 SQL 注入的攻击
  • 如果使用准备好的语句,它如何容易受到 SQL 注入的攻击...?
  • @user2670722 您正在将 $col 值直接传递给您的查询语句,而无需任何类型的清理。
  • 他的意思可能是因为您已经将$col 直接放在SQL 中,而不是之后将其绑定到语句中。

标签: php oop pdo


【解决方案1】:
$this->db = $db;

表示您将$db 分配给$this-&gt;db,而不是相反!

所以,你必须在课堂上使用 $this->db,而不是 $db

$result = $this->db->prepare("SELECT ".$col." FROM products WHERE id = :id");

【讨论】:

  • 有效!非常感谢!
【解决方案2】:

“你的常识”是对的。但我想补充一点,您可以而且应该使用单例模式:创建一个类,其目的是维护与数据库的唯一连接。

class Database {
    private static $instance = null;

    private $pdo;
    private function __construct() {
        $this->pdo = new PDO("mysql:host=localhost;dbname=blaa;", "blaa", "blaa");
    }

    public static function get() {
        if(is_null(self::$instance))
            self::$instance = new Database();
        return self::$instance;
    }
}

然后,每次需要访问数据库时,不要将 PDO 对象存储为实例属性,而是使用:

$db = Database::get();

你的例子会变成:

class test {
    function __construct() {
        // You don't need this anymore, unless you have other things to do in the constructor
    }

    function show($col, $id) {
        $db = Database::get();
        $result = $db->prepare("SELECT ".$col." FROM products WHERE id = :id");
        $result->execute(array("id"=>$id));
        $row = $result->fetch();
        echo $row[$col];
    }
}

如果您不想在每个需要它的方法中调用Database::get,则可以改为在构造函数中调用一次。

class test {
    private $db;

    function __construct() {
        $this->db = Database::get();
    }

    function show($col, $id) {
        $result = $this->db->prepare("SELECT ".$col." FROM products WHERE id = :id");
        $result->execute(array("id"=>$id));
        $row = $result->fetch();
        echo $row[$col];
    }
}

【讨论】:

  • 也许你应该从现在开始澄清如何在每个方法中使用$db = Database::get(); 而不是重新实例化它
  • 哦,有道理! $db = Database::get();去其他班级?
  • 是的,但是我仍然看不出在每个方法中写入全局$db和写入$db = database:get()之间的区别,重用它是反模式,如果我有 50 种查询方法?
  • 再次编辑。 :) 有些事情你不能用构造函数中的调用来做(比如在代码中间透明地切换到另一个目标数据库),但如果你不需要它们,你可以这样为每个方法保存一行.
  • 非常感谢!明白了:)
猜你喜欢
  • 2013-01-07
  • 1970-01-01
  • 2012-05-26
  • 1970-01-01
  • 2021-07-26
  • 2017-07-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多