Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Pageflower Bundle Laravel Package

phpmentors/pageflower-bundle

A Symfony bundle from PHP Mentors that integrates Pageflower into Symfony applications. It supplies bundle configuration and service wiring for Pageflower's page-oriented features, helping developers add consistent page handling and navigation to PHP projects.

View on GitHub
Deep Wiki
Context7

Getting Started

Pageflower is a Spring-Web-Flow-style pageflow engine: you declare flows (pages + transitions + guards) in config, and the engine controls which page a request is allowed to reach and where it redirects. phpmentors/pageflower-bundle is a thin Symfony integration layer over the phpmentors/pageflower core, so expect to read two READMEs: this bundle's, then the core library's.

Minimal path:

  1. Check compatibility before anything else. The last release is 2020-06-19, which puts it in the Symfony 4.x / early 5.x window. Confirm against your app:
    composer require phpmentors/pageflower-bundle --dry-run
    composer why-not phpmentors/pageflower-bundle
    
  2. Install and register the bundle (Symfony 4/5 style config/bundles.php; older skeletons use AppKernel):
    PhpMentors\PageflowerBundle\PageflowerBundle::class => ['all' => true],
    
  3. Configure a flow definition path. The bundle expects flow YAML in your config tree, something like:
    # config/packages/phpmentors_pageflower.yaml
    phpmentors_pageflower:
        flows:
            checkout:
                definition: '%kernel.project_dir%/config/pageflows/checkout.yaml'
    
  4. Write one flow. The smallest useful case is a two-page wizard with a guard:
    # config/pageflows/checkout.yaml
    checkout:
        pages:
            cart:
                transitions:
                    next: { to: shipping, guard: cart_is_not_empty }
            shipping:
                transitions:
                    back: { to: cart }
                    next: { to: confirm }
    
  5. First use case: multi-step checkout, onboarding, or any wizard where "can the user be on this page right now?" is a real question. That is the only thing this package is for; if you just need routing plus session state, native Symfony routing is cheaper.

Where to look first, in order: README.md of the bundle (it is short and mostly install + one example), then the core phpmentors/pageflower repo's tests/ — for a 5-star package, the tests are the actual documentation for guard/transition semantics.

Implementation Patterns

Pages are controller actions, not entities. Each page in the flow maps to a route/controller. The engine's job is to evaluate the incoming transition, run guards, and either dispatch the page or redirect back to the last valid page. Keep controllers thin; the flow owns sequencing, controllers own rendering.

Guards as services. A guard is a named service whose method returns whether a transition may fire. Pattern:

final class CartIsNotEmpty implements GuardInterface
{
    public function __construct(private Cart $cart) {}

    public function evaluate(): bool
    {
        return !$this->cart->isEmpty();
    }
}

Register with the tag the bundle documents (verify the exact tag name with bin/console debug:container --tag=<tag> — this is where the 2020-era docs are thinnest).

Flow state lives in session scope. The engine tracks the current page per flow instance. Treat the session as the source of truth for navigation position only; never put domain data there. On logout or "start over," explicitly reset the flow rather than relying on garbage collection.

Redirect-after-POST is the engine's default posture. Do not try to render a page directly on a POST; let the transition fire and redirect. If you fight this you will get double-submit bugs that look like engine bugs.

Integration tip — version your flows. Because in-flight sessions reference page names, renaming a page while users are mid-flow strands them. Either namespace flow names (checkout_v2) and migrate, or add a guard on entry that resets unknown state.

Testing pattern. Two layers: unit-test guards in isolation (they are plain services), and write one functional test per flow that walks happy path + one guard-rejection path. Assert on redirect targets, not rendered HTML, because the engine's observable behavior is the redirect.

Porting note for Laravel developers. There is no Laravel analog packaged here, and PageflowerBundle is Symfony DI + HttpKernel coupled. If you are evaluating it for a Laravel codebase, you are evaluating the concept (declarative flows + guards) and will be reimplementing it on top of middleware, not installing it. The core phpmentors/pageflower library is framework-agnostic in principle; the bundle is the part you would leave behind.

Gotchas and Tips

  • Maintenance risk is the headline. 5 stars, 0 dependents, last release 2020. BSD-2-Clause means you can fork and vendor it freely — plan on that rather than on upstream fixes. Clone it into src/ or a VCS repository entry if install constraints block you.
  • Composer will lie to you gently. A require that resolves on Symfony 5.4 may still explode on Symfony 6/7 attribute and return-type changes. Run the test suite of a two-page flow before committing to it anywhere real.
  • Service IDs aren't discoverable from the README. Use bin/console debug:container | grep -i pageflow and debug:router to find what the bundle actually registered. Do not copy class names from blog posts; they drift between the core library and the bundle.
  • Guard name typos fail late. A missing guard service typically surfaces as a runtime exception at transition time, not at container compile time. Add a smoke test that instantiates every flow definition.
  • Debugging transitions: log at the point where a transition is selected and where a guard returns false. When a user "can't get to the next step," it is almost always a false guard or a stale session position — those two log lines answer it in seconds.
  • Don't mix YAML and annotation flow definitions in one project unless the README explicitly supports it; the loader precedence is undocumented and you'll spend an afternoon on it.
  • Extension points worth knowing: the guard interface, the flow definition loader (if you want JSON/PHP-array flows), and the scope/session storage (if you need server-side persistence instead of session). Those three are where 90% of real customization lands.
  • Escape hatch: if the engine's control over redirects becomes the constraint, you can keep the flow YAML as pure documentation and call guards directly from a hand-rolled middleware order. That degrades gracefully and is a reasonable exit plan for a package this small.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource
noith/settings