Intereting Posts
проблема с несколькими curl и simplehtmldom, захват только заголовка? MYSQL: агрегирование заказов в диапазоне дат с нулевыми значениями для count Как заставить CodeIgniter принимать URL-адрес строки запроса? PHP Crypt () Сравнение двух зашифрованных строк как OpenID различается между разными входами на той же конечной точке OpenID Новое для входа и сеансов PHP; Это достаточно безопасно? Цикл через двумерный массив Неизвестный модификатор '(' при использовании preg_match () с выражением REGEX SMS и PHP … и Google Voice? Выделить текущую страницу на DYnamic Navigation PHP PHP продолжает вставку при обновлении Динамически заполненный выпадающий список; Ошибка возврата $ _POST не получить ошибку Исключение несоответствия токена в Verify csrf token в laravel 5.5 Внесите текущий объект ($ this) в класс потомков Как получить ссылочный сайт, с которого пользователь перешел в arive на моем сайте с помощью PHP?

PHP – лучший способ загрузить объект Database из Model, но иметь только один экземпляр?

Это моя проблема, у меня есть крошечная инфраструктура PHP MVC, которую я построил. Теперь, когда Im in Controller, я должен иметь возможность загрузить модель. У меня есть модели, называемые таблицами базы данных, такими как Users.php, Pages.php и т. Д.

Все контроллеры расширяют BaseController, и все модели расширяют BaseModel, таким образом, я могу использовать некоторые методы для всех контроллеров. Как и любой контроллер, я могу использовать метод loadModel следующим образом:

$usersModel = $this->loadModel("Users"); 

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

Чтобы получить подключение к базе данных из моих моделей, у baseModel есть метод loadDatabase (), и я использую его следующим образом:

 $database = $this->loadDatabase(); 

Это вернет класс, который является тонким слоем вокруг PDO, поэтому оттуда я могу использовать что-то вроде этого:

 $data = $database->fetchAssoc("SELECT * FROM users WHERE name = ?", array("someone")); 

Вот как я могу вернуть некоторые данные из модели в контроллер.

Таким образом, контроллер может загружать модель, а затем вызывать методы на этой модели, которые возвращают некоторые данные или обновляют или удаляют и т. Д.

Теперь контроллер может загружать более одной модели. И каждая модель должна загружать базу данных, и именно там она становится сложной. Мне нужно только одно соединение с базой данных.

Так выглядит метод loadDatabase:

  public function loadDatabase() { // Get database configuration require_once("Application/Config/Database.php"); // Build configuration the way Database Object expects it $dns = "{$db_config['db_driver']}:host={$db_config['db_host']};dbname={$db_config['db_name']}"; $username = $db_config['db_user']; $password = $db_config['db_pass']; $options = $db_config['db_options']; // Return new Database object return new \Core\Database\Database($dns, $username, $password, $options); } 

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

Теперь я застрял, и я не знаю, правильно ли это загрузить базу данных из модели? Как мне настроить это, как мне загрузить базу данных изнутри модели, так что всегда есть только один экземпляр объекта базы данных. Beacuse, если я сделаю что-то вроде этого от контроллера:

 $users = $this->loadModel("Users"); $pages = $this->loadModel("Pages"); $users->doSomethingThatNeedsDatabase(); $users->doSomethingThatNeedsDatabase(); $pages->doSomethingThatNeedsDatabase(); 

Я бы создал 3 объекта базы данных 🙁

Поэтому мой вопрос заключается в том, как мне загружать базу данных из моделей и как должен выглядеть этот метод в BaseModel? Что делать, если я хотел бы использовать 2 базы данных, у меня возникнут некоторые большие проблемы с этой настройкой. Как я могу добиться этого без использования одноэлементного шаблона?

На данный момент у меня также есть что-то вроде этого:

 public function getDatabase() { $reg = \Core\Registry\Registry::getInstance(); $db = $reg->getObject("database"); if(!isset($db)) { require_once("Application/Config/Database.php"); $dns = "{$db_config['db_driver']}:host={$db_config['db_host']};dbname={$db_config['db_name']}"; $username = $db_config['db_user']; $password = $db_config['db_pass']; $options = $db_config['db_options']; $db = new \Core\Database\Database($dns, $username, $password, $options); $reg->setObject('database', $db); } return $reg->getObject('database'); } 

Это шаблон реестра, в котором я мог бы хранить общие объекты. Поэтому, когда модель запрашивает соединение с БД, я могу проверить, находится ли класс DB в реестре, и вернуть его, если бы я не начал и не возвращался … Самое запутанное, что мне нужно загрузить конфигурационный массив …

Итак, каков наилучший способ загрузки базы данных из моделей?

Спасибо за чтение, это был очень длинный вопрос, но это меня так беспокоит, я надеюсь, что кто-то может помочь мне с этим … Спасибо!

Вы пойдете не так, как решить это.

Вместо того, чтобы каждый раз вручную создавать новую «Модель», а затем настраивать ее, вы должны создать структуру, которая сделает это для вас (чрезвычайно упрощенная версия):

 class ModelFactory { protected $connection = null; // --- snip -- public function __construct( $connection ) { $this->connection = $connection; } // --- snip -- public function buildMapper( $name ) { $instance = new {$name}( $this->connection ); return $instance; } // --- snip -- } 

Этот класс, который вы использовали бы в файле index.php или bootstrap.php или любом другом файле, который вы используете в качестве точки входа для вашего приложения:

 // at the bootstrap level $modelFactory = new ModelFactory( new PDO(...) ); // i am assuming that you could get $controllerName // and $action from routing mechanism $controller = new {$controllerName}( $modelFactory ); $controller->{$action}(); 

Основная проблема, с которой вы столкнулись, на самом деле вызвана непониманием модели. В правильном MVC Model является слоем, а не конкретным классом. Модельный слой состоит из множества классов / экземпляров с двумя основными обязанностями:

  • бизнес-логика домена
  • доступ к данным и их хранение

Экземпляры в первой группе обычно называются объектами домена или бизнес-объектами (вроде ситуации с выродками и кретинками ). Они касаются валидаций, вычислений, разных условий, но не имеют понятия, как и где хранится информация. Он не изменяет способ создания счета-фактуры , независимо от того, поступают ли данные от SQL, удаленного REST API или снимок экрана документа MS Word.

Другая группа состоит в основном из Data Mappers . Они хранят и извлекают информацию из объектов домена. Обычно это будет ваш SQL. Но карты не всегда сопоставляются непосредственно с схемой БД. В классической структуре «многие-ко-многим» у вас могут быть 1 или 2 или 3 устройства, обслуживающие хранилище. Mappers обычно по одному на каждый объект домена .. но даже это необязательно.

В контроллере все будет выглядеть примерно так.

 public function actionFooBar() { $mapper = $this->modelFactory->buildMapper( 'Book' ); $book = $this->modelFactory->buildObject( 'Book' ); $patron = $this->modelFactory->buildObject( 'Patron' ); $book->setTitle('Neuromancer'); $mapper->fetch( $book ); $patron->setId( $_GET['uid']); if ( $book->isAvailable() ) { $book->lendTo( $user ); } $mapper->store( $book ); } 

Может быть, это даст вам некоторые указания относительно направления, в котором это можно сделать.

Некоторые дополнительные видеоматериалы:

  • Расширенные шаблоны OO ( слайды )
  • Глобальное государство и синглтоны
  • Не смотрите на вещи!

Лучший способ для этих моделей использовать шаблон инъекции зависимостей.

 public function loadModel() { $db = $this->loadDatabase(); $model = new Model(); $model->setDatabase($db); return $model; } 

где loadDatabase() должен после инициализации и после возврата простого экземпляра соединения с базой данных.

Попробуй это:

 class Registry { /** @return Registry */ public static function getInstance() {} public function getObject($key) {} public function setObject($key, $value) {} /** @return bool */ public function isObjectExists($key) {} } class Db { const DB_ONE = 'db_one'; const DB_TWO = 'db_two'; protected static $_config = array( self::DB_ONE => array(), self::DB_TWO => array(), ); public static function getConnection($dbName) {} } abstract class BaseModel { abstract protected function _getDbName(); protected function _getConnection() { $dbName = $this->_getDbName(); if (!Registry::getInstance()->isObjectExists($dbName)) { Registry::getInstance()->setObject($dbName, Db::getConnection($dbName)); } return Registry::getInstance()->getObject($dbName); } } class UserModel extends BaseModel { protected function _getDbName() { return Db::DB_ONE; } } class PostModel extends BaseModel { protected function _getDbName() { return Db::DB_TWO; } } 

Удачи!