myvars / form-flow
Generic Symfony controller-flow coordinators (Form/Action/Confirm/Search/InlineEdit) — the FormFlow pattern.
Requires
- php: >=8.5
- pagerfanta/core: ^4
- symfony/config: ^8.1
- symfony/dependency-injection: ^8.1
- symfony/form: ^8.1
- symfony/http-foundation: ^8.1
- symfony/http-kernel: ^8.1
- symfony/object-mapper: ^8.1
- symfony/options-resolver: ^8.1
- symfony/routing: ^8.1
- symfony/security-csrf: ^8.1
- symfony/ux-turbo: ^3.1
- twig/twig: ^3
Requires (Dev)
- friendsofphp/php-cs-fixer: ^3.95
- phpstan/phpstan: ^2.2
- phpstan/phpstan-symfony: ^2.0
- phpunit/phpunit: ^13.1
This package is auto-updated.
Last update: 2026-06-04 19:41:10 UTC
README
Thin controllers, consistent flows. myvars/form-flow is a small Symfony bundle that factors the
repetitive parts of CRUD-style controllers — form handling, validation feedback, CSRF-guarded
confirmation, pagination, Turbo-aware redirects — into five reusable flow coordinators. Your
controller actions stay one call long, and every create/update/delete action follows the same shape.
#[Route('/task/new', name: 'app_demo_task_new', methods: ['GET', 'POST'])] public function new(Request $request, CreateTaskMapper $mapper, CreateTaskHandler $handler, FormFlow $flow): Response { return $flow->form( request: $request, formType: TaskType::class, data: new TaskForm(), mapper: $mapper, // form DTO -> command handler: $handler, // command -> ResultInterface context: FlowContext::forCreate(FlowModel::create('demo', 'task')), ); }
The five flows
| Flow | Purpose |
|---|---|
FormFlow |
Create/update with Symfony forms — validate, map to a command, dispatch, flash, redirect |
ActionFlow |
State transitions without a form (approve, complete, …) |
ConfirmFlow |
Confirm-then-execute (delete, cancel, rewind, …) with per-action CSRF scoping |
SearchFlow |
Paginated index pages from a Pagerfanta adapter |
InlineEditFlow |
Single-field inline editing over Turbo Frames |
Design
The package owns logic only. It depends on framework packages, Pagerfanta and its own Contract\
ports — never on application code. The consuming app supplies two things:
- Adapters for the ports (
ResultInterface,RedirectTargetInterface,FlasherInterface,SearchCriteriaInterface), which Symfony autowires by interface. - Templates — the bundle ships design-neutral defaults so flows render out of the box; your app
overrides any of them by placing its own styled version at the same
templates/shared/form_flow/...path (yourtemplates/wins). See docs/templates.md.
This keeps the flows decoupled from your domain, your DTOs and your design system.
Requirements
- PHP 8.5+
- Symfony 8.1+ (Form, HttpFoundation, Routing, Security CSRF, Twig, UX Turbo)
Installation
composer require myvars/form-flow
Enable the bundle (if Symfony Flex did not):
// config/bundles.php return [ // ... MyVars\FormFlow\FormFlowBundle::class => ['all' => true], ];
Then provide the port adapters and templates — see docs/installation.md.
Documentation
- Installation & wiring — bundle setup, the adapters you implement, path-repo/Docker notes
- Using the flows — a worked controller example for every flow, plus
FlowContext/FlowModel - Ports & adapters — implementing
Result,RedirectTarget,Flasher,SearchCriteria - Template contract — required templates and the variables passed to them
Quality
composer test # PHPUnit — unit, flow and bundle-integration suites composer phpstan # PHPStan level 7 composer cs # php-cs-fixer (dry-run)
License
Released under the MIT License.