Наша взаимовыгодная связь https://banwar.org/
У мережі велику кількість мінлива по створенню сайтів на готової CMS або фреймворку . Однак, працюючи фрілансером, часто зустрічаю сайти на самописних системах. Програмісти пишуть їх не від хорошого життя. Залежно від ступеня простоти (складності) проекту надмірно або навпаки недостатньо, застосування готової системи, і на її переробки йде більше часу, ніж на створення сайту з нуля. Наприклад, для сайту одностранічнік не потрібно важкої системи типу Joomla або фреймворка типу Yii , А у CMS типу Texpattern може не вистачити функціоналу. Плюс завдання, які ставить замовник, можуть бути вельми специфічними, і досить важко реалізованими на готовій системі.
Для прикладу можна взяти роботи з моделями в Yii . Йдеться про ActiveRecord. У Yii на офіційному сайті є відмінний мануал по створенню блогу . Якщо дотримуватися його, і робити все, як написано, то через пару годин вивчення, можна отримати повноцінний блог. З категоріями, мітками, користувачами і адміністративною панеллю.
Проблеми починаються тоді, коли ви спробуєте зробити щось, що не входить в мануал. Вивести під статтею схожі матеріали. Для цього, треба складати реляційну модель, набагато більш складну, ніж представлена в прикладах.
Як сказав один наш комік - "тут починається вестерн". Те, що в SQL б зайняло 3 рядки коду, в Active Record займе пару ночей читання мінлива, і експериментів. Тому що, на перший погляд тривіальне завдання, раптом викликає незрозумілий баг Yii, про який чули півтора людини і обидва китайці. Приклад не надумане, ті хто програмував на Yii використовуючи Actve Record підтримають.
Ця методологія роботи з даними дуже зручна, коли справа стосується однієї таблиці. Або навіть двох, коли зв'язок йде один до багатьох, по одному полю. Справжнє пекло починається, коли потрібно отримати дані з декількох таблиць.
У світі CMS теж далеко ходити не треба. При роботі над модулем Яндекс карт для Joomla потрібно було підключити в адмінці сайту javascript файл. Тижневе вивчення системи нічого не дало. Такого функціоналу в модулях просто немає. Треба сказати, що я викрутився використовуючи функціонал розширених полів підключив потрібний файл. Але те, скільки часу у мене на це пішло, незрівнянно з тим, якби система була побудована за моїми законами, і я знав, що і де в неї підключається.
Про це розповім в цій статті. Як написати php фреймворк з нуля. Наведемо основні техніки проектування MVC фреймворків на чистому php без використання сторонніх бібліотек.
Фреймворки пишуть такі ж програмісти, як і ви. Немає нічого неможливого. Написати для себе каркас на якому потім можна буде будувати конструкції нетипових сайтів.
Хочу застерегти вас, не варто писати свій велосипед , Без особливої потреби і досвіду. Більшу частину коду доведеться писати руками. Тут не буде готових модулів і розширень.
Однак і плюси теж є, система буде повністю під вашим контролем. Ніяких обмежень API і вимог системи. Тільки чистий vanilaPHP і нічого зайвого.
Залишимо лірику, приступимо нарешті до коду.
Вихідні матеріали до статті завантажити і подивитися на github. Статті по цій темі будуть публікуватися з тегом ideal , А останню версію фреймворку можна буде знайти на gihub
Точка входу
Будь-сайт, CMS або фреймворк починається з точки входу. Зазвичай це index.php в корені сайту. Але ми не будемо так робити. Щоб програміст, який працює з нашим фреймворком відразу розібрався, що всі дані йдуть через точку входу, назвемо файл main.php. Тоді буде зрозуміло - всі запити перенаправляються через .htaccess
код .htaccess
AddDefaultCharset utf-8 RewriteEngine on php_value upload_max_filesize 50M php_value post_max_size 50M php_value display_errors 1 DirectoryIndex main.php? Controller = index ErrorDocument 404 /main.php?controller=error RewriteRule ^ index.html $ main.php RewriteCond% {REQUEST_FILENAME}! -F RewriteCond% {REQUEST_FILENAME}! -d RewriteRule ^ (. *) $ main.php? route = $ 1 [L, QSA]
Перші 8 рядків - це допоміжні настройки, які стануть в нагоді для фреймворка в майбутньому. Ми встановили кодування utf-8 за замовчуванням, сайт буде працювати на ній. Включили модуль apache Rewrite, для того щоб перенаправити все не статичні запити на main.php. Це і роблять 3 останні рядки. Вся рядок запиту, яка йде після домену, буде передана в змінну $ _GET [ 'route']. Тобто запит http://sitename.ru/kolesa/perellli/?id=5 перетвориться в http://sitename.ru/main.php?route= kolesa / perellli / & id = 5
Подальші маніпуляції з розбором URL виробляються за допомогою PHP. Це поширений прийом, ви легко можете скористатися ним в інших системах. Так працює і Yii. Але наш фреймворк на відміну від Yii без .htaccess працювати не зможе.
Файл main.php не повинен робити багато, він лише визначить константи шляхів, підключить фреймворк і запустить додаток
<? Php define ( 'ROOT', dirname (__ FILE __). '/'); define ( 'IDEAL', dirname (__ FILE __). '/ ideal /'); define ( 'APP', dirname (__ FILE __). '/ application /'); include IDEAL.'framework.php '; app :: gi () -> start ();
структура
Тепер продумаємо структуру нашого фреймворка. Зручно, щоб його файли лежали в окремій папці. Зробимо таку структуру
- application - controllers - models - views - config.php - ideal - classes - framework.php - config.php .htaccess main.php
в папці ideal буде лежати наш ідеальний =) движок, а в папці application файли користувача.
в файлі framework.php визначимо Автозавантажувач класів, для того щоб не писати руками кожен раз include 'classname.php'; Я вже писав про цю техніку
<? Php function class_autoload ($ class_name) {$ file = IDEAL. 'Classes /'.$ class_name.'. Php '; if (file_exists ($ file) == false) return false; require_once ($ file); } Function controller_autoload ($ class_name) {$ file = APP. 'Controllers /'.$ class_name.'. Php '; if (file_exists ($ file) == false) return false; require_once ($ file); } Function model_autoload ($ class_name) {$ file = APP. 'Models /'.$ class_name.'. Php '; if (file_exists ($ file) == false) return false; require_once ($ file); } Spl_autoload_register ( 'class_autoload'); spl_autoload_register ( 'controller_autoload'); spl_autoload_register ( 'model_autoload');
в цьому файлі будуть ще й інші системні дії. Але поки вистачить і цього.
Автозавантажувач спрацьовують при використанні класу. Спершу шукається в папці фреймворка, потім в папці контролерів, потім в моделях. Відповідно називати контролер також, як і клас, або модуль можна.
Тепер опишемо клас App, він знаходиться в папці classes двіжка.Его метод start і буде запускати наш додаток.
<? Php class App extends Singleton {function start () {Router :: gi () -> parse (); $ Controller = app :: gi (Router :: gi () -> controller.'Controller '); $ Controller -> __ call ( 'action'.Router :: gi () -> action); }}
Клас успадковує абстрактний клас Singleton . Зручність у тому, що екземпляр будь-якого класу, який успадковує від Singleton, можна отримати з будь-якого місця програми через його метод gi () Наприклад, екземпляр нашого застосування можна отримати App :: gi (). Цей метод поверне єдиний екземпляр клас App. Один екземпляр може створити проблему, коли потрібно використовувати кілька баз даних. Тому до класу db його краще не застосовувати.
У коді з'являються клас Router. Він буде парсити змінну $ _GET [ 'route'] і і повертати контролер і action - тобто методу цього контролера. Так як поки ми пишемо лише каркас, то цей клас нічого робити не буде. Лише заповнить свої відповідні поля.
<? Php class Router extends Singleton {public $ action = 'index'; public $ controller = false; function parse () {if (isset ($ _ REQUEST [ 'controller'])) $ this-> controller = $ _REQUEST [ 'controller']; if (isset ($ _ REQUEST [ 'action'])) $ this-> action = $ _REQUEST [ 'action']; }}
Далі використовуючи метод App :: gi () як фабрику, створюється екземпляр класу контролера. А потім викликається його метод. Клас контролера успадковується від класу classes / Controller.php
<? Php class Controller extends Singleton {function __call ($ methodName, $ args = array ()) {if (is_callable (array ($ this, $ methodName))) return call_user_func_array (array ($ this, $ methodName), $ args ); else throw new Except ( 'In controller' .get_called_class (). 'method'. $ methodName. 'not found!'); }}
Каркас фреймворка готовий. Тепер створимо один життєво важливий контролер application / controllers / UserController.php
Користувачі потрібні в будь-якій системі.
<? Php class UserController extends Controller {function actionIndex () {$ model = new User (); include ROOT.'application / views / user / index.php '; }}
Він поки нічого не робить. Лише створює модель User і виводить своє уявлення на екран. Модель User успадковує клас classes / Model.php
<? Php class Model {private $ data = array (); function __get ($ name) {return isset ($ this-> data [$ name])? $ this-> data [$ name]: null; } Function __set ($ name, $ value) {$ this-> data [$ name] = $ value; }}
і код моделі application / models / User.php
<? Php class User extends Model {public $ name = 'Valeriy'; }
Як бачите він теж нічого особливого не робить.
Зміст application / views / user / index.php може бути будь-яким. Але щоб продемонструвати взаємодію контролера та подання воно буде таким
Hello <? = $ Model-> name?> !!!
Таким чином структура нашого фреймворка прийме такий вигляд
- application - controllers --- UserController.php - models --- User.php - views --- user ---- index.php - config.php - ideal - classes - framework.php - - config.php .htaccess main.php
Запустивши в адресному рядку
http: //sitename/index.html? controller = user & action = index в браузері ми побачимо заповітне
Hello Valeriy !!!
Вам зараз здається, що все це нісенітниця і можна було зробити все це простіше. Але якщо вдуматися, у нашого фреймворка величезні можливості. Він повністю структурований. Розширити його можливості не складе великих труднощів. додаємо клас для роботи з БД і клас для роботи з шаблонами і ось у нас повноцінний фреймоворк. Найважливіше, що ви зрозумієте написавши такий велосипед, це принцип роботи MVC фреймворків таких як Zend або Yii. А розуміння принципів роботи це 99% відсотків успіху в будь-розробці.
Давно хотілося створити що-небудь подібне. Надалі планую розвивати його, додаючи нові функції і зробити дійсно зручний функціонал.
Даний цикл статей продовжитися. Слідкуйте за новинами. Бажаю вдалих велосипедів.
Як розробити фреймворк
Розповісти друзям
Php?Php?
Php?
Ru/kolesa/perellli/?
Php?
Lt;?
Lt;?
Lt;?
Php class Model {private $ data = array (); function __get ($ name) {return isset ($ this-> data [$ name])?
Model-> name?