PHPackages                             chrisgalliano/pion - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. chrisgalliano/pion

ActiveLibrary

chrisgalliano/pion
==================

Pion is a lightweight PHP Framework

2.1.0(3y ago)066[3 issues](https://github.com/ChrisGalliano/Pion/issues)2MITPHPPHP 7.4.\*

Since Jan 23Pushed 3y ago1 watchersCompare

[ Source](https://github.com/ChrisGalliano/Pion)[ Packagist](https://packagist.org/packages/chrisgalliano/pion)[ RSS](/packages/chrisgalliano-pion/feed)WikiDiscussions master Synced 2mo ago

READMEChangelog (9)Dependencies (3)Versions (6)Used By (2)

About Pion
----------

[](#about-pion)

Pion - легковесный PHP Framework.

Pion Components
---------------

[](#pion-components)

- [Pion Support](https://plugins.jetbrains.com/plugin/14599-pion-support) plugin for PhpStorm
- [Peony Templating](https://github.com/ChrisGalliano/PeonyTemplating)
- [Muon Forms](https://github.com/ChrisGalliano/MuonForms)

Examples
--------

[](#examples)

- [Pion + Doctrine + Symfony Console + Docker](https://github.com/ChrisGalliano/PionExample)

Pion principles
---------------

[](#pion-principles)

**1. Minimalism**
Pion предоставляет только базовый набор инструментов. Его задача - получить пользовательский request, обработать его и вернуть ответ.
Такой подход проектирования использован умышленно, чтобы защитить ядро фреймворка от тесной интеграции c "лишними" компонентами. Проще говоря - вы без проблем можете использовать ваш любимый templating/ORM/IoC-container/etc. 😄

> Ремарка 1: ➡️ [Pion Example](https://github.com/ChrisGalliano/PionExample), тут вы можете найти "plug and play" пример приложения построенного на связке Pion + Doctrine + Symfony Console + еще пара Symfony компонентов

> Ремарка 2: Для Pion разработан нативный templating компонент - [Peony](https://github.com/ChrisGalliano/PeonyTemplating). Он супер простой и вряд ли подойдет для сложных задач. Но у него есть ряд преимуществ, например [PhpStorm плагин](https://plugins.jetbrains.com/plugin/14599-pion-support) для комплишна переданных во вьюшку переменных. 😉

> Ремарка 3: Возможно в дальнейшем будут разработаны "нативные" ORM/IoC-container/Console/etc. компоненты. В любом случае они будут поставляться в виде отдельных пакетов.

**2. Customizability**
Pion спроектирован с расчетом на то, что практически любой из его внутренних компонентов может быть заменен кастомным.

**3. Muggle principle**
Архитектура фреймворка стремится к уменьшению количества "магии".

> ИМХО: вы должны иметь возможность в любой момент заглянуть "под капот" фреймворка и быстро понять, что там происходит. Без борьбы с "адом обратных вызов"/свалки из абстрактных классов и yaml/array конфигураций.

Pion продвигает идею очевидного flow и контролируемости.

**4. IoC/DI**
Также Pion поддерживает принципы инверсии управления. Это видно на примере использования подкомпонента Arguments Resolver (подробнее о нем ниже). Вкратце - если какой-то экшн требует соединения с базой данных - приложение обязано передать ему экземпляр EntityManager в качестве аргумента.

**5. Foolproof**
Да, Pion предполагает, что вы каждый раз будете наследовать `\Pion\Http\Uri\PionUri` для определения ссылки на каждый экшн. Например. Но благодаря этому вы будете защищены от случайной опечатки в имени GET параметра. Да и переименовывать GET параметры будет значительно легче. 😄

**6. Easy configuration**
Процесс конфигурации Pion очень прост (это же lightweight framework 🙂). При конфигурации не используется yaml/json/ассоциативные массивы. Я глубоко убежден, что это плохая практика, так IDE не резолвит ключи в таких конфигурациях и если вам надо заглянуть "под капот" - приходится использовать текстовый поиск по названию этих ключей. 🤦‍♂️

Вы должны иметь возможность в любой момент использовать "go to declaration" в любом месте конфигурации.

Hello World
-----------

[](#hello-world)

Пока в качестве Hello World - примера выступает репозиторий [Pion Example](https://github.com/ChrisGalliano/PionExample). Можете скачать его себе и запустить в Docker, там есть инструкция. На его примере достаточно легко понять принцип работы фреймворка.

А если вас интересуют детали - продолжайте прокручивать эту документацию 😃

Main Components
---------------

[](#main-components)

### Application

[](#application)

Application - сердце фреймворка. Его задачи:

- Определить action для текущего request-а
- Выполнить action и вернуть его результат

В качестве настроек Application принимает `\Pion\Routing\RoutingInterface` и `\Pion\Actions\Resolver\ActionArgumentsResolverInterface`.

Чтобы обработать request и получить ответ - необходимо вызвать метод `\Pion\Application\ApplicationInterface::dispatch` и передать ему `\Pion\Http\Request\RequestInterface`. Про эти компоненты ниже. ⤵️

### Request

[](#request)

Любая реализация `\Pion\Http\Request\RequestInterface`. Стандартная реализация так и называется - `\Pion\Http\Request\Request`. Предоставляет приложению OOP-style доступ к суперглобальным переменным `$_GET`/`$_POST`/`$_SERVER`/`$_COOKIES`.

### Routing

[](#routing)

Любая реализация `\Pion\Routing\RoutingInterface`. Стандартная реализация - `\Pion\Routing\Routing`. В качестве конфигурации принимает в конструкторе массив объектов, реализующих `\Pion\Routing\Route\RouteInterface`.

**RouteInterface**
У `\Pion\Routing\Route\RouteInterface` есть 3 метода:

- `\Pion\Routing\Route\RouteInterface::path(): string` - возвращает URL path роута. Нужен, чтобы построить URL для этого роута.
- `\Pion\Routing\Route\RouteInterface::isSupported(RequestInterface $request): bool` - определяет, может ли текущий роут обработать переданный request.
- `\Pion\Routing\Route\RouteInterface::action(): \Pion\Actions\ActionInterface` - возвращает объект экшена-обработчика этого роута.

### Actions

[](#actions)

Согласно MVC в приложении должны быть контроллеры, которые получают пользовательский request, выполняют какую-то бизнес логику и возвращают ответ. Как правило в одном контроллере может находиться несколько экшенов, каждый из которых обрабатывает свой Route. Этот подход плох по следующим причинам:

- Классы контроллеров неконтролируемо разрастаются
- Экшены начинают использовать какую-то общую логику, инкапсулированную внутри контроллера. сли такой экшн понадобится вынести в отдельный контроллер - это может стать проблемой.
- Если экшены хранят данные внутри свойств объекта контроллера - это может привести к неочевидным глюкам. Например экшн A помещает в `$this->user` объект авторизованного пользователя. А потом кто-то пытается обратиться к `$this->user` в экшене B и получает NPE. Пример утрирован, но суть, думаю, ясна.

С оглядкой на все это в Pion нет контроллеров - есть Actions. Action реализует `\Pion\Actions\ActionInterface`.

Каждый экшн обязан реализовать 2 метода:

- `\Pion\Actions\ActionInterface::route(): \Pion\Routing\Route\RouteInterface` - возвращает Route настроенный для этого экшена.
- `\Pion\Actions\ActionInterface::__invoke(???): \Pion\Http\Response\ResponseInterface`. Метод `__invoke` не описан в `\Pion\Actions\ActionInterface`, так как может принимать произвольный набор параметров (об этом в блоке Argument resolving). По сути в этом методе мы обрабатываем запрос, выполняем бизнес-логику и возвращаем ответ, который будет отправлен пользователю.

### Argument resolving

[](#argument-resolving)

`\Pion\Actions\ActionInterface::__invoke(???)` - аргументы этого метода могут быть произвольными. В Pion используется механизм называемый *Argument Resolving*. По сути он реализует один из принципов IoC - инъекцию зависимостей. Если ваш экшн зависит, например, от соединения с базой данных - его сигнатура должна выглядеть следующим образом:

```
# ...
public function __invoke(DbConnection $dbConnection): \Pion\Http\Response\ResponseInterface {
  # ...
}
```

При инициализации этого экшена Application обязан передать ему DbConnection. Откуда Application получает эту зависимость?
Выше, в блоке `Application`, я писал, что один из элементов его конфигурации - это `\Pion\Actions\Resolver\ActionArgumentsResolverInterface`.
Контракт этого интерфейса содержит всего 1 метод - `ActionArgumentsResolverInterface::resolve(ActionInterface $action): array`. Его задача проста - определить, какие аргументы нужно передать в метод `__invoke` и вернуть массив этих аргументов, если он может их определить.

Естественно логику определения аргументов не нужно реализовывать самому, для этого есть стандартная реализация - `\Pion\Actions\Resolver\ActionArgumentsResolver`.
В качестве настроек необходимо передать массив `\Pion\Actions\Resolver\Argument\Value\ValueResolverInterface`.
Не буду вдаваться в подробности, скажу вкратце - задача ValueResolver-а вернуть значение для какого-то одного конкретного аргумента в `__invoke`.

У `\Pion\Actions\Resolver\Argument\Value\ValueResolverInterface` конечно есть стандартные реализации, их две.

**ObjectValueResolver**
В качестве аргумента в конструкторе принимает объект, который будет резолвить.

**RequestValueResolver**
В качестве аргумента в конструкторе принимает RequestInterface. Умеет резолвить значения из $\_GET и $\_POST.

**Example:**

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

```
$request = new \Pion\Http\Request\Request();
$dbConnection = new DbConnection(...);
$response = (new \Pion\Application\Application(
  new \Pion\Routing\Routing(
    DeleteUserAction::route()
  ),
  new \Pion\Actions\Resolver\ActionArgumentsResolver(
    new \Pion\Actions\Resolver\Argument\Value\RequestValueResolver($request),
    new \Pion\Actions\Resolver\Argument\Value\ObjectValueResolver($dbConnection)
  )
))->dispatch($request);

# ...

class DeleteUserAction implements \Pion\Actions\ActionInterface {
  public function __invoke(DbConnection $dbConnection, string $userId) : \Pion\Http\Response\ResponseInterface {
    ...
  }
}
```

> P.S. Работать с `$_GET`/`$_POST` параметрами только через ArgumentsResolver не обязательно. Вы можете зарезолвить сам Request `new \Pion\Actions\Resolver\Argument\Value\ObjectValueResolver\ObjectValueResolver($request)` 😄

### Response

[](#response)

> данный интерфейс находится в разработке и пока предоставляет базовый функционал.

Любая реализация `\Pion\Http\Response\ResponseInterface`. В качестве стандартной можно использовать `\Pion\Http\Response\PlainTextResponse` или `\Peony\Response\TemplatedResponse`, если вы используете [Peony](https://github.com/ChrisGalliano/PeonyTemplating). Если вы используете другой темплейтинг - советую реализовать для него `TemplatedResponse` по [примеру](https://github.com/ChrisGalliano/PeonyTemplating/blob/master/src/Response/TemplatedResponse.php).

### URL's

[](#urls)

Для построения URL на экшн предполагается наследовать `\Pion\Http\Uri\PionUri`.
Например [так](https://github.com/ChrisGalliano/PionExample/blob/master/web-app/src/HelloWorld/HelloWorldActionUri.php).

###  Health Score

29

—

LowBetter than 60% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity8

Limited adoption so far

Community13

Small or concentrated contributor base

Maturity64

Established project with proven stability

 Bus Factor1

Top contributor holds 97.1% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~344 days

Total

5

Last Release

1286d ago

Major Versions

0.0.1 → 1.0.02019-04-25

1.1.0-rc.1.1 → 2.0.02020-07-07

### Community

Maintainers

![](https://www.gravatar.com/avatar/68bf617a48168234ad5572a1238add0414dffda90c6d86d22596b9c5cf4ebf4b?d=identicon)[ChrisGaliano](/maintainers/ChrisGaliano)

---

Top Contributors

[![ChrisGalliano](https://avatars.githubusercontent.com/u/17964229?v=4)](https://github.com/ChrisGalliano "ChrisGalliano (68 commits)")[![dependabot[bot]](https://avatars.githubusercontent.com/in/29110?v=4)](https://github.com/dependabot[bot] "dependabot[bot] (2 commits)")

---

Tags

lightweight-frameworklightweight-php-frameworkphpphp-framework

### Embed Badge

![Health badge](/badges/chrisgalliano-pion/health.svg)

```
[![Health](https://phpackages.com/badges/chrisgalliano-pion/health.svg)](https://phpackages.com/packages/chrisgalliano-pion)
```

###  Alternatives

[aws/aws-sdk-php

AWS SDK for PHP - Use Amazon Web Services in your PHP project

6.3k511.3M2.2k](/packages/aws-aws-sdk-php)[sylius/sylius

E-Commerce platform for PHP, based on Symfony framework.

8.4k5.6M647](/packages/sylius-sylius)[saloonphp/saloon

Build beautiful API integrations and SDKs with Saloon

2.4k9.6M467](/packages/saloonphp-saloon)[algolia/algoliasearch-client-php

API powering the features of Algolia.

69333.0M114](/packages/algolia-algoliasearch-client-php)[shopware/platform

The Shopware e-commerce core

3.3k1.5M3](/packages/shopware-platform)[google/cloud-core

Google Cloud PHP shared dependency, providing functionality useful to all components.

343121.4M78](/packages/google-cloud-core)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
