PHP Рекомендовать способ инициирования соединения с базой данных из экземпляра класса

0

У меня есть следующие классы в PHP:

class Database {
    ...
}

class Product {
    public function __construct() {
        ...
    }
}

В настоящее время я думаю о наличии глобального экземпляра класса базы данных, в котором в методе __construct класса Product я проверил бы, был ли объект инициализирован следующим образом:

class Product {
    public function __construct() {
         if (!isset($db)) {
            throw new Exception ('Database object not initialized.');
        }
        ...
    }
}

Это хорошая реализация? Если нет, что вы рекомендуете?

  • 0
    @tadman Вы бы порекомендовали использовать ORM для разработки обширного веб-приложения?
  • 0
    Предложите больше изучить, а затем, если нужно, задать более конкретный вопрос. Вот хороший ресурс: stackoverflow.com/questions/4595964/…
Показать ещё 1 комментарий
Теги:
database
class
oop

1 ответ

1
Лучший ответ

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

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

class Product {
    private $pdo = null;
    // other product properties here

    public function __construct() {
        // get db
        try {
            // set PDO object reference on this object
            $this->pdo =  PDOSingleton::getInstance();
        } catch (Exception $e) {
            error_log('Unable to get PDO instance. Error was: ' .
                $e->getMessage();
            // perhaps rethrow the exception to caller
            throw $e;
        }
        // query DB to get user record
    }

    // other class methods
}

// example usage
$product = new Product(1);

При использовании инъекции зависимостей это может выглядеть следующим образом:

class Product {
    private $pdo = null;
    // other product properties here

    // pass PDO object to the constructor. Enforce parameter typing
    public function __construct(PDO $pdo) {
        $this->pdo = $pdo;
        // query DB to get product record
    }

    // other class methods
}

// example usage
// instantiate PDO object. This probably happens near beginning
// of code execution and might be the single instance you pass around
// the application
try {
    $pdo = new PDO(...);
} catch (PDOException $e) {
    // perhaps log error and stop program execution
    // if this dependency is required
}

// somewhere later in code
$product = new Product($pdo);

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

  • отделяет класс потребления от деталей того, как создать экземпляр зависимости. Почему класс пользователя должен знать, какой синглтон использовать, чтобы получить зависимость от PDO? Все классы должны заботиться о том, как работать с зависимостью (то есть, какие свойства и методы у нее есть), а не как ее создать. Это более точно следует принципу единой ответственности, который обычно требуется в ООП, поскольку пользовательский класс должен иметь дело с созданием представления пользователя, а не с созданием его зависимостей.

  • устраняет дубликат кода между классами, которым требуется зависимость, поскольку вам не нужна вся обработка в каждом классе при создании/создании зависимостей. В примере кода я устраняю необходимость потенциально обрабатывать неудавшееся создание БД внутри конструктора, так как я знаю, что у меня уже есть действительный объект PDO, переданный как параметр (если я не получил один переданный, я бы получил недопустимое исключение аргумента).

  • 0
    Со ссылкой на вторую форму я хочу избежать передачи экземпляра базы данных каждый раз, когда я создаю экземпляр класса Product. Что если у меня есть экземпляр класса базы данных в заголовочном файле, который включен на все страницы и использую global $db; в конструкторе класса Product?

Ещё вопросы

Сообщество Overcoder
Наверх
Меню