<?php $app = "micro framework for PHP 7"; ?>

Загрузка и установка

Установка с помощью composer

composer create-project sumish/minimal .

Конфигурация

Массив конфигурации находится в основном корневом файле config.php. Эти настройки являются глобальным (для всех приложений). При инициализации приложений, для каждого приложения, настройки могут определяться дополнительно в файлах app/name/config.php

Общая конфигурация

return [ 'routes' => [ '/' => 'home', '/dashboard' => 'home/dashboard', '/info' => 'home/info' ], 'headers' => [ 1000 => 'Content-Type: text/html; charset=utf-8', ], 'components' => [ 'session' => \Sumish\Session::class, 'request' => \Sumish\Request::class, 'response' => \Sumish\Response::class, 'document' => \Sumish\Document::class, 'router' => \Sumish\Router::class, 'load' => \Sumish\Loader::class, 'view' => \Sumish\View::class ], 'db' => [ 'dsn' => 'mysql:host=localhost;dbname=project', 'user' => 'root', 'password' => '', ], 'compression' => 0, 'mode' => 'dev' ];

Подключение и сборка проекта

Автозагрузка классов при использовании composer

<?php require_once('vendor/autoload.php'); ...

Автозагрузка классов без composer

<?php require_once('framework/autoload.php'); ...

Сборка и запуск проекта

<?php require_once('vendor/autoload.php'); $app = new Sumish\Application([ 'routes' => [ '/' => 'home' ] ]); $app->run();

Запуск с подключением config.php

<?php require_once('vendor/autoload.php'); (new Sumish\Application(require('config.php')))->run();

Стандартные компоненты

Container

Контейнер обеспечивает внедрение зависимостей. Проще говоря это механизм передачи объектов другим объектам. Объект конрейнера $this->container передает базовые компоненты ядру системы и затем эти объекты можно применять.

Область видимости объектов контейнера может быть как внутри некоторых базовых компонентов Application, Controller, Router, Loader, View, так и за пределами их после создания объекта приложения.

Создание и вызов простого объекта

<?php ... $app = new Sumish\Application(require('config.php')); $app->container->set('component_name', new class { data = 'Hello'; }); echo $app->component_name->data; // -> Hello

Передачи в контейнер различных данных

<?php ... class Example { public $prop = 12345; public function __construct($args) { if (!is_null($args)) { $this->prop = $args; } } public function method($data) { return $data; } } // Будет создан объект, только при первом вызове свойства или метода $app->container->set('example1', Example::class); echo $app->example1->prop; // -> 12345 // Простая передача экземпляра объекта $app->container->set('example2', new Example); echo $app->example2->method('Hello'); // -> Hello // Передача экземпляра объекта c параметрами конструктора $app->container->set('example3', new Example(54321)); echo $app->example3->prop; // -> 54321 // Передача экземпляра объекта c параметрами конструктора через аргумент метода set() $app->container->set('example4', new Example, ['args'=>54321]); echo $app->example4->prop; // -> 54321 // Передача массива $app->container->set('example5', ['one', 'two']); echo $app->example5[0]; // -> "one" echo $app->example5[1]; // -> "two" // Передача числа $app->container->set('example6', 12345); echo $app->example6; // -> 12345 // Передача функции $app->container->set('example7', function() { return 'Hello'; }); echo $app->example7(); // -> Hello

Стоит отметить что, если были переданы данные методом set(), то повторная передача не переопределит текущий контейнер. Для переопределения необходимо передавать методом register()

Перерегистрация контейнера

$app->container->set('example1', 12345); echo $app->example1; // -> 12345 $app->container->set('example1', 54321); echo $app->example1; // -> 12345 $app->container->register('example1', 54321); echo $app->example1; // -> 54321

Router

Список маршрутов формируется на основе конфигурационных файлов из массива routes. Приоритет обхода маршрутов определяется по именам директорий приложений в основной директории app.

Формирование списка маршрутов из файлов конфигурации

<?php ... 'routes' => [ '/' => 'home', ]; <?php ... 'routes' => [ '/news1' => 'news/index', '/news1/list' => 'news/list', ]; <?php ... 'routes' => [ '/news2' => 'news/index', '/news2/list' => 'news/list', ];

При запросе страницы, все маршруты будут сформированы в один список

'routes' => [ '/' => 'home', '/news1' => 'news/index', '/news1/list' => 'news/list', '/news2' => 'news/index', '/news2/list' => 'news/list', ];

Controller

Контроллеры могут быть описаны в нескольких местах, в зависимости от удобства применения структуры приложения. Изначально необходимо указать пути к контроллерам в массиве routes. Путь к контроллеру может быть указан обычным именем и при необходимости указано действие после слеша "/".

Путь к контроллеру с корневым действем indexAction()

<?php ... 'routes' => [ '/' => 'news' ]

Изначально поиск описания контроллера будет в файле app/news/controller.php, а в классе NewsController будет попытка вызвать метод indexAction(). Если файл controller.php отсутствует или отсутствует описание класса NewsController, тогда будет запрошен файл NewsController.php в отдельной директории app/news/controllers. Если этот файл присутствует и в нем описывается класс NewsController, тогда будет вызван метод indexAction() в нем.

Указание действия listAction()

<?php ... 'routes' => [ '/' => 'news/list' ] Поиск контроллера с методом действия, будет осуществляться в нескольких местах по приопитету:
  1. В файле app/news/controller.php класс NewsController и метод listAction()
  2. В файле app/news/controller.php класс NewsListController и метод indexAction()
  3. В файле app/news/controllers/NewsController.php класс NewsController и метод listAction()
  4. В файле app/news/controllers/NewsListController.php класс NewsListController и метод indexAction()

Действия

Действия представляют собой методы для контроллеров. Как уже было описано раньнее, при определении маршрутов в массиве routes, указывается контроллер и так же может указыватся его действие после слеша.

<?php 'routes' => [ '/blog' => 'blog/list', ];
<?php use Sumish\Controller; class BlogController extends Controller { public function listAction() { ... } } <?php class BlogListController extends Controller { public function indexAction() { ... } }

Request

Для получения данных GET, POST, Cookie, Files, Server можно воспользоваться объектом $this->request.

Получение пользовательских данных запросов

$this->request->get['login'] $this->request->post['message'] $this->request->request['check'] $this->request->cookie['flag'] $this->request->files['filedata'] $this->request->server['HTTP_HOST']

Response

Весь ответ, в том числе и обработка вывода шаблонов (представлений) обрабатывается объектом $this->response. Он имеет также ряд методов для дополнительной обработки HTTP.

Добавление заголовков в HTTP ответ

$this->response->addHeader('Content-Type: text/html; charset=utf-8'); $this->response->addHeader('X-XSS-Protection: 1'); $this->response->addHeaders([ 2001 => 'X-Generator: Sumish', 2002 => 'X-Powered-By: PHP/7' ]);

Перенаправление страницы

$this->response->redirect('/path/to/page');

Добавление вывода в формирующуюся страницу

$this->response->addOutput('HTML content>'); $this->response->setOutput('HTML content');

Управление сжатием страницы

$this->response->setCompression(5); $this->response->compress('New data...');

Вывод потока сформированной страницы

$this->response->output();

Session

С сессиями можно работать через объект $this->session.

Получение идентификатора сессии с помощью метода getId()

echo $this->session->getId();

Определение данных сессии с помощью массива data[]

$this->session->data['user'] = $this->db->getUser(); echo $this->session->data['user'];

Loader

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

Подгрузка моделей

После определения моделей, их можно применять внутри контроллера после подгрузки.

$this->load->model('newslist'); $this->load->model('newsupdate');

Подгружаемые модели можно вызывать с методами

$this->load->model('newslist')->getData(); $this->load->model('newsupdate')->setId(5);

Для упрощения вызов методов, можно вызывать через переменную

$news = $this->load->model('newslist'); $news->getData();

Подгрузка контроллеров

Если необходима некоторая функциональность их других контроллеров, то можно с помощью $this->load->controller выполнить подгрузку определенного контроллера и получить его объект.

// получение основного контроллера NewsController приложения news $newsController = $this->load->controller('news'); // получение контроллера NewsUpdateController приложения news $newsUpdateController = $this->load->controller('news/update'); // вызов методов в загруженных контроллерах $newsController->doAction(); $newsUpdateController->doAction();

Таким образом будут загружены контроллеры из app/news/controller.php или app/news/controllers/NewsController.php, app/news/controllers/NewsUpdateController.php в зависимости от их места описания.

Library

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

Подгрузка сторонних библиотек

Альтернативный способ composer, добпаления новой функциональности. Если есть возможность подключить пакет с помощью composer, тогда лучше воспользоватся им. Если такого пакета нет или вам нужно интегрировать более старые классы или библиотеки PHP, тогда можете их подключить с помощью $this->load->library или сокращенно $this->load->lib.

$this->load->lib('activerecord');

...

Model

Все модели определяются подобно контроллерам в файле app/name/model.php или в отдельной директории app/name/models если не описано в model.php.

<?php class NewsModel { public function getData() { ... } }

В одном файле model.php можно описать несколько моделей

<?php class NewsListModel { public function getData() { ... } } class NewsUpdateModel { public function setId($id) { ... } }

Базы данных

Для обеспечения моделей работы с базами данных существует абстрактный класс в котором реализован статический метод соединения с базой. Параметры соединения прописываются в корневом файле config.php в массиве db.

return [ 'db' => [ 'dsn' => 'mysql:host=localhost;dbname=mvc', 'user' => 'root', 'password' => '', ] ];

Данее, можно унаследовать модель с ModelDb и использовать PDO через $this->db

class NewsListModel extends Sumish\ModelDb { public function getData() { $data = $this->db->query(...); return $data->fetchAll(PDO::FETCH_ASSOC); } }

При необходимости объект $this->db можно переопределить на произвольный объект обработки базы данных, например FluentPDO

# composer install "fpdo/fluentpdo" $this->container->register('db', 'FluentPDO', ['pdo' => 'mysql:dbname=project;host=localhost']); $query = $this->db->from('article') ->where('published_at > ?', $date) ->orderBy('published_at DESC') ->limit(5); foreach ($query as $row) { echo "$row[title]\n"; }

Сторонние расширения

Также возможностью работы с базой данных, может стать использование сторонних библиотек.

ActiveRecord

Для упращеной работы с базой в объектно-ориентированном стиле необходимо подключить для этих целей библиотеку

... 'libraries' => [ 'activerecord' ], ...

Загрузку можно также сделать только при необходимости в самом контроллере

$this->load->lib('activerecord');

Далее можно создавать модель в стиле ActiveRecord

class NewsModel extends Sumish\ActiveRecord { static $table_name = 'news_models'; }

В контроллере теперь можно использовать модель в стиле ActiveRecord

... echo HomeModel::table_name(); var_dump(get_class_methods('HomeModel')); ...

RedBean

Еще одна библиокета, которая может работать с базой по принципу CRUD

... 'libraries' => [ '...', 'redbean' ], ...

...

R::setup(); R::setAutoResolve( TRUE ); //Recommended as of version 4.2 $post = R::dispense( 'post' ); $post->text = 'Hello World'; $id = R::store( $post ); //Create or Update $post = R::load( 'post', $id ); //Retrieve R::trash( $post ); //Delete

View

Изначально шаблоны обрабатывеются с помощью шаблонизатора Twig. Это определяется в свойстве объекта представлений $this->view->processor.

Для отрисовки шаблона, достаточно вызвать метод $this->view->render:

$this->view->render('filename', ['data' => 'text']);

Будет подгружен шаблон filename.tpl из директории приложения app/name/templates/filename.tpl. Если данного файла нет, тогда будет попытка подгрузить из корневой директории templates/name/filename.tpl. Все переменные и другие конструкции шаблонов будут разбираться шаблонизатором Twig. Например: переменная {{ data }} будет заменяться на строку "text". Можно отключить обработку шаблонов Twig, для этого необходимо присвоить свойству $this->view->processor значение null.

Переклчение обработки шаблонов в классический стиль (PHP код)

echo $this->view->processor = null;

Теперь шаблоны будут обрабатываться в классическом стиле. Например: переменная <?php echo $data; ?> будет заменяться на строку "text".