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

Wizard Bundle Laravel Package

gnugat/wizard-bundle

A Symfony bundle for building multi-step wizards. Define ordered steps, guide users through a sequence of forms or actions, and keep navigation and flow logic organized within your Symfony application.

View on GitHub
Deep Wiki
Context7

Getting Started

Start with an honest framing: this is not a Laravel package. gnugat/wizard-bundle is a Symfony 2 bundle, and its own README is tagged [DEPRECATED] use Symfony Flex instead. It expects app/AppKernel.php, app/console, and Symfony's Bundle/Kernel contracts. You cannot composer require it into a Laravel app and expect anything to happen — there is no service provider, no facade, no Artisan command.

So the practical "getting started" for a Laravel developer is:

  1. Read the README once to understand the problem it attacked: the Symfony 2 bundle-install ritual of composer require → register in AppKernel → append config → append routing → publish assets, collapsed into one interactive command.
  2. Skim two places first: Command/InstallCommand.php (the entry point and CLI contract) and the Wizard/ directory (the step classes that do the actual file mutations). Everything else is Symfony 2 plumbing you can ignore.
  3. Treat it as a reference design, then map each of its steps onto the Laravel feature that already covers it — package discovery, vendor:publish, and provider boot().

First concrete use case: you maintain an internal package that isn't on Packagist, and you want php artisan acme:install to wire it up in one shot. Read this bundle's step model — a small set of composable, individually re-runnable steps — before writing your own install command.

If you genuinely want to run it (to study the diffs), you need a Symfony 2.x app:

composer require --dev gnugat/wizard-bundle

# register the wizard itself in app/AppKernel.php, then:
php app/console wizard:install acme/foo-bundle

Then git diff the app/AppKernel.php change. That diff is the whole value proposition.

Implementation Patterns

Pattern 1 — One command install, mapped to Laravel package discovery

The wizard's core behavior: take a package name, run composer require, detect the bundle class from the naming convention (acme/foo-bundle → Acme\FooBundle\AcmeFooBundle), and register it. Laravel solved this natively in 5.5 with package auto-discovery, so the day-to-day move is to declare it in the package's own composer.json and do nothing else:

{
    "extra": {
        "laravel": {
            "providers": ["Acme\\Foo\\FooServiceProvider"],
            "aliases": { "Foo": "Acme\\Foo\\Facades\\Foo" }
        }
    }
}

The consuming app then only runs composer require acme/foo. No source-file mutation, no wizard. If a consumer needs to opt out, they don't edit config/app.php — they add:

{
    "extra": {
        "laravel": { "dont-discover": ["acme/foo"] }
    }
}

Pattern 2 — Dev/test-only registration

The wizard inserted new AcmeFooBundle(), into the dev array rather than the production $bundles array. The Laravel equivalent is an environment guard inside the provider:

public function register(): void
{
    if ($this->app->environment(['local', 'testing'])) {
        $this->app->register(\Acme\Foo\DebugServiceProvider::class);
    }
}

Pair this with dont-discover in the consuming app if the package should never auto-register in production.

Pattern 3 — Step orchestration → an Artisan install command

Instead of templating edits into AppKernel, package the "post-install wiring" as an explicit command that composes idempotent vendor:publish calls:

class InstallCommand extends Command
{
    protected $signature = 'foo:install {--force : Overwrite published files}';
    protected $description = 'Publish Foo config, migrations and assets';

    public function handle(): int
    {
        $this->call('vendor:publish', [
            '--provider' => \Acme\Foo\FooServiceProvider::class,
            '--tag'      => 'foo-config',
            '--force'    => $this->option('force'),
        ]);

        $this->call('vendor:publish', [
            '--provider' => \Acme\Foo\FooServiceProvider::class,
            '--tag'      => 'foo-migrations',
        ]);

        if ($this->confirm('Run migrations now?', true)) {
            $this->call('migrate');
        }

        $this->info('Foo installed. Add FOO_API_KEY to .env.');
        return self::SUCCESS;
    }
}

The wizard's lesson that carries over: keep each step small, make it safe to re-run, and print exactly what changed.

Pattern 4 — Config merging instead of config appending

The wizard appended YAML to config.yml. Laravel's equivalent is mergeConfigFrom() in the provider plus a publishes() tag for the overridable copy:

public function register(): void
{
    $this->mergeConfigFrom(__DIR__.'/../config/foo.php', 'foo');
}

public function boot(): void
{
    $this->publishes([
        __DIR__.'/../config/foo.php' => config_path('foo.php'),
    ], 'foo-config');
}

Consumers get sane defaults without touching a file, and can publish when they need to override.

Pattern 5 — Wire the discovery hook

If you copy the "one command" idea, hook it into Composer the way Laravel core does:

{
    "scripts": {
        "post-autoload-dump": [
            "Illuminate\\Foundation\\ComposerScripts::postAutoloadDump",
            "@php artisan package:discover --ansi"
        ]
    }
}

Gotchas and Tips

  • Do not add this to a dependency graph. Deprecated upstream, zero dependents, single maintainer, and PHP 5.x/Symfony 2 constraints. On a modern Laravel app composer require will either refuse on platform constraints or install dead code. There is no support channel if it breaks.
  • The naming convention is the magic, and it's brittle. The bundle guesses the class name from the Composer package name (acme/foo-bundle → Acme\FooBundle\AcmeFooBundle). Any package that doesn't follow the convention silently fails to register. This is exactly the fragility Symfony Flex recipes and Laravel's explicit extra.laravel.providers were created to eliminate — prefer explicit declarations over conventions in anything you build.
  • It mutates source files. The wizard edits AppKernel.php and appends to config/routing files. There is no dry-run, diff preview, or uninstall path. If you build an installer, make those first-class: --dry-run, --diff, and a documented uninstall. This is the single most valuable takeaway from studying the package.
  • Not idempotent by design. Re-running an install command that appends to files produces duplicate registrations. Guard every step you write: check for an existing entry before inserting, and let vendor:publish handle overwrite semantics via --force.
  • Debugging is opaque. When "magic" install steps fail you get generic console output, not a stack trace pointing at the offending step. If you write an install command, wrap each step and report precisely which one failed and what file it was touching.
  • Don't translate the Symfony question helpers literally. Symfony Console's question API maps roughly to Laravel Prompts (text(), select(), confirm(), suggest()), which is cleaner and has better UX. Use Prompts rather than hand-rolling $this->ask() chains — and use confirm() defaults deliberately so the "just press enter" path is the safe one.
  • Environment/version drift is the real killer. Any package pinning old Symfony/PHP versions becomes a blocked framework upgrade six months later. Keep install tooling on first-party primitives (Composer scripts, Artisan, Prompts) with no third-party coupling.
  • Use it as a bounded design study, not a dependency. One engineer-day reading Command/InstallCommand.php and Wizard/ yields a requirements list for your own installer: idempotency, dry-run/diff, explicit class declarations over conventions, clear failure messages, and an uninstall path. After that, close it out.
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.
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings
coleus/apps
seampact/laravel
emmyconceptng/laravel-ng-postcode
jjsquady/round-robin
skyraptor/chatter
edlugz/sasapay
abbasudo/artisan-route