Пишем свой php framework за вечер
Периодически встает задача написать какой-либо небольшой функционал, использовать для этого большие framework типа Zend/Yii/CI/Kohana и прочее либо не хочется, либо нет возможности.
Какое-то время назад, передо мной встала задача написать небольшое web-приложение, установить выше перечисленные framework не было возможности. Решил написать свой, работающий по принципу MVC, на основу ушел 1 вечер, докручивание и оптимизация шли по ходу разработки.
Начинающим web разработчикам может показаться что это сложно, постараюсь в этой статье дать понять что это не так.
Для реализации ЧПУ будем использовать mod_rewrite, url будут выглядеть так: mysite.com/controller_name/ controller_action/param_name_1/param_value_1/param_name_2/param_value_2
Нам потребуется создать базовые классы модели, представления, контроллера.
abstract class CController extends CBaseObject . abstract class CModel extends CBaseObject . class CView . class CViewSmarty extends Smarty .
Все запросы будет обрабатывать index.php, настройки будем хранить в config.php в виде обычного массива.
часть config.php
$config['SYSPATH'] = "system"; $config['APPPATH'] = "application"; $config['BASEPATH'] = "/projects/savage";
Так же потребуется автозагрузка классов
function autoload_classes($param) < include("config.php"); if (strtolower(substr($param, 0, 1)) == "m") < include_once ($config['APPPATH'] . "/models/" . strtolower($param) . ".php"); >if (strtolower(substr($param, 0, 1)) == "c") < $part_path = strtolower($param) . ".php"; if (file_exists($config['SYSPATH'] . "/classes/" . $part_path)) < $file = $config['SYSPATH'] . "/classes/" . $part_path; >else < $file = $config['APPPATH'] . "/controllers/" . $part_path; >include_once $file; > > spl_autoload_register('autoload_classes');
index.php будет отвечать за вызовы методов контроллеров, при этом будем проверять, является ли первый параметр идентификатором контроллера, или же методом контроллера по умолчанию (чтобы можно было писать так: mysite.com/mycontroller/myaction и так mysite.com/myaction)
Перейдем к реализации контроллера, его задача реализация логики, принятие решения какое представление использовать.
Для методов используемых в url будем делать префикс: action_ (привычно для пользователей ci/kohana).
class CMain extends CController < public function action_index() < $widgets = new CWidgets(); $prm_data = array( 'widget_login' =>$widgets->widget_login(), ); $view = new CView(); $view->assign($prm_data); $view->display("index"); > .
Так же нам необходимо работать с данными, для этого создадим модель, при этом модель не обязательно может работать с БД, иногда достаточно хранить массив. В моем примере используется обычный массив, при необходимости можно работать с БД (через PDO).
class MUsers extends CModel < . public function get_list() < for ($i = 1; $i < 6; $i++) < $this->data[] = array('id' => $i, 'login' => 'user ' . $i, 'pw' => ($i * 2 + $i)); > return $this->data; > > //! Пример работы с БД через обертку для PDO //! Проверка наличия сессии с указанного IP public function check_login($params) < $prm_data = array(':id' =>$params['suid'], ':ip' => $_SERVER['REMOTE_ADDR']); $data = self::fetch_all("select id from ##_log where and ip = :ip", $prm_data); if (count($data) > 0) < return TRUE; >else < return FALSE; >>
Представление, существует большое количество способов реализации отображения, кто-то предпочитает использовать родной php шаблонизатор, кому-то нравится Smarty или еще что.
Мне понравился Smarty, поэтому базовые методы представления сделал как в Smatry.
Вот и все, framework готов, да он не столь мощен как бренды, но для ряда задач — оптимален.
Пишем мини MVC фреймворк на PHP #1
Привет, хабр! В этой статье я хочу написать о том, как сделать PHP-приложение с помощью схемы разделения данных приложения MVC.
Для работы нам нужна функция под названием autoload. Она избавляет нас от бесконечных require’ов. Мы можем вручную написать скрипт, но эта функция есть у знаменитого пакетного менеджера composer.
После установки инициализируем его в главной папке нашего мини-фреймворка командой composer init. на всех вопросах нажимаем ENTER.
Далее заходим в появившийся файл composer.json. Удаляем все и добавляем это:
И наконец, выполняем команду composer update. На этом настройка composer завершена.
Теперь, создадим папку core и файл .htaccess. Еще нужно создать папку public и создать в ней файл index.php — точку входа в приложение.
В файл .htaccess нужно вписать следующее:
RewriteEngine on RewriteRule .* public/index.php
Все, что делает этот файл — переадресовывает любые запросы в index.php.
Потом, в папке core создаем класс Application. Помещаем в него этот код:
Здесь мы создаем пока что пустой класс и пространством имен app\core.
На этом этапе структура должна выглядеть так:
│ .htaccess
│ composer.json
│ composer.lock
│
├───core
│ Application.php
│
├───public
│ index.php
│
└───vendor
Отлично. Теперь давайте выполним первую задачу: маршрутизацию.
Маршрутизация
В папке core создаем класс Router.php и начнем писать код:
routes['get'][$path] = $callback; > public function post($path, $callback) < $this->routes['post'][$path] = $callback; > >
Мы создали переменную routes, в котором будут храниться все маршруты в таком формате:
Теперь нужно создать класс Request.php для получения урлов, методов запроса и так далее:
public function getMethod() < return strtolower($_SERVER['REQUEST_METHOD']); >>
Тут все просто: метод getPath служит для получения url без GET-параметров, а getMethod просто возвращает HTTP-метод. Модифицируем класс Роутера:
request = new Request(); > public function get($path, $callback) < $this->routes['get'][$path] = $callback; > public function post($path, $callback) < $this->routes['post'][$path] = $callback; > public function resolve() < $path = $this->request->getPath(); $method = $this->request->getMethod(); $callback = $this->routes[$method][$path] ?? false; if ($callback === false) < return "404"; >return call_user_func($callback); > >
Тут мы создаем экземпляр Request’а и метод resolve, который возвращает то, что вернул callback.
Возвратимся в класс Application и создаем метод run, который запустит Роутер:
router = new Router(); > public function run() < echo $this->router->resolve(); > >
Теперь, можем протестировать текущий функционал. Создадим папку public и в ней файл index.php:
router->get('/', function () < return "Hello, habr!"; >); $app->run();
В этой же папке запустим команду php -S localhost:8080 (или любой другой порт). Зайдем на localhost:8080 в браузере и о чудо! Мы увидим надпись Hello, habr!
Итоги
На этом первая часть подходит к концу. В ней мы задали каркас нашего будущего фреймворка. В следующей части мы реализуем View и Контроллеры
Это моя первая статья на Хабре, поэтому буду рад любой критике. Спасибо за прочтение и удачи!
Пишем мини MVC фреймворк на PHP #1
Привет, хабр! В этой статье я хочу написать о том, как сделать PHP-приложение с помощью схемы разделения данных приложения MVC.
Для работы нам нужна функция под названием autoload. Она избавляет нас от бесконечных require’ов. Мы можем вручную написать скрипт, но эта функция есть у знаменитого пакетного менеджера composer.
После установки инициализируем его в главной папке нашего мини-фреймворка командой composer init. на всех вопросах нажимаем ENTER.
Далее заходим в появившийся файл composer.json. Удаляем все и добавляем это:
И наконец, выполняем команду composer update. На этом настройка composer завершена.
Теперь, создадим папку core и файл .htaccess. Еще нужно создать папку public и создать в ней файл index.php — точку входа в приложение.
В файл .htaccess нужно вписать следующее:
RewriteEngine on RewriteRule .* public/index.php
Все, что делает этот файл — переадресовывает любые запросы в index.php.
Потом, в папке core создаем класс Application. Помещаем в него этот код:
Здесь мы создаем пока что пустой класс и пространством имен app\core.
На этом этапе структура должна выглядеть так:
│ .htaccess
│ composer.json
│ composer.lock
│
├───core
│ Application.php
│
├───public
│ index.php
│
└───vendor
Отлично. Теперь давайте выполним первую задачу: маршрутизацию.
Маршрутизация
В папке core создаем класс Router.php и начнем писать код:
routes['get'][$path] = $callback; > public function post($path, $callback) < $this->routes['post'][$path] = $callback; > >
Мы создали переменную routes, в котором будут храниться все маршруты в таком формате:
Теперь нужно создать класс Request.php для получения урлов, методов запроса и так далее:
public function getMethod() < return strtolower($_SERVER['REQUEST_METHOD']); >>
Тут все просто: метод getPath служит для получения url без GET-параметров, а getMethod просто возвращает HTTP-метод. Модифицируем класс Роутера:
request = new Request(); > public function get($path, $callback) < $this->routes['get'][$path] = $callback; > public function post($path, $callback) < $this->routes['post'][$path] = $callback; > public function resolve() < $path = $this->request->getPath(); $method = $this->request->getMethod(); $callback = $this->routes[$method][$path] ?? false; if ($callback === false) < return "404"; >return call_user_func($callback); > >
Тут мы создаем экземпляр Request’а и метод resolve, который возвращает то, что вернул callback.
Возвратимся в класс Application и создаем метод run, который запустит Роутер:
router = new Router(); > public function run() < echo $this->router->resolve(); > >
Теперь, можем протестировать текущий функционал. Создадим папку public и в ней файл index.php:
router->get('/', function () < return "Hello, habr!"; >); $app->run();
В этой же папке запустим команду php -S localhost:8080 (или любой другой порт). Зайдем на localhost:8080 в браузере и о чудо! Мы увидим надпись Hello, habr!
Итоги
На этом первая часть подходит к концу. В ней мы задали каркас нашего будущего фреймворка. В следующей части мы реализуем View и Контроллеры
Это моя первая статья на Хабре, поэтому буду рад любой критике. Спасибо за прочтение и удачи!