Какой лучший способ абстрагировать базу данных от PHP-приложения? - PullRequest
6 голосов
/ 15 апреля 2009

Мой вопрос заключается в том, как абстрагировать соединение с базой данных от уровня модели приложения? Основная задача заключается в том, чтобы иметь возможность легко переходить с разных типов баз данных. Возможно, вы начнете с простого файла, базы данных, разделенной запятыми. Затем вы хотите перейти к базе данных SQL. Затем вы решите, что реализация LDAP будет лучше. Как человек может легко планировать что-то подобное?

Для простого примера, скажем, у вас есть пользователь с именем, фамилией и адресом электронной почты. Очень простой PHP-класс, представляющий его, может выглядеть следующим образом (пожалуйста, не обращайте внимания на проблемы с общедоступными переменными экземпляра):

<?php

class User {
  public $first;
  public $last;
  public $email;
}

?>

Я часто видел, где люди имеют класс DAO, в который встроен SQL как таковой:

<?php

class UserDAO {
  public $id;
  public $fist;
  public $last;
  public $email;

  public function create( &$db ) {
    $sql = "INSERT INTO user VALUES( '$first', '$last', '$email' )";
    $db->query( $sql );
  }
}

?>

Моя проблема с такими стратегиями заключается в том, что когда вы хотите изменить свою базу данных, вы должны изменить каждый класс DAO: функции создания, обновления, загрузки, удаления, чтобы иметь дело с вашим новым типом базы данных. Даже если у вас есть программа для их автоматической генерации (которой я особенно не фанат), вам придется отредактировать эту программу, чтобы она теперь работала.

Что вы предлагаете, как с этим справиться?

Моя текущая идея - создать суперкласс для объектов DAO с собственными функциями создания, удаления, обновления и загрузки. Однако эти функции будут брать массивы атрибутов DAO и генерировать сам запрос. Таким образом, единственный SQL находится в классе SuperDAO, а не разбросан по нескольким классам. Тогда, если вы захотите изменить слой вашей базы данных, вам нужно будет только изменить способ, которым класс SuperDAO генерирует запросы. Преимущества? Недостатки? Предвидимые проблемы? Хорошо, плохо и безобразно?

Ответы [ 10 ]

8 голосов
/ 15 апреля 2009

Вы можете использовать различные среды, такие как PDO, PEAR :: MDB2 или Zend_Db, но, если честно, за 12 лет разработки PHP мне никогда не приходилось переходить с одного типа инфраструктуры хранения данных на другой.

Чрезвычайно редко можно даже перейти от чего-то похожего на Sqlite к MySQL. Если бы вы сделали больше, у вас все равно были бы гораздо большие проблемы.

7 голосов
/ 15 апреля 2009

Использование ORM обычно является предпочтительным способом абстрагирования базы данных. Неполный список реализаций PHP доступен в Wikipedia .

3 голосов
/ 05 июня 2016

Я предложил интересную концепцию, которая позволила бы разработчику создавать код, независимый от базы данных , но в отличие от ORM не жертвует производительностью :

  • простой в использовании (например, ORM)
  • db-agnostic: работает с SQL, NoSQL, файлами и т. Д.
  • всегда оптимизировать запросы, если поставщик позволяет (суб-выбор, уменьшение карты)

Результат - Agile Data - структура доступа к базе данных (подробное объяснение см. В видео).

Решение реальных задач с использованием кода, независимого от БД, и Agile Data

  1. Начните с описания бизнес-моделей .
  2. Создать драйвер персистентности $db (причудливое слово для подключения к БД), который может быть файлом CSV, SQL или LDAP.
  3. Ассоциируйте модель с $db и выражайте Action
  4. Выполнить Action

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

Пример кода

Мой следующий фрагмент кода решает довольно сложную проблему определения какова текущая общая задолженность всех наших VIP-клиентов . Схема:

enter image description here

Следующий код зависит от поставщика:

$clients = new Model_Client($db);
// Object representing all clients - DataSet

$clients -> addCondition('is_vip', true);
// Now DataSet is limited to VIP clients only

$vip_client_orders = $clients->refSet('Order');
// This DataSet will contain only orders placed by VIP clients

$vip_client_orders->addExpression('item_price')->set(function($model, $query){
    return $model->ref('item_id')->fieldQuery('price');
});
// Defines a new field for a model expressed through relation with Item

$vip_client_orders->addExpression('paid')
  ->set(function($model, $query){
    return $model->ref('Payment')->sum('amount');
});
// Defines another field as sum of related payments

$vip_client_orders->addExpression('due')->set(function($model, $query){
    return $query->expr('{item_price} * {qty} - {paid}');
});
// Defines third field for calculating due

$total_due_payment = $vip_client_orders->sum('due')->getOne();
// Defines and executes "sum" action on our expression across specified data-set

Результирующий запрос, если $db является SQL:

select sum(
  (select `price` from `item` where `item`.`id` = `order`.`item_id` )
  * `order`.`qty`
  - (select sum(`payment`.`amount`) `amount` 
     from `payment` where `payment`.`order_id` = `order`.`id` )
) `due` from `order` 
where `order`.`user_id` in (
  select `id` from `user` where `user`.`is_client` = 1 and `user`.`is_vip` = 1 
)

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

Я думаю, что мой подход - отличный способ абстрагирования базы данных, и я работаю над его реализацией под лицензией MIT:

https://github.com/atk4/data

2 голосов
/ 15 апреля 2009

Лучший способ - использовать библиотеку ORM (объектно-реляционное отображение). Их много для PHP. Я лично использовал и могу порекомендовать doctrine orm (я использовал его в сочетании с silex, который представляет собой минималистичный php framework).

Вот поток StackOverflow о PHP ORM, где вы можете найти несколько альтернатив, если хотите: Хорошая библиотека PHP ORM?

2 голосов
/ 15 апреля 2009

Вы должны заглянуть в библиотеку PDO.

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

PDO не обеспечивает абстракцию базы данных; он не переписывает SQL и не эмулирует отсутствующие функции. Вы должны использовать полноценный слой абстракции, если вам нужно это средство.

1 голос
/ 29 декабря 2013

На самом деле решение для темы "где реализовать логику доступа к данным?" не сложно. Все, что вам нужно помнить, это то, что код вашей модели должен быть отделен от кода доступа к данным.

Как:

Уровень модели с некоторой бизнес-логикой метод User :: name ()

class User 
{
  public $first;
  public $last;
  public $email;
  public function name ()
  {
      return $this->first." ".$this->last;
  }
}

Уровень доступа к данным:

class Link
{
    $this->connection;
    public function __construct ()
    {
        $this->connection = PDO_Some_Connect_Function();
    }
    public function query ($query)
    {
        PDO_Some_Query ($this->connection, $query);
    }

}

class Database
{
    public $link;
    public function __construct ()
    {
        $this->link = new Link();
    }
    public function query ($query)
    {
        $this->link->query ($query);
    }
}

class Users
{
    public $database;
    public function __construct (&$database)
    {
         $this->database = &$database;
    } 
    public save ($user)
    {
        $this->database->link->query ("INSERT INTO user VALUES( '$user->first', '$user->last', '$user->email' ))";
    }

Использование:

$database = new Database();

$users = new Users();

$users->save (new User());

В этом примере очевидно, что вы всегда можете изменить свой класс доступа к данным Link, который будет выполнять запросы на что угодно (это означает, что вы можете сохранять своих пользователей на любом сервере при изменении ссылки).

В то же время у вас есть чистый код уровня модели, который живет независимо и не знает, кто и где сохраняет свои объекты.

Кроме того, класс базы данных здесь кажется ненужным, но на самом деле он может породить прекрасные идеи, такие как сбор множества ссылок по одному экземпляру для множества соединений БД в одном проекте.

Также существует простейший и всемогущий фреймворк для одного файла, который называется db.php (http://dbphp.net)), который построен по шаблону, который я здесь описал, и даже автоматически создает таблицы с возможностью полного контроля над его стандартом Настройки поля / таблицы sql и синхронизировать структуру базы данных с вашей моделью каждый раз, когда вы хотите.

1 голос
/ 16 апреля 2009

Мне всегда нравилось использовать ADOdb. Из того, что я видел, похоже, что он способен переключаться между совершенно разными платформами.

http://adodb.sf.net

1 голос
/ 15 апреля 2009

Вообще говоря, если у вас возникнут проблемы с использованием базы данных, тогда ваше приложение выиграет от использования функций, характерных для «бренда» базы данных, и станет более надежным приложением для этого.

Очень редко можно переходить из одной системы баз данных в другую. Единственный раз, когда вы реально можете подумать, что эта функция заслуживает реализации, это если вы пишете какую-то слабосвязанную систему или среду, предназначенную для массового потребления (например, Zend Framework или Django).

1 голос
/ 15 апреля 2009

Теоретически звучит хорошо, но, по всей вероятности, ЯГНИ .

Было бы лучше использовать библиотеку SQL, такую ​​как PDO , и не беспокоиться о LDAP, пока не доберетесь до нее.

0 голосов
/ 23 августа 2010

Axon ORM автоматически обнаруживает изменения в вашей схеме без необходимости перестраивать код.

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