Правила     Закладки     Карма    Календарь    Журналы    Помощь    Поиск    PDA    Чат   
        СМС-ки
   
Пейджер выключен!
 
Фильтр авторов:    показать 
  скрыть
  Ответ в темуСоздание новой темыСоздание опроса

> Инфраструктура
twin  
 ۩  Дата
Цитировать сообщение

Пользователя сейчас нет на форуме



Глухой нуб
******

Профиль
Группа: Администратор
Почтальон группы
Сообщений: 15559
Пользователь №: 6543
На форуме: 8 лет, 2 месяца
Карма: 299

Трезвый :
5 лет, 11 месяцев, 10 дней


Оглавление.

В сборке библиотек инфраструктура минимальна. Автолоадер мы уже сделали, теперь нужно создать комфортные условия для разработки. А именно озаботиться дебаггингом.

Для этого конечно есть интерпретатор, который показывает ошибки. Есть даже Xdedug. Но их не всегда достаточно, особенно для отлова логических казусов в процессе исполнения скрипта.

Многие пишут свои хандлеры, либо берут и адаптируют готовые. Могу предложить свою разработку. Взять её можно здесь, либо на гитхабе.

Работает крайне просто. Нужно подключить его в индекс и он выловит все ошибки, вплоть до синтаксических и фатальных, а так же неотловленные эксепшены и trigger_error(), поместив вот в такие таблицы:

Присоединённое изображение
Присоединённое изображение


--------------------
Если вам недостаточно собственных заблуждений, можно расширить их мнениями экспертов.

Нужно уважать мнение оппонета. Ведь заблуждаться - его святое право.

Зачем ворошить старое, когда можно наворотить новое?

user posted image
PMСайт пользователяICQ
    0   Для быстрого поиска похожих сообщений выделите 1-2 слова в тексте и нажмите сюда Для быстрой цитаты из этого сообщения выделите текст и нажмите сюда
twin  
 ۩  Дата
Цитировать сообщение

Пользователя сейчас нет на форуме



Глухой нуб
******

Профиль
Группа: Администратор
Почтальон группы
Сообщений: 15559
Пользователь №: 6543
На форуме: 8 лет, 2 месяца
Карма: 299

Трезвый :
5 лет, 11 месяцев, 10 дней


Обратите внимание, что дебаггер может подключается выше автолоадера, он ему не нужен. А вот сам автолоадер будет отдебажен.

Ну и еще пара моментов. Чтобы отключить режим отладки, нужно определить константу BUGSNARE со значением false.
<?php

// Отключение режима отладки.
define('BUGSNARE', false);
include_once __DIR__ .'/../vendor/PhpBugsnare/setup.php';
Если выставить true, режим будет включен. Дебаггер требует накладных расходов, да и не дело показывать ошибки пользователю. Так что на боевой версии его лучше отключать.

И еще один момент. После подключения доступна функция dbg().

Аргументом может принимать как переменные, так и вызовы функций и методов. В отчете будет стек прохождения логической цепочки с локальными участками кода.

Можно так же посмотреть содержимое объекта и даже структуру класса, если передать аргументом его полное название.

Присоединённое изображение
Присоединённое изображение


--------------------
Если вам недостаточно собственных заблуждений, можно расширить их мнениями экспертов.

Нужно уважать мнение оппонета. Ведь заблуждаться - его святое право.

Зачем ворошить старое, когда можно наворотить новое?

user posted image
PMСайт пользователяICQ
    0   Для быстрого поиска похожих сообщений выделите 1-2 слова в тексте и нажмите сюда Для быстрой цитаты из этого сообщения выделите текст и нажмите сюда
twin  
 ۩  [x] Дата
Цитировать сообщение

Пользователя сейчас нет на форуме



Глухой нуб
******

Профиль
Группа: Администратор
Почтальон группы
Сообщений: 15559
Пользователь №: 6543
На форуме: 8 лет, 2 месяца
Карма: 299

Трезвый :
5 лет, 11 месяцев, 10 дней


Теперь фронт-контроллер (коммутатор).

В последнем листинге на картинке видно, что я его уже начал делать для наглядности. Остановлюсь на одном важном моменте. Сделан он статическим классом, а не объектом. Статика работает экономичнее, но это не столь важно. Важнее другое.

На мой взгляд нужно использовать те инструменты, которые наиболее подходят к задаче. Дело в том, что этот функционал может быть затребован только один раз. А значит инициировать объект нет никакого смысла. Только ради красного словца.

Конечно, если уж совсем невтерпеж, то можно и объектом, мало что изменится:
    (new \Core\FrontController)->run();
Опять же к вопросу свободы выбора. У кого к чему больше лежит душа.

Ну и сам коммутатор. В нем пока только один метод. Его задача выбрать нужный контроллер приложения в зависимости от GET-параметра. Допустим это будет page:
<?php

namespace Core;

class FrontController
{
public static function run()
{
$page = isset($_GET['page']) ? $_GET['page'] : null;
$page = preg_replace('~[^a-z0-9_]~i', '', $page);
$controllerName = ucfirst(strtolower($page));
$controller = '\App\Controllers\\'. $controllerName .'Controller';

if (class_exists($controller)) {
$controller::run();
} else {
print('404');
}
}
}


Здесь три интересных момента.

Первое. Остальные контроллеры тоже предполагаются статичными. Я на своей практике ни разу не встречал ситуации, чтобы для генерации одной страницы могло потребоваться несколько экземпляров одного контроллера. И представить себе не могу. Ну у кого другое мнение, не вопрос. Можно сделать и его объектом. Я смысла не вижу.

Второе. Там внизу стоит print('404'); Это временно, позже там будет генерация полноценной 404-й страницы.

И главное. Инициализация GET-параметра тернарником напрямую из суперглобального массива. Вот это не есть хорошо. Этим сейчас и озадачимся.


--------------------
Если вам недостаточно собственных заблуждений, можно расширить их мнениями экспертов.

Нужно уважать мнение оппонета. Ведь заблуждаться - его святое право.

Зачем ворошить старое, когда можно наворотить новое?

user posted image
PMСайт пользователяICQ
    0   Для быстрого поиска похожих сообщений выделите 1-2 слова в тексте и нажмите сюда Для быстрой цитаты из этого сообщения выделите текст и нажмите сюда
twin  
 ۩  [x] Дата
Цитировать сообщение

Пользователя сейчас нет на форуме



Глухой нуб
******

Профиль
Группа: Администратор
Почтальон группы
Сообщений: 15559
Пользователь №: 6543
На форуме: 8 лет, 2 месяца
Карма: 299

Трезвый :
5 лет, 11 месяцев, 10 дней


Сборник (библиотека) общих функций.

Не секрет, что PHP не идеален. Иногда каких то функций остро нехватает, иногда какие то хочется переделать.

Кроме того, могут потребоваться свои, пользовательские.

Конечно, можно все это собрать в класс, эдакий глобальный хэлпер. Для таких случаев в ООП придумана модель stateless. Это такой класс, который не хранит состояния, и методы которого не взаимодействуют друг с другом. Простыми словами - контейнер для функций.

Но у него есть один огромный недостаток. Если в разных местах потребуются разные функции, то в этих местах придется инициализировать новые объекты. Для того, чтобы нивелировать сей пердимонокль, можно применить модный нынче принцип IoC. В частности DIC. Это, кто не знает, эдакий всеобщий объект, внедряемый в другие объекты как зависимость. И в котором собраны другие, необходимые приложению объекты. Это весьма упрощенно, но суть именно такова. Можно не плодить новых, а пользоваться расшареным объектом из контейнера. Тогда вызов требуемой функции будет выглядеть как то так:
<?php

class
Example
{
public function __construct($contaner)
{
$this->container = $contaner;
}

public function someMethod()
{
$page = $this->container->get('DtfaultFuncnions')->takeGET('page');
}
}

Можно попробовать немного упростить, поместив этот объект в свойство:
<?php

class
Example
{
protected $defaultFunction;

public function __construct($contaner)
{
$this->defaultFunction = $contaner->get('DtfaultFuncnions')
}

public function someMethod()
{
$page = $this->defaultFunction->takeGET('page');
}
}

Однако на самом деле это очевидный путь усложнения. Мало того, что код раздувается (не говоря уже о самом контейнере), так еще и размазывается по классу. Теперь, чтобы понять откуда ноги растут, придется смотреть откуда взялось свойство.

Контейнер иногда действительно полезен, но только не в случае stateless. Потому что расшаренный объект фактически равнозначен статическому классу. Однако посмотрим, как с классом:
<?php

use Core\DtfaultFuncnions;

class Example
{
public function someMethod()
{
$page = DtfaultFuncnions::takeGET('page');
}
}

Уже лучше, писанины меньше, код прозрачнее и проще. Можно оставить и так, но мое твердое убеждение, что инструменты не следует извращать. Если нужна функция, то это должна быть функция, от неё не требуется ничего большего. Оборачивать её классом нет никакого смысла. И еще, раз это функции, доступные по умолчанию, не нужно помещать их в немспейс. А это еще больше упрощает жизнь.

Могут последовать возражения, мол функции доступные глобально, это плохо. Что можно случайно написать одноименную, если идти по такому пути, и будет конфликт.

Ну так это же и есть глобальные функции по определению. И даже хорошо, ибо не будет неоднозначностей. Попробуйте определить функцию с названием htmlspecialchars() к примеру. Интерпретатор скажет - аяяй. Так и тут. За такой ситуацией строго следит сам PHP.

Впрочем это ИМХО, каждый волен поступать по своему. Ведь основной постулат такого способа программирования - простота и неортогональность.

Итак, создадим файл с дефолтными функциями. Я, по привычке, назову его default.php :

Core\default.php
<?php

/////// ГЛОБАЛЬНЫЕ ФУНКЦИИ ///////

/**
* Получает GET параметр по ключу.
*
*
@param string $key
*
@param string $default
*
*
@return mix
*/

function takeGET($key, $default = null)
{
return isset($_GET[$key]) ? $_GET[$key] : $default;
}



Этот файл нужно подключить к системе. Обычно, если используется схема фреймворка, для этого создается файл bootstrap.php, эдакий инициатор запуска. У нас не фреймворк, а конкретное приложение. Я не вижу потребности делать еще одну прослойку, с этим вполне справится индекс:

www/index.php
<?php

// Автозагрузчик классов
require __DIR__ .'/../Core/Autoloader.php';

// Режим отладки.
define('BUGSNARE', $config->getConfig()['debug']);
include_once __DIR__ .'/../vendor/PhpBugsnare/setup.php';

// Функции по умолчанию
include_once __DIR__ .'/../Core/default.php';

\
Core\FrontController::run($config);


Конечно, это может показаться примитивным, подключать файлы в индексе. Но это и есть KISS. Приложение на основе сборки библиотек, в отличие от фреймворка, не претендует на универсальность. Это сборка, её просто нужно собрать. А значит и keep it simple, stupid.

Структура приложения теперь будет примерно такой:

Присоединённое изображение
Присоединённое изображение


--------------------
Если вам недостаточно собственных заблуждений, можно расширить их мнениями экспертов.

Нужно уважать мнение оппонета. Ведь заблуждаться - его святое право.

Зачем ворошить старое, когда можно наворотить новое?

user posted image
PMСайт пользователяICQ
    0   Для быстрого поиска похожих сообщений выделите 1-2 слова в тексте и нажмите сюда Для быстрой цитаты из этого сообщения выделите текст и нажмите сюда
twin  
 ۩  Дата
Цитировать сообщение

Пользователя сейчас нет на форуме



Глухой нуб
******

Профиль
Группа: Администратор
Почтальон группы
Сообщений: 15559
Пользователь №: 6543
На форуме: 8 лет, 2 месяца
Карма: 299

Трезвый :
5 лет, 11 месяцев, 10 дней


Соответственно фронт-контроллер пока такой:
<?php

namespace Core;

class FrontController
{
public static function run()
{
$page = takeGET('page');
$page = preg_replace('~[^a-z0-9_]~i', '', $page);
$controllerName = ucfirst(strtolower($page));
$controller = '\App\Controllers\\'. $controllerName .'Controller';

if (class_exists($controller)) {
$controller::run();
} else {
print('404');
}
}
}
Теперь он легко и просто подхватит нужный контроллер в зависимости от GET. Это пока не всё, потому что нужно еще активировать действие в контроллере. Как принято говорить - вызвать нужный экшен (action). Но это позже, когда дело дойдет до конкретных контроллеров.

А пока нужно закончить инфраструктуру. Еще одним архиважным местом в приложении является конфигурация. Вот этим и займемся.


--------------------
Если вам недостаточно собственных заблуждений, можно расширить их мнениями экспертов.

Нужно уважать мнение оппонета. Ведь заблуждаться - его святое право.

Зачем ворошить старое, когда можно наворотить новое?

user posted image
PMСайт пользователяICQ
    0   Для быстрого поиска похожих сообщений выделите 1-2 слова в тексте и нажмите сюда Для быстрой цитаты из этого сообщения выделите текст и нажмите сюда
twin  
 ۩  [x] Дата
Цитировать сообщение

Пользователя сейчас нет на форуме



Глухой нуб
******

Профиль
Группа: Администратор
Почтальон группы
Сообщений: 15559
Пользователь №: 6543
На форуме: 8 лет, 2 месяца
Карма: 299

Трезвый :
5 лет, 11 месяцев, 10 дней


Конфигуратор

Конфигурационный файл можно расположить в двух местах. В публичной папке или в папке с приложением (App/). В публичной лучше ничего лишнего не держать. Если только не предполагается несколько морд с одним приложением. У нас такого не предвидется, а значит спокойно засунем конфигу в приложение. Хотя по сути не важно, где она лежит. Можно сунуть куда угодно, лишь бы было удобно пользоваться.

Сама конфига, это обычный php файл, в котором находится массив с настройками. Настраивать нам пока что нечего, так что он будет пустым:

App/config.php
<?php

return [

];


А вот дальше интересно. Обрабатывать конфигу будет специальный класс - конфигуратор. Пока он тоже простой, как три копейки:

Core\Configurator.php
<?php

namespace Core;

class Configurator
{
protected $config;

public function __construct($path)
{
$this->config = include $path;
}

public function getConfig()
{
return $this->config;
}
}
Но интересное не это. Тут мы наконец то добрались до вожделенных всеми объектов. Вернее объекта. Одного.

А почему объект, потому что здесь удобно использовать именно его. Во первых магия. В таком классе есть конструктор. Во вторых может понадобится несколько конфиг. А значит можно создать несколько объектов. В третьих, этот объект мы будем передавать, как зависимость. Пока без всяких контейнеров. Вот так:
www/index.php
<?php

// Автозагрузчик классов
require __DIR__ .'/../Core/Autoloader.php';
// Режим отладки.
define('BUGSNARE', true);
include_once __DIR__ .'/../vendor/PhpBugsnare/setup.php';
// Функции по умолчанию
include_once __DIR__ .'/../Core/default.php';
// Конфигурация
$config = new \Core\Configurator(__DIR__ .'/../App/config.php');

\
Core\FrontController::run($config);


Что с этим объектом делать потом, это дальше. Когда будет разрабатываться само приложение.


--------------------
Если вам недостаточно собственных заблуждений, можно расширить их мнениями экспертов.

Нужно уважать мнение оппонета. Ведь заблуждаться - его святое право.

Зачем ворошить старое, когда можно наворотить новое?

user posted image
PMСайт пользователяICQ
    0   Для быстрого поиска похожих сообщений выделите 1-2 слова в тексте и нажмите сюда Для быстрой цитаты из этого сообщения выделите текст и нажмите сюда
twin  
 ۩  Дата
Цитировать сообщение

Пользователя сейчас нет на форуме



Глухой нуб
******

Профиль
Группа: Администратор
Почтальон группы
Сообщений: 15559
Пользователь №: 6543
На форуме: 8 лет, 2 месяца
Карма: 299

Трезвый :
5 лет, 11 месяцев, 10 дней


Ну вобщем то и всё. Инфраструктура намечена, это фактически проектирование без бумажек. Непосредственно кодом, методом заглушек. Такое проектирование называется эволюционным.

Дальше проектировать можно только отдельные страницы. Тут как угодно, можно рисовать UML, можно и без него обойтись. Библиотеки в проектировании особо не нуждаются, если они конечно не предполагаются огромными. А если так, то это скорее всего уже ошибка проектирования. У библиотек узкие задачи и нет внешних связей. Так что объем кода в них обычно невелик.

Ну а мы приступим непосредственно к разработки приложения.


--------------------
Если вам недостаточно собственных заблуждений, можно расширить их мнениями экспертов.

Нужно уважать мнение оппонета. Ведь заблуждаться - его святое право.

Зачем ворошить старое, когда можно наворотить новое?

user posted image
PMСайт пользователяICQ
    0   Для быстрого поиска похожих сообщений выделите 1-2 слова в тексте и нажмите сюда Для быстрой цитаты из этого сообщения выделите текст и нажмите сюда
  Быстрый ответ
Информация о Госте
Введите Ваше имя
Кнопки кодов
Для вставки цитаты, выделите нужный текст и
НАЖМИТЕ СЮДА
Введите сообщение
Смайлики
:huh:  :o  ;) 
:P  :D  :lol: 
B)  :rolleyes:  <_< 
:)  :angry:  :( 
:unsure:  :blink:  :ph34r: 
     
Показать всё

Опции сообщения  Включить смайлики?
 Включить подпись?
 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:

Опции темы Ответ в темуСоздание новой темыСоздание опроса