Php 在多个类实例中使用mySQL准备语句

Php 在多个类实例中使用mySQL准备语句,php,oop,mysqli,prepared-statement,Php,Oop,Mysqli,Prepared Statement,我试图理解如何最好地利用mysqli编写的语句,而且我对面向对象的PHP也相当陌生 我知道,准备一条语句并多次执行它比简单地重复同一个查询要高效得多 下面的类通过主键获取声音对象。如果我需要在同一个脚本中有多个此类实例,那么我会从一个预先准备好的语句中获益吗 这是否适合作为存储过程的候选对象 class sound { public $id; public $name; public $musickey; public function __construct(

我试图理解如何最好地利用mysqli编写的语句,而且我对面向对象的PHP也相当陌生

我知道,准备一条语句并多次执行它比简单地重复同一个查询要高效得多

下面的类通过主键获取声音对象。如果我需要在同一个脚本中有多个此类实例,那么我会从一个预先准备好的语句中获益吗

这是否适合作为存储过程的候选对象

class sound {
    public $id;
    public $name;
    public $musickey;

    public function __construct($id) {
        $this->id = $id;
        $sqli = new mysqli();
        if($stmt = $con->prepare("SELECT name, musickey FROM sounds WHERE id = ?")) {
        $stmt->bind_param("i", $this->id);
        $stmt->execute();
        $stmt->bind_result($name, $musickey);
}
我希望我的问题不是重复的。我一直在试图找到关于这个话题的一些东西,但有时形成正确的问题和找到答案一样困难

我知道,准备一条语句并多次执行它比简单地重复同一个查询要高效得多

对。因为服务器端准备语句(mysqli使用的语句)只在后续执行时将绑定参数发送到数据库,而不是整个查询。此外,数据库服务器不必重新分析查询,但可以重用准备好的查询。因此,这会对检索数据产生影响。所以从理论上讲,这更有效

在实践中,不要期望有那么大的差异。这当然取决于您打算调用的查询的数量和复杂性,从而产生显著的差异。如有疑问,请选择基准

它还具有以下附加好处:

下面的类通过主键获取声音对象。如果我需要在同一个脚本中有多个此类实例,那么我会从一个预先准备好的语句中获益吗

不会。因为每次创建新实例准备语句时,mysqli都会向服务器发出查询。除了执行调用之外。所以你什么都没赢。如果只使用以下内容,则会更简单

$query = sprintf('SELECT name, musickey FROM sounds WHERE id = %d', $id);
然后,如果确实希望每个ID有一个实例,则将其作为整个查询执行

如果要使用准备好的语句执行此操作,则只需要准备一次但可以多次传递ID的一个实例

这是否适合作为存储过程的候选对象

class sound {
    public $id;
    public $name;
    public $musickey;

    public function __construct($id) {
        $this->id = $id;
        $sqli = new mysqli();
        if($stmt = $con->prepare("SELECT name, musickey FROM sounds WHERE id = ?")) {
        $stmt->bind_param("i", $this->id);
        $stmt->execute();
        $stmt->bind_result($name, $musickey);
}
如果将应用程序逻辑放入存储过程,则会降低应用程序的可移植性。如果要在某一时刻更改数据库系统,则需要重新创建存储过程。这取决于你做出明智的选择。如果您不需要更改数据库系统,那么它可能是可行的。我更喜欢将逻辑保存在应用程序中

我对面向对象的PHP也很陌生

(和复杂性)来自客户。所以在那里拥有公共财产不是最好的主意。此外,构造函数应该只将对象置于有效状态。由于准备执行查询,所以您希望将其推迟到需要时

尽管如此,考虑一下

interface FindById
{
    public function findById($id);
}

class SoundFinder implements FindById
{
    private $mysqli;
    private $statement;
    private $query = "SELECT name, musickey FROM sounds WHERE id = ?";

    public function __construct(mysqli $mysqli) 
    {
        $this->mysqli = $mysqli;
    }

    private function prepare()
    {
        $this->statement = $mysqli->prepare($this->query)
    }

    public function findById($id)
    {
        if (!$this->statement) {
            $this->prepare();
        }
        $this->statement->bind_param("i", $this->id);
        $this->statement->execute();
        $this->statement->bind_result($name, $musickey);
        $this->statement->free_result();
        return array($name, $musickey);
    }
}
然后你可以这样使用它:

$connection = new mysqli(/* your connection data */);
$soundFnder = new SoundFinder($connection);
$sound42 = $soundFinder->findById(42);
$sound314 = $soundFinder->findById(314);
比简单地重复同一个查询要高效得多

你理解错了。
不知道是谁告诉你的,但根本没有“更多”了。
这种差异几乎不明显,而且往往不值得如此混乱。特别是在这种简单的主键查找的情况下

我会从事先准备好的声明中获益吗

我对此表示怀疑


如果这样一个地方曾经成为瓶颈(请注意,是进行任何优化的唯一原因),那么最好选择一个查询中的所有数据

我知道我遗漏了一些非常基本的东西。我没有想过创建然后重用这个类的一个实例。很好的解释。谢谢。我不是想说死线程,但是在prepare函数中,它应该是$this->mysqli->prepare()??如果我确定我会编辑这篇文章