Вступ

Типовий PHP-проєкт швидко перетворюється на «все в одному»: валідація, сесії, БД і HTML злипаються з роутером, і вимкнути непотрібне вже важко. Concept 2 для PHP 8.4+ побудований інакше — на PSR (HTTP, Container, Logging, …) і трьох шарах, які можна збирати поштучно:

  • Core — лише контейнер, маршрутизація й dispatch: щоб HTTP-цикл існував без фреймворк-магії
  • Extensions — окремі composer-пакети (валідація, view, БД, …): підключаєш, коли з’явився біль, а не «на всяк випадок»
  • Stack — fluent API, який збирає обрані Extensions у providers: явний рецепт збірки замість прихованого global bootstrap

Додаток у Bootstrap обирає лише потрібні capabilities, передає їм явні параметри і реєструє результат у контейнері. Нічого не «вмикається само» через глобальний config: якщо capability немає в Stack — її сервісів немає в контейнері. Core лишається тонким; доменна логіка живе в Extensions.

Concept 2

Strict-typed PHP 8.4+, PSR-standards
Stack
Fluent builders, які збирають потрібні extension providers.
providers() ↑
Extensions Composer-пакети
Http Validation Database Session View Logger …
contracts ↑
Core php-concept/core-2
App HttpKernel RouteStrategy Argument Resolvers

Вперше з Concept 2?

Почніть з Огляду рецептів — покрокові рецепти Stack, починаючи з Перший HTTP-запит.

Що це не є

Concept 2 — не CMS і не framework, який нав’язує повний стек незалежно від задачі. Немає єдиного «увімкнути все»: ви явно збираєте Stack з потрібних Extensions.

Також Concept 2 — не «магія конфігів усередині пакетів». Extensions не читають глобальний config; значення (шляхи, flags, connection arrays) передає той код, який збирає Stack — зазвичай glue додатку.

Core · Extensions · Stack

Три шари мають чіткі межі відповідальності. Core забезпечує спільний runtime; Extensions додають можливості; Stack — зручний спосіб скласти їх докупи без ручного переліку десятків new XxxServiceProvider(...).

ШарПакетРоль
Core php-concept/core-2 App, HttpKernel, RouteStrategy, базові argument resolvers
Extensions php-concept/extension-* Http, Validation, Database, Session, View, Logger, …
Stack php-concept/stack Fluent ConceptStack + bricks → list of providers

Core

Пакет php-concept/core-2 — точка входу runtime. Типові частини:

  • App — створює League Container (з ReflectionContainer delegate) і запускає HTTP-обробку
  • HttpKernelServiceProvider — реєструє PSR-7 ServerRequest, Router і завантаження route-файлів
  • RouteStrategy — викликає handler маршруту: interceptors, підготовка request, resolve аргументів, invoke
  • Базові resolvers — ServerRequestArgumentResolver і RouteParameterArgumentResolver
  • Контракти розширення — ArgumentResolverInterface, RouteInterceptorInterface

Core не залежить від Extensions і не читає config. Порядок argument resolvers і список interceptors йому передають ззовні (через Stack / glue) — ядро лише виконує ланцюжок.

Extensions

Кожне розширення — окремий composer-пакет php-concept/extension-{name}. У корені src/ — один entry point {Name}ServiceProvider; публічні інтерфейси — у src/Contracts/; реалізації — у feature-директоріях.

Правила wiring:

  • Конфігурація — через constructor params provider-а (шляхи, flags, масиви, optional factories)
  • Extension не читає ConfigInterface всередині своїх класів
  • Сервіси extension отримують залежності через конструктор, а не через service locator на «чужі» типи
  • Допускається $container->get() лише власних контрактів або стабільних core/PSR типів у wiring provider-а

Приклади: Http (ResponseFactory, UrlGenerator), Validation + FormRequest, Casting, Session/CSRF, Database, View/Twig, Logger, DataMasker, Console. Детальні сторінки — у розділі «Розширення».

Stack

Пакет php-concept/stack дає fluent API ConceptStack. Виклики на кшталт addHttp(), addView(), addDatabase(), addLogging() одразу реєструють capability (окремий end() не потрібен). Після збірки $stack->providers() повертає упорядкований список ServiceProvider для реєстрації в контейнері.

Stack — тонкий шар над Extensions: він знає, які providers і з якими параметрами створити, але сам config не читає. Усі значення (debug, шляхи до view, connection array, log file) передає викликаючий код як explicit arguments на brick-методи.

Окремі гілки можна тримати від кореня $stack (наприклад, database + query logging), не змішуючи контекст fluent-ланцюжка.