Главная
Блог разработчиков phpBB
 
+ 17 предустановленных модов
+ SEO-оптимизация форума
+ авторизация через соц. сети
+ защита от спама

Прикручиваем ActiveRecord к сайту

Anna | 29.05.2014 | нет комментариев
Вступление

В процессе создания больше ли мене трудного сайта доводится задумываться об организации доступа к БД(базе данных). Если сайт создается на базе присутствующего фреймворка либо CMS, то там как правило имеются встроенные механизмы ORM (с англ. — Объектно-реляционное отображение, подробнее в вики). В данной статье я расскажу как дозволено прикрутить знаменитую и примитивную ORM систему ActiveRecord к собственному фреймворку.

Как работает ActiveRecord?

Компонент представляет из себя комплект основных классов, нужных для работы(Model,Config, ConnectionManager и др.), комплект адаптеров для подключения к определенной СУБД и точки входа, файла инициализации ActiveRecord.php тот, что содержит функцию автозагрузки классов наших моделей плана. Все классы определенны в пространстве имен ActiveRecord, наш план скорее каждого будет находится в ином пространстве либо в глобальном, следственно, Дабы при наследовании классов всякий раз не писать конструкции как бы extends \ActiveRecord\Model либо применять директиву use ActiveRecord, имеет толк сделать собственную обертку над ActiveRecord. Это также дозволит расширить вероятности нашей ORM не затрагивая компонент AR.

Выходит, Дабы воспользоваться всеми способами AR, нам нужно подключить файл инициализации ActiveRecord.php к плану, сделать для всякой таблицы в БД класс-модель и унаследовать его от \ActiveRecord\Model(скажем class Book extends \ActiveRecord\Model {} ), инициализировать подключение к БД с поддержкой конструкции:

$connections = array(
	'development' => 'mysql://invalid',
	'production' => 'mysql://test:test@127.0.0.1/test'
);

ActiveRecord\Config::initialize(function($cfg) use ($connections)
{
    $cfg->set_model_directory('.');
    $cfg->set_connections($connections);
}); 

Позже этого мы можем обращаться к нашим моделям и вызывать нужные способы, скажем Book::first() — вернет первую строку из таблицы определенной в модели Book.

Создание обертки AR

В плане допустимо понадобится обращение к БД из различных файлов, да и конфигурация традиционно храниться в отдельном файле, стандартных вероятностей AR не неизменно хватает и сама форма записи через пространство имен \ActiveRecord не дюже прекрасно. Эта тема тянет на несколько статьей, следственно тут я постараюсь высказать суть вопроса.

В простом случае нам понадобится сделать каждого 2 класса, один мы наследуем от \ActiveRecord\Model и иной будет основным, в котором мы будем проводить инициализацию и конфигурацию AR. Сотворим 2 файла-класса:

//Orm.php

class Orm
{
/**
         *  array $models_ Массив всех моделей плана, если какая либо модель не будет определенна в этом массиве, ее невозможно будет подключить
         * массив имеет следующие елементы [Имя модели]=>array('path'=>Путь к директории в которой храниться модель , 'namespace'=> Пространство имен в котором определен класс модели)
         */
        public $models_ = array();

        /**
         * Проверка минимиальной версии PHP, подключение нужных классов, регистрация автозагрузчика для моделей, инициализация конфигруации
         *
         * @param null $name
         */
        function __construct($name = null)
        {
            if (!defined('PHP_VERSION_ID') || PHP_VERSION_ID < 50300)
                die('PHP ActiveRecord requires PHP 5.3 or higher');

            define('PHP_ACTIVERECORD_VERSION_ID', '1.0');

            include_once 'lib/Singleton.php';
            include_once 'lib/Config.php';
            include_once 'lib/Utils.php';
            include_once 'lib/DateTime.php';
            include_once 'lib/Model.php';
            include_once 'lib/Table.php';
            include_once 'lib/ConnectionManager.php';
            include_once 'lib/Connection.php';
            include_once 'lib/SQLBuilder.php';
            include_once 'lib/Reflections.php';
            include_once 'lib/Inflector.php';
            include_once 'lib/CallBack.php';
            include_once 'lib/Exceptions.php';

            spl_autoload_register(__NAMESPACE__ . '\ActiveRecord::activerecord_autoload');
            Config::initialize(function ($cfg) {
                $cfg->set_connections(array(
                    'development' => Configuration::$dbtype . "://"
                    . Configuration::$db_user . ":" 
                    . Configuration::$db_password . "@" 
                    . Configuration::$db_host . "/"
                    . Configuration::$db_name
                ));
             /* Следует очевидно задать формат времени, он будет применяться в других классах AR, по умолчанию действует "Y-m-d H:i:s T" что добавляет
                 часовой пояс к строке, такой формат времени не дюже нравиться полями типа datetime в MySQL
             */
                $cfg->set_date_format("Y-m-d H:i:s");
            });

        }

        /**
         Установка нынешней директории с классами моделей, создание и возвращение объекта модели, если модель не обнаружена возвращается FALSE
         */
        public function getModel($model)
        {
            $config = Config::instance();

            if (array_key_exists($model, $this->models_)) {

                $config->set_model_directory($this->models_[$model]['path']);

if( $this->models_[$model]['namespace'] )
                $class = "\\" . $this->models_[$model]['namespace'] . "\\" . $model;
else
$class =  $model;
                return new $class;
            } else {
                return false;
            }
        }

        /**
         Автозагрузчик классов моделей, файл загружается из папки установленной в getModel()       
         $class_name Имя загружаемой модели, передается механически при применении оператора NEW
        в способе getModel()
         */
        public static function activerecord_autoload($class_name)
        {
            $root = Config::instance()->get_model_directory();

            $class_name = explode('\\', $class_name);
            $class_name = end($class_name);

            $file = $root . $class_name . ".php";

            if (file_exists($file))
                require $file;
        }
}

//Model.php

class Model extends \ActiveRecord\Model
{
        /* Имя таблицы в БД, данную переменную стоит переопределить в потомках, 
           если имя таблицы не совпадает с именем класса */
	static $table_name = 'simple_name';

	// Имя столбца с первичным ключем
	static $primary_key = 'id';

	// Имя соединения используемого при подключении
	static $connection = 'production';

	// Очевидное указание имени БД, при генерации SQL будет применяться конструкция -  db.table_name
	static $db = 'test';

      /*
       * Дозволено определить личные способы и свойства нужные для работы всех моделей
       */
}

От класса Model мы будем наследовать все модели существующих таблиц. Также представим, что каждая конфигурация приложения хранится в отдельном файле Configuration.php:

class Configuration{
/*.....*/

         /**
         *  $db_host Имя хоста на котором расположена БД
         */
        static $db_host = 'localhost';
        /**
         * $db_user Имя пользователя БД
         */
        static $db_user = 'root';
        /**
         *  $db_password Пароль пользователя БД
         */
        static $db_password = 'root';
        /**
         *  $db_name Имя базы данных
         */
        static $db_name = 'db_name';
        /**
         * $dbtype Тип подключения к БД
         */
        static $dbtype = 'mysql';

/*.....*/

}

В конструкторе класса Orm(данный код взят из ActiveRecord.php) подключаем нужные классы и регестрируем автозагрузчик, в самом конце инициализируем подключение к БД.

Специальное внимание стоит уделить формату времени, если его оставить по дефолту, то во время операций записей данных в БД поля типа datetime будут генерировать ошибку, т.к. AR генерирует строки в формате 2000-02-03 16:23:27 MSK, т.е. указывает индекс часового пояса. Изменить конфиг не довольно, не знаю отчего, но разработчики AR применяют в других классах формат даты и времени не из конфига, а очевидно указывают его в требуемых способах, следственно придется внести еще измения в следующие файлы:
/lib/Column.php способ cast

return new DateTime($value->format('Y-m-d H:i:s T')) 

на

return new DateTime($value->format(Config::instance()->get_date_format()))

Подобно в файлах /lib/Connection.php способы datetime_to_string() string_to_datetime(), и /lib/Model.php способ assign_attribute().

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

<?php

class Controller{
public static $ORM;

function __construct(){
$this->loadOrm();
}

function loadOrm(){
include 'Orm.php'

self::$ORM = new Orm();
self::_models = array('Book'=>array('path'=>'models', 'namespace'=>__NAMESPACE__));

}
}
new Controller;
?>

//в ином файле мы выводим скажем всех авторов имеющихся книг в БД
<?php

$model = Controller::$ORM ->getModel('Book');
$books = $model->all();

foreach($books as $book)
echo $book->author;

Безусловно, данный метод требует еще доработки, скажем дозволено сделать статические способы у Orm класса, тогда при запуске плана нам необходимо будет инициализировать его, а дальше всюду применять конструкцию как бы Orm::getModel(‘Имя модели’);
AR достаточно сильный и эластичный инструмент, в нем поддерживаются помимо стандартных операций CRUD, также и связи между таблицами(включая трудные связи через — through), имеется SQLBuilder для построения SQL запросов, валидация, конвертация и др.

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

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

Источник: programmingmaster.ru

Оставить комментарий
Форум phpBB, русская поддержка форума phpBB
Рейтинг@Mail.ru 2008 - 2017 © BB3x.ru - русская поддержка форума phpBB