Добрый день, %username%!
Сегодня я хочу рассказать вам, как легко и удобно написать свой небольшой веб фреймворк на языке программирования php, для использования в личных целях, в не больших проектах. Отчасти это удобно тогда, когда вам требуется создать не большую систему, или заказчик просто не разрешает использовать чужие технологии. Вам может показаться, что это довольно сложная вещь, но всё оказывается иначе. Подробнее под катом. По началу вы можете подумать, что написание технологий в веб фреймворке куда сложнее, чем использоваться стандартные «банальные» методы. К примеру, вместо использования удобного роутинга, использовать обычные запросы вида switch ($_GET[‘do’]), что очень не красиво и неудобно. Однако используя технологии MVC, нам будет гораздо легче писать приложения, а так же мы выиграем большое количество времени. Возможно, в следующей части статьи я напишу про создание модуля HMVC, но пока ограничимся этим. Так же нужно продумать структуру логики приложения, мы сделаем возможность подключать модули, а так же заменять основу логики в модулях, если нам это понадобится. Сделаем автоматическую загрузку классов, что очень удобно при наследовании контроллеров, а так же напишем несколько удобных классов (кэширование, обработчик ошибок, исключений и т.д.). Напишем модули для работы с основными частями сайта. Например, шаблонизатор – Smarty, реляционная база данных (ORM) – ActiveRecord. Всё это будет подключаться в модульной системе, и соответственно подгружаться только когда мы используем данную технологию, чтобы не совершать лишней нагрузки.
Так как я очень часто использую веб фреймворк Kohana, моя логика будет схожа с логикой данного фреймворка. Итак, начнём!
Создадим основной файл (index.php):
<?php define ('DS', DIRECTORY_SEPARATOR); define ('DEV_FRAMEWORK', __DIR__ . DS); // Путь к корню проекта define ('APPS', DEV_FRAMEWORK . 'apps' . DS); // Путь к приложениям define ('SYSTEM', DEV_FRAMEWORK . 'system' . DS); // Путь к системным файлам define ('EXT', '.php'); // Расширение файлов // Если файл bootstrap присутствует в папке приложений, подключаем его, иначе подключаем его из системной папки if (file_exists (APPS . 'bootstrap' . EXT)) { require APPS . 'bootstrap' . EXT; } else { require SYSTEM . 'bootstrap' . EXT; }</
Думаю с главным файлом пока можно закончить. Разберём файл bootstrap.php
<?php // Проверяем наличие константы (Подключаемся с главного файла или нет) if (!defined ('DEV_FRAMEWORK')) die ('Bad query!'); // Разрешаем использование пространства имён, затем регистрируем собственный загрузчик spl_autoload_extensions (EXT); spl_autoload_register (); spl_autoload_register (array ('SystemClassesDev', 'loader'));
Файлы с классами у нас будут находиться в модулях, в папке приложений, и в системной папке. Естественно сначала мы ищем данный модуль в модулях, если его не оказывается, ищем в папке с приложениями, и только затем в системной папке. Такая система позволит нам заменять логику работы скрипта, не прибегая к правке системных файлов. Рассмотрим файл system/classes/dev.php
<?php namespace SystemClasses; // Регистрируем пространство имён class Dev extends SystemClassesSystemDev {} // Наследуем системный класс Dev ?>
Возможно, вы не совсем поняли, зачем мы создали пустой класс и наследовали его от системного, дело в том, что это нам поможет создавать модули, с правкой логики проекта, не прибегая к правке системного класса. Проще говоря, мы просто создадим класс с таким же именем, внесём свои правки, и так же будем наследовать от системного класса, что очень удобно. Теперь рассмотрим системный файл dev.php (system/classes/system/dev.php):
<?php namespace SystemClassesSystem; // Регистрируем своё пространство имён class Dev { public static $modules = array (); // Создадим заранее массив для путей к модулям // Напишем простенькую функцию для добавления модулей. Как вы уже заметили, мы склеиваем массивы, что позволяет нам добавлять модули неоднократно и из разных мест. public static function addModules (array $modules) { return self::$modules = array_merge (self::$modules, $modules); } // Наш загрузчик public static function loader ($class) { $class = str_replace ('_', '/', $class); // Заменяем нижнее подчёркивание на слеш, таким образом, мы можем создавать папки и объявлять классы из любого дерева подпапок $class = strtolower ($class); // Переводим в нижний регистр, хотя это не обязательно // Сначала проходимся по модулям foreach (self::$modules as $module => $path) { $loader = self::__loader ($path . DS . 'classes' . DS . $class); if ($loader) return TRUE; } // Ищем в каталоге приложений $loader = self::__loader (APPS . 'classes' . DS . $class); if ($loader) return TRUE; // Окончательный вариант поиска, в системной директории $loader = self::__loader (SYSTEM . 'classes' . DS . $class); if ($loader) return TRUE; // Если ничего не найдено, возвращаем ошибку return trigger_error ('I can't find a class'); } private static function __loader ($class) { $class = $class . EXT; if (file_exists ($class)) if (require_once $class) return true; else return trigger_error ('I can't load class'); } } ?>
Мы уже можем подгружать наши классы автоматическим загрузчиком, «засовывать» классы в поддиректории. На данном этапе мы проделали «основную» работу фреймворка. В следующей части статьи мы создадим класс для обработки запросов (MVC), напишем простой пример модуля, и создадим несколько важных классов (обработка ошибок, кеширование и т.д.). С удовольствием выслушаю все недочёты. Спасибо за внимание!
Автор: unrealphp