composer.json:
"repositories": [
{
"type": "git",
"url": "https://github.com/proklung/wp.core.symfony"
}
]
composer require proklung/wp-core-symfony
В wp-config.php
:
use Prokl\ServiceProvider\LoadEnvironment;
/** Загрузить окружение. Параметр конструктора - путь к .env файлам */
$environment = new LoadEnvironment($_SERVER['DOCUMENT_ROOT']);
$environment->load();
$environment->process();
В functions.php
темы:
use Prokl\ServiceProvider\ServiceProvider;
$serviceProvider = new ServiceProvider(
'app/symfony/services.yaml',
$_ENV['APP_ENV'],
(bool)$_ENV['APP_DEBUG'],
'/config/bundles.php'
);
Для обеспечения "преемственности" (похожести) с оригиналом можно задать путь к файлу конфигурации
(скажем, bundles.php
) бандлов четвертым (необязательным) параметром конструктора.
APP_ENV
- код окружения (dev, prod, test и т.д.)APP_DEBUG
- режим отладки
- Опция
compile.container
в подтягиваемом конфиге - компилировать ли контейнер в файл. Если не задана, то "нет, не компилировать". Имеет смысл для окружения, не равного "dev". Т.е. опция управляет дампированием контейнера на проде.
Место, где хранятся дампы контейнеров: <значение переменной контейнера kernel.cache_dir>/symfony-app/containers
Определяются классом AppKernel
. По умолчанию:
- путь к кэшу (
kernel.cache_dir
) -/wp-content/cache
- путь к логам (
kernel.logs_dir
) -'/../../logs'
(два уровня выше DOCUMENT_ROOT - особенности используемой сборки Битрикс)
Чтобы это изменить нужно отнаследоваться от класса AppKernel
и переопределить несколько переменных:
use Prokl\ServiceProvider\Services\AppKernel;
class MyKernel extends AppKernel
{
protected $cacheDir = '/bitrix/cache/mycache';
protected $logDir = '/logs-saver';
}
(второй вариант - отнаследоваться от AppKernel
и переопределить методы getCacheDir
и getLogDir
).
Изменить через наследование класс ядра:
class MyServiceProvider extends ServiceProvider
{
protected $kernelServiceClass = MyKernel::class;
protected $cacheDir = '/wp-content/my-cache';
}
Второй вариант - отнаследоваться от ServiceProvider
и заменить метод getPathCacheDirectory
своей логикой.
Файл конфигурации - /config/standalone_bundles.php
. Этот путь можно изменить через конструктор.
Папка, где лежат конфигурации - /config
. Конфигурации бандлов - /config/packages
.
Согласно концепции Symfony все сервисы (в идеале) должны быть приватными и инжектиться. Но в кастомном случае
часто нужно получать их через хелпер-сервис-локатор. Для превращения нужных сервисов в публичные предлагается
такое решение. В общем разделе параметров контейнера появилась опция publicable_services
:
parameters:
publicable_services:
- 'snc_redis.default'
После компиляции контейнера приватный сервис snc_redis.default
станет публичным.
Отдельные контейнеры - со своим конфигом, полностью изолированные (для модулей, плагинов и т.п.).
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Prokl\ServiceProvider\Micro\AbstractStandaloneServiceProvider;
use Prokl\ServiceProvider\Micro\ExampleAppKernel;
class ExampleMicroServiceProvider extends AbstractStandaloneServiceProvider
{
/**
* @var ContainerBuilder $containerBuilder Контейнер.
*/
protected static $containerBuilder;
/**
* @var string $pathBundlesConfig Путь к конфигурации бандлов.
*/
protected $pathBundlesConfig = '/src/Micro/example.config/standalone_bundles.php';
/**
* @var string $configDir Папка, где лежат конфиги.
*/
protected $configDir = '/src/Micro/example.config/example.config/example.yaml';
/**
* @var string $kernelServiceClass Класс, реализующий сервис kernel.
* Нужен для того, чтобы экземпляры контейнеров в kernel сервисе не перемешивались.
*/
protected $kernelServiceClass = ExampleAppKernel::class;
}
Пример класса ExampleAppKernel
:
/**
* Class ExampleAppKernel
* @package Prokl\ServiceProvider\Micro
*/
use Prokl\ServiceProvider\Micro\AbstractKernel;
class ExampleAppKernel extends AbstractKernel
{
protected static $kernelContainer;
}
Где надо - инициализация:
$micro = new ExampleMicroServiceProvider(
'src/SymfonyDI/Micro/example.config/example.yaml',
$_ENV['APP_ENV'],
(bool)$_ENV['APP_DEBUG']
);
Хэлпер container
заточен под работу с микро-сервис-провайдерами:
var_dump(container($micro)->getParameter('example'));
Чтобы сервис запустился автоматически после инициализации контейнера, он должен быть помечен тэгом service.bootstrap
.
app.options:
class: Local\Services\AppOptions
arguments: ['%kernel.environment%', '@parameter_bag']
tags: ['service.bootstrap']
Поддерживается приоритет запуска. Тогда надо так:
app.options:
class: Local\Services\AppOptions
arguments: ['%kernel.environment%', '@parameter_bag']
tags:
- { name: 'service.bootstrap', priority: 100 }
Сервис с приоритетом 100 запустится раньше сервиса с приоритетом 200.
Тэг: custom.events.init
.
type
- add_action, add_filter & etc По умолчанию:add_action
.event
- название хука.method
- метод-обработчик в сервисеpriority
- приоритет
Local\Events\CometCacheClearMemcachedEvent:
tags:
- { name: 'custom.events.init', event: 'post_class', method: 'handler', type: 'add_filter', priority: 100 }
Тэг: post.type
.
Реализует интерфейс PostTypeDataInterface
с двумя методами:
getNameTypePost
- название типа постаgetRegistrationData
- массив с традиционными для объявления типа поста данными. Типа такого:
return [
'labels' => [
'name' => __('Instagram'),
'singular_name' => __('Instagram'),
],
'public' => true,
'publicly_queryable' => true,
'show_ui' => true,
'show_in_menu' => true,
'query_var' => true,
'rewrite' => 'instagram',
'capability_type' => 'post',
'has_archive' => 'instagram',
'hierarchical' => false,
'menu_position' => null,
'supports' => ['title', 'editor', 'author', 'thumbnail', 'excerpt', 'comments'],
];
Local\PostTypes\InstagramPostType:
tags:
- { name: 'post.type' }
Автоматом регистрируются несколько сервисов:
service_container
(и alias) - сервис-контейнер целикомapp.request
- конвертор глобалов в Requestcustom.post.type.registrator
- регистратор кастомных типов постов в Wordpress- синонимы сервиса
kernel
. delegated_container_manipulator
- манипулятор делегированными контейнерами.
container()
- отдает экземпляр контейнера (выступает в роли сервис-локатора):
$kernel = container()->get('kernel');
delegatedContainer()
- отдает экземпляр манипулятора (реализующего интерфейсSymfony\Component\DependencyInjection\ContainerInterface
) делегированными контейнерами.
$moduleService = delegatedContainer()->get('my_module_id.service');
Делегированный контейнер - автономный контейнер, сформированные в модуле, плагине и тому подобных местах.
В контейнере он помечается тэгом delegated.container
(их может быть сколь угодно много):
module_notifier_container:
class: Symfony\Component\DependencyInjection\ContainerInterface
factory: ['Proklung\Notifier\DI\Services', 'getInstance']
tags:
- { name: 'delegated.container' }