【问题标题】:PDO interaction shared among classes类之间共享的 PDO 交互
【发布时间】:2019-10-03 12:48:11
【问题描述】:

我的每个数据库表都有一个类,例如events 表的行存储在Event 类中。对于我编写的每个类,有几个方法完全相同,只是变量或列名不同。例如:

玩家类update()

public function update() {
    $conn = new PDO( db_host, db_user, db_pw );
    $sql = "UPDATE players SET name=:name, picture=:picture, position=:position, num=:num, team=:team, description=:description WHERE id = :id";
    $st = $conn->prepare ( $sql );
    $st->bindValue( ":name", $this->name, PDO::PARAM_STR );
    $st->bindValue( ":picture", $this->picture, PDO::PARAM_STR );
    $st->bindValue( ":position", $this->position, PDO::PARAM_STR );
    $st->bindValue( ":num", $this->num, PDO::PARAM_INT );
    $st->bindValue( ":team", $this->team, PDO::PARAM_INT );
    $st->bindValue( ":description", $this->description, PDO::PARAM_STR);
    $st->bindValue( ":id", $this->id, PDO::PARAM_INT );
    $st->execute();
    $conn = null;
}

团队班update()

public function update() {
    $conn = new PDO( db_host, db_user, db_pw );
    $sql = "UPDATE teams SET name=:name, sname=:sname, logo=:logo, sport=:sport WHERE id = :id";
    $st = $conn->prepare ( $sql );
    $st->bindValue( ":name", $this->name, PDO::PARAM_STR );
    $st->bindValue( ":sname", $this->sname, PDO::PARAM_STR );
    $st->bindValue( ":logo", $this->logo, PDO::PARAM_STR );
    $st->bindValue( ":sport", $this->sport, PDO::PARAM_STR );
    $st->bindValue( ":id", $this->id, PDO::PARAM_INT );
    $st->execute();
    $conn = null;
 }

正如您所见,方法的要点是相同的,只是将不同的变量绑定到语句(更多方法就是这种情况)。有没有一种简单的方法可以让每个类都具有相同的基本update()insert()delete()... 方法但具有各自的变量?我曾想过从超类继承基本行为,但从 OO 的角度来看没有多大意义(而且我不相信有任何方式可以说“对于在这个类中声明的每个公共变量”)但我不是确定是否有一种方法可以使用合成(或者根本没有,真的)来做到这一点。

【问题讨论】:

  • 您实际上需要一个用于该 tbh 的查询构建器。 findAllfindBy(property) 等一些方法可能有效。但是 CRUD 不能工作,因为没有表可以保证具有相同的列。话虽如此,您可以从适当的 ORM 中受益,例如 DoctrinePropel 或您喜欢的任何其他 ORM。
  • 我希望有一种更简单/更原生的方式来做到这一点:(谢谢你的回答
  • 使用合适的 ORM 非常简单。更不用说您受益于数百万人使用的成熟且经过测试的软件包。这没有什么问题。诚然,设置需要一点时间,但它会及时补偿。
  • 我会将这些类命名为“PlayerRepository”、“TeamRepository”,而不要理会它们。这还不错,您可以 100% 控制正在发生的事情。

标签: php pdo


【解决方案1】:

是的,这是您所说的婴儿 ORM,它很容易实现。

首先,创建一个原型类,包含所有常用方法(create()、update()、find() 等)。

abstract class BaseActiveRecord
{
    protected $_db;
    protected $_table;
    protected $_primary = 'id';
    protected $_fields = [];

    public function __construct($db)
    {
        $this->_db = $db;
    }
    public function read($id)
    {
        $sql = "SELECT * FROM `$this->_table` WHERE `$this->_primary` = ?";
        $stmt = $this->_db->prepare($sql);
        $stmt->execute([$id]);
        $stmt->setFetchMode(PDO::FETCH_INTO, $this);
        $stmt->fetch();
    }
    public function update()
    {
        $data = [];
        $set = "";
        foreach($this->_fields as $key)
        {
            $set .= "`$key` = :$key,";
            $data[$key]  = $this->{$key};
        }
        $set = rtrim($set, ",");
        $data[$this->_primary] = $this->{$this->_primary};
        $where = "$this->_primary = :$this->_primary";
        $sql = "UPDATE {$this->_table} SET $set WHERE $where";
        $this->_db->prepare($sql)->execute($data);
    }
}

如您所见,有一些新变量:

  • $_table 保存特定类中使用的表名。
  • $_primary 包含将在find()update() 方法中使用的主键的名称,默认值为id
  • $_fields 是一个非常重要的属性,它应该包含这个类的所有“真实”属性的列表。它将用于create()update() 方法

然后只需创建实际的类,扩展您的原型类,例如 Team

class Team extends BaseActiveRecord
{
    protected $_table = "teams";
    protected $_fields = ['name', 'sname', 'logo', 'sport'];
}

如您所见,定义相当简单 - 在这里您必须定义表和字段名称才能使我们的自动化工作。现在!您所要做的就是简单地调用update() 方法!

include 'pdo.php';
$team = new Team($pdo);
$team->read(1); // get the record from the database
$user->name = "Boston Celtics";
$user->sname = "Celtics";
$user->update(); // save the updated record.

请注意,您永远不应该在每个方法内创建新的数据库连接。创建一次并传递给您的类的构造函数。这里是how to connect with PDO properly

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-06
    • 1970-01-01
    • 1970-01-01
    • 2017-05-04
    • 1970-01-01
    相关资源
    最近更新 更多