[ Поиск ] - [ Пользователи ] - [ Календарь ]
Полная Версия: Устройство сервиса.
twin
Тем, кто хочет принять участие в разработке, сей мануал посвящается. :)

Начнем с архитектуры. Фреймворк строится на основе SOA. Это значит, что он основывается на отдельных, слабо связанных компонентах. Ну подробности там есть.

Ядро фреймворка осуществляет управление приложением (роутинг, режимы ошибок, еще несколько плюшек), помогает в отладке (дебаггер) и формирует сервисы.

Что такое сервис. Сервис, это набор компонентов, которые необходимы для выполнения определенной задачи. Рассмотрим на действующем примере. Есть компонент Mysqli. Это обычный класс, который унаследован от штатного, законнекчен и немного расширен для дебаггинга запросов. И есть компонент Sqldebug, это универсальный для всех СУБД компонентов, дебаггер. Вместе они составляют сервис.

Сервис строится билдером (строитель по английски). В зависимости от настроек конфигурации. Построенный интерфейс сервиса упаковывается в сервис-локатор. Откуда мы потом его будем получать по мере необходимости.

Но делает билдер это не сразу, а только тогда, когда к нему обратятся за сервисом. Поэтому фреймворк использует только те сервисы, которые запрашиваются пользователем.

Теперь правила построения компонентов, билдеров и сервисов.

Компоненты.

1. Компоненты располагаются в папке components.
2. Каждый в собственной директории.
3. Название директории, файла и основного класса (интерфейса компонента) должны совподать.
4. Название компонента должно отражать его суть, быть максимально коротким и состоять из одного слова.
5. Основной класс (интерфейс) должен уметь принимать зависимостями объекты дополнительных компонентов. Тоесть там для них должны быть объявлены публичные свойства.
6. Внедрение зависимостей осуществляются только через свойства или сеттеры, но не через конструктор.
7. В конструктор интерфейса обязательно должны передаваться настройки конфигурации.

Ну а дальше дело фантазии.

Вот тренировочные компоненты
Первый.
<?php

namespace ABC\Abc\Components\Training;

/**
* Класс Traning
*
* NOTE: Requires PHP version 5.5 or later
*
@author phpforum.su
*
@copyright © 2015
*
@license http://www.wtfpl.net/
*/
class Training
{
/**
*
@var ABC\Abc\Components\TraningExample\TraningExample
*/

public $example;

/**
* Конструктор
*
*
@param array $data
*/

public function __construct($data = [])
{
// Здесь настройки из конфигурационного файла
}

public function display()
{
echo $this->example->getText();
}
}


Второй
<?php

namespace ABC\Abc\Components\TrainingExample;

/**
* Класс TraningExample
*
* NOTE: Requires PHP version 5.5 or later
*
@author phpforum.su
*
@copyright © 2015
*
@license http://www.wtfpl.net/
*/
class TrainingExample
{
/**
* Конструктор
*
*
@param array $data
*/

public function __construct($data = [])
{
// Здесь настройки из конфигурационного файла
}

public function getText()
{
return 'Привет, Мир!';
}
}


Теперь правила построения билдера.

1. Билдеры располагаются в папке Builders
2. Название билдера должно соответствовать названию сервиса с постфиксом Builder
Пример: TrainingBuilder
3. Каждый билдер должен быть унаследован от основного билдера.
4. В билдере обязателен метод buildService (что прописано контрактом в родителе).
5. Этот метод должен принимать параметр $global с булевым значением, на основе которого решается способ хранения сервиса
6. Зависимости должны внедряться только серез публичные свойства или сеттеры.
7. В конструктор обязательно должны передаваться настройки конфигурации, даже если они там не нужны.
8. Вобщем то и всё пока.

Вот пример билдера:
<?php

namespace ABC\Abc\Builders;

use ABC\Abc\Builders\AbcBuilder;

// Требующиеся дополнительные компоненты
use ABC\Abc\Components\TrainingExample\TrainingExample;

/**
* Класс MysqliBuilder
*
* NOTE: Requires PHP version 5.5 or later
*
@author phpforum.su
*
@copyright © 2015
*
@license http://www.wtfpl.net/
*/

class TraningBuilder extends AbcBuilder
{
/**
*
@var array
*/

protected $service = 'Training'; // <-- Это имя сервиса

/**
* Строит сервис.
*
*
@return void
*/

protected function buildService($global = false)
{ // Формируем путь до компонента
$component = '\ABC\abc\components\\'. $this->service .'\\'. $this->service;
// Получаем из конфиги необходимые настройки
$data = @$this->config[$this->service] ?: [];
// Здесь решаем, каким должен быть сервис. Глобальным (по приципу Singletone)
// Или обычным, когда при каждом обращении формируются новые объекты

$typeService = $global ? 'setGlobal' : 'set';
// Помещаем сервис в локатор в виде анонимной функции
$this->locator->$typeService(
$this->service, // <--- Это название сервиса
function() use ($component, $data) {// <--- Передаем в функцию имя компонента и настройки конфигурации
// Подготавливаем к запуску интерфейс основного компонента

$obj = new $component($data);
// Тут добавляем к данным дополнительные объекты
$obj->example = new TrainingExample;
// Когда будет вызвана функция, будет создан и возвращен объект основного компонента
// с переданными ему настройками и объектами других компонентов в виде зависимостей

return $obj;
}
);
}
}


Всё это работает в фреймворке, можно посмотреть здесь.

Сервис вызывается примерно так:
Abc::getService('Traning')->display();

Это должно выдать вожделенный "Привет, Мир!" :)

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

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

Настаивал, настаиваю и буду настаивать на своем. На кедровых орешках.

user posted image
Быстрый ответ:

 Графические смайлики |  Показывать подпись
Здесь расположена полная версия этой страницы.
Invision Power Board © 2001-2024 Invision Power Services, Inc.