Взаимодействие PDO распределяется среди классов - PullRequest
2 голосов
/ 03 октября 2019

У меня есть класс для каждой таблицы базы данных, например, 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() ..., но с соответствующими переменными? Я думал о наследовании базового поведения от суперкласса, но с точки зрения ОО не имеет особого смысла (и я не уверен, что есть какой-либо способ сказать «для каждой публичной переменной, объявленной в этом классе»), но я неконечно, если есть способ сделать это, используя композиции (или вообще, на самом деле).

1 Ответ

3 голосов
/ 03 октября 2019

Да, это детская ОРМ, о которой вы говорите, и ее довольно легко реализовать.

Прежде всего, создайте класс-прототип со всеми распространенными методами (create (), update (), find () и т. Д.).

abstract class BaseDataMapper
{
    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 BaseDataMapper
{
    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.

Обратите внимание, что вы никогда не должны создавать новое соединение с базой данных внутри каждого метода. Создайте его один раз и передайте в конструктор ваших классов. Вот как правильно подключиться к PDO .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...