Здравствуйте, на днях занялся интеграцией популярного PHP-ORM Doctrine с не менее популярным PHP-фрэймворком CodeIgniter и обнаружил, что официальный способ интеграции, озвученный в кукбуке Doctrine и на вики CodeIgniter вызывает у меня, по меньшей мере, негодование.
Почему? Потому что в инструкции предлагается:
Что в этом плохого? То, что при обновлении фрэймворка, нам из раза в раз придется лезть в файл index.php и вносить изменения. То, что в конфигурационных файлах не должно выполняться системных действий. А также то, что в итоге мы подключаем конфигурационный файл database.php через index.php, полностью игнорируя гибкие средства фрэймворка.
Я предлагаю на суд хабраюзеров свой способ подключения Doctrine к CodeIgniter, лишеннный вышеуказанных недостатков. Итак, начнем:
Всё. Теперь мы спокойно можем использовать Doctrine внутри контроллеров и вьюшек, относящихся к данному приложению.
Опробуем простенький пример приложения с применением нашего вновь прибывшего ORM =)
Надеюсь, кому-нибудь помог. Извиняюсь, что в личный блог, а не в «CodeIgniter» — не хватает кармы.
UPD: перенес в «CodeIgniter»
UPD2: в config/autoload.php обязательно надо выключить «database» из списка загружаемых библиотек
Почему? Потому что в инструкции предлагается:
- Изменять содержимое файла index.php;
- Использовать конфигурационный файл application/config/database.php для инициализации соединения и подключения CI.
Что в этом плохого? То, что при обновлении фрэймворка, нам из раза в раз придется лезть в файл index.php и вносить изменения. То, что в конфигурационных файлах не должно выполняться системных действий. А также то, что в итоге мы подключаем конфигурационный файл database.php через index.php, полностью игнорируя гибкие средства фрэймворка.
Я предлагаю на суд хабраюзеров свой способ подключения Doctrine к CodeIgniter, лишеннный вышеуказанных недостатков. Итак, начнем:
- Первым делом скачиваем последнюю версию Doctrine отсюда;
- Копируем из скачанного архива содержимое директории lib в директорию system/database/doctrine/;
- Я стараюсь всегда мыслить логично, поэтому, для подключения ORM библиотеки, мы используем механизм библиотек в CI. В директорию application/libraries мы помещаем файл doctrineORM.php со следующим кодом:
- <?php if (!defined('BASEPATH')) exit('No direct script access allowed');
- /**
- * Doctrine initialization class
- */
- class DoctrineORM
- {
- function __construct() {
- // Получаем конфиг базы данных
- require_once(APPPATH . 'config/database.php');
- // Создаем DSN из полученной инфы
- $db['default']['dsn'] = $db['default']['dbdriver'] .
- '://' . $db['default']['username'] .
- ':' . $db['default']['password'].
- '@' . $db['default']['hostname'] .
- '/' . $db['default']['database'];
- // Подключаем Doctrine.php
- require_once(BASEPATH . 'database/doctrine/Doctrine.php');
- // Устанавливаем autoloader
- spl_autoload_register(array('Doctrine', 'autoload'));
- // Инициализируем соединение
- Doctrine_Manager::connection($db['default']['dsn'], $db['default']['database']);
- // Устанавливаем тип загрузки моделей в "conservative/lazy"
- Doctrine_Manager::getInstance()->setAttribute('model_loading', 'conservative');
- // Загружаем модели в autoloader
- Doctrine::loadModels(APPPATH . 'models');
- }
- }
Этот файл будет отвечать за инициализацию Doctrine внутри нашего проекта. Получается своеобразный loader;
- В корень нашего application помещаем файлы doctrine и doctrine.php
doctrine:
- #!php
- <?php
- // Директории system и application относительно текущей
- $sys_folder = '../';
- $app_folder = '.';
- include('doctrine.php');
doctrine.php:
- <?php
- define('BASEPATH', str_replace('\\', '/', $sys_folder) . '/');
- define('APPPATH', str_replace('\\', '/', $app_folder) . '/');
- require_once(APPPATH . 'libraries/doctrineORM.php');
- new DoctrineORM();
- // Конфигурируем "Doctrine Cli"
- $config = array(
- 'data_fixtures_path' => APPPATH . '/fixtures',
- 'models_path' => APPPATH . '/models',
- 'migrations_path' => APPPATH . '/migrations',
- 'sql_path' => APPPATH . '/sql',
- 'yaml_schema_path' => APPPATH . '/schema'
- );
- $cli = new Doctrine_Cli($config);
- $cli->run($_SERVER['argv']);
Эти файлы будут отвечать за CLI интерфейс библиотеки Doctrine. Общаться с Doctrine мы сможем через консольную инструкцию «php doctrine», выполненную из директории application;
- Создать в директории application поддиректории:
- application/fixtures;
- application/migrations;
- application/schema;
- application/sql.
- Ввнести верные данные для соединения с СУБД в application/config/database.php. Это следует делать так же, как если бы вы работали с нативным ORM CodeIgniter;
- Занести библиотеку doctrineORM в список автозагружаемых библиотек в конфигурационном файле application/config/autoloader.php
Пример:
- $autoload['libraries'] = array('doctrineORM', 'session');
Всё. Теперь мы спокойно можем использовать Doctrine внутри контроллеров и вьюшек, относящихся к данному приложению.
Опробуем простенький пример приложения с применением нашего вновь прибывшего ORM =)
- Создадим в директории application/schema файл user.yml со следующей структурой:
- ---
- User:
- columns:
- id:
- primary: true
- autoincrement: true
- type: integer(4)
- username: string(255)
- password: string(255)
- relations:
- Groups: # Relation alias or class name
- class: Group # Class name. Optional if alias is the class name
- local: user_id # Local: User.id = UserGroup.user_id. Optional
- foreign: group_id # Foreign: Group.id = UserGroup.group_id. Optional
- refClass: UserGroup # xRefClass for relating Users to Groups
- foreignAlias: Users # Opposite relationship alias. Group hasMany Users
- Group:
- tableName: groups
- columns:
- id:
- primary: true
- autoincrement: true
- type: integer(4)
- name: string(255)
- UserGroup:
- columns:
- user_id:
- type: integer(4)
- primary: true
- group_id:
- type: integer(4)
- primary: true
- relations:
- User:
- local: user_id # Local key
- foreign: id # Foreign key
- onDelete: CASCADE # Database constraint
- Group:
- local: group_id
- foreign: id
- onDelete: CASCADE
- Откроем консоль (или командную строку) и перейдем в директорию нашего приложения (application);
- Выполнение следующей команды создаст модели в директории application/models на основе структуры user.yml
$ php doctrine generate-models-yaml<br>generate-models-yaml - Generated models successfully from YAML schema<br><br>* This source code was highlighted with Source Code Highlighter.
- Теперь можно создать немного фиктивных данных для вноса их в СУБД. Для этого создайте файл application/fixtures/users.yml
- ---
- User:
- jwage:
- username: jwage
- password: test
- Теперь запустите задание build-all-reload, чтобы очистить базу данных, создать модели и пересоздать структуру в базе
$ php doctrine build-all-reload<br>build-all-reload - Are you sure you wish to drop your databases? (y/n)<br>y<br><br>* This source code was highlighted with Source Code Highlighter.
- Теперь можно использовать Doctrine для получения/записи данных напрямую из нашего контроллера. В контроллер welcome, метод index() добавьте следующий код и откройте
главную страницу проекта в браузере
- $user = new User();
- $user->username = 'zYne-';
- $user->setPassword('password');
- $user->save();
- $userTable = Doctrine::getTable('User');
- $user = $userTable->findOneByUsername('zYne-');
- echo $user->username; // prints 'zYne-'
Надеюсь, кому-нибудь помог. Извиняюсь, что в личный блог, а не в «CodeIgniter» — не хватает кармы.
UPD: перенес в «CodeIgniter»
UPD2: в config/autoload.php обязательно надо выключить «database» из списка загружаемых библиотек