PHPackages                             zikula/wizard - 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. [Utility &amp; Helpers](/categories/utility)
4. /
5. zikula/wizard

AbandonedArchivedLibrary[Utility &amp; Helpers](/categories/utility)

zikula/wizard
=============

Wizard for multi-stage interaction including Symfony Forms

3.1.1(5y ago)947.9k↓50%2MITPHPPHP &gt;=7.2.0

Since Mar 10Pushed 3y ago5 watchersCompare

[ Source](https://github.com/zikula/Wizard)[ Packagist](https://packagist.org/packages/zikula/wizard)[ Docs](https://ziku.la)[ RSS](/packages/zikula-wizard/feed)WikiDiscussions main Synced 1mo ago

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

Added to monorepo
=================

[](#added-to-monorepo)

Wizard has been included into the [core repository](https://github.com/zikula/core/).

Wizard
======

[](#wizard)

The Wizard Component is a management tool for multi-stage user interaction. It utilizes several Interfaces and the Wizard class to create a workflow that is compatible with Symfony Forms and Twig templating. Relying on the concept of **Stages**, the developer is able to define a sequence using a `.yml` file and control that sequence in their Controller.

On instantiation, the Wizard class requires a **StageContainer** and a full path to the **stage definition file**(in yaml format). The Wizard will load the stage definitions from there. The Wizard Component includes a YamlFileLoader for this purpose.

Create a concrete class that extends the `Zikula\Component\Wizard\AbstractStageContainer`. Use autowiring and autoconfiguration to configure the class:

```
_instanceof: # only works for classes that are configured in this file
    Zikula\Component\Wizard\StageInterface:
        tags: ['my_special_tag']

# if this is the only instance of the interface you will use, you can use an alias
Zikula\Component\Wizard\StageContainerInterface: '@Acme\Bundle\MyCustomBundle\Container\FooStageContainer'

Acme\Bundle\MyCustomBundle\Container\FooStageContainer:
    arguments:
        $stages: !tagged_iterator my_special_tag
```

Stage
-----

[](#stage)

A Stage is simply a class which implements the StageInterface. It defines a **name**, a **template name** and any **template parameters** that stage will require. A stage must also define whether it is **necessary** by possibly completing some logic and returning a boolean. Stages marked as NOT **necessary** will be skipped following their instantiation and processing of the `isNecessary()` method, allowing that stage to complete tasks as needed before proceeding. Stages are skipped when the Wizard calls the `getCurrentStage()` method.

Use Symfony autowiring and autoconfiguring or manual Dependency Injection to add services to your stages.

Stages may optionally implement:

- `InjectContainerInterface` if the Stage requires the Symfony container
- `FormHandlerInterface` if the Stage will be using a Symfony Form

The Wizard can be halted in the `isNecessary()` method by throwing an `AbortStageException`. The message of which is available for retrieval using `$wizard->getWarning()`.

Stage Definition File
---------------------

[](#stage-definition-file)

The stage definition file is a simple yaml file. The first key `stages:` is required and then each stage should be listed by `name` and each should have properties `class` and `order`. The `name` key must be the same as the name of the stage as set in its Stage class. The `class` property should be the fully-qualified classname (with namespace) and the `order` property should be an integer identifying the sequential order of the stage. Optionally, a stage can be identified with a `default` property which should be set to true. This stage will be used by the wizard if no stage argument is provided.

### Sample stages.yml

[](#sample-stagesyml)

```
stages:
    prep:
        class: Acme\Bundle\DemoBundle\Stage\PrepStage
        order: 1
        default: true
    getinfo:
        class: Acme\Bundle\DemoBundle\Stage\GetInfoStage
        order: 2
    noform:
        class: Acme\Bundle\DemoBundle\Stage\NoFormStage
        order: 3
    complete:
        class: Acme\Bundle\DemoBundle\Stage\CompleteStage
        order: 4
    nonstage:
        class: Acme\Bundle\DemoBundle\Stage\NonStage
        order: 99
```

### Sample Controller

[](#sample-controller)

```
use Symfony\Component\Form\FormFactoryInterface;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\RouterInterface;
use Zikula\Component\Wizard\FormHandlerInterface;
use Zikula\Component\Wizard\StageContainerInterface;
use Zikula\Component\Wizard\Wizard;
use Zikula\Component\Wizard\WizardCompleteInterface;

class MyController
{
    /**
     * @var StageContainerInterface
     */
    private $stageContainer;

    /**
     * @var \Twig\Environment
     */
    private $twig;

    /**
     * @var FormFactoryInterface
     */
    private $formFactory;

    /**
     * @var RouterInterface
     */
    private $router;

    /**
     * define route = 'index/{stage}'
     */
    public function indexAction(Request $request, $stage)
    {
        // begin the wizard
        $wizard = new Wizard($this->stageContainer, realpath(__DIR__ . '/../Resources/config/stages.yml'));
        $currentStage = $wizard->getCurrentStage($stage);
        if ($currentStage instanceof WizardCompleteInterface) {
            return $currentStage->getResponse($request);
        }
        $templateParams = $currentStage->getTemplateParams();
        if ($wizard->isHalted()) {
            $request->getSession()->getFlashBag()->add('danger', $wizard->getWarning());
            return new Response($this->twig->render('@MyCustomBundle/error.html.twig', $templateParams));
        }

        // handle the form
        if ($currentStage instanceof FormHandlerInterface) {
            $form = $this->formFactory->create($currentStage->getFormType());
            $form->handleRequest($request);
            if ($form->isSubmitted() && $form->isValid()) {
                $currentStage->handleFormResult($form);
                $url = $this->router->generate('index', ['stage' => $wizard->getNextStage()->getName()], true);

                return new RedirectResponse($url);
            }
            $templateParams['form'] = $form->createView();
        }

        return new Response($this->twig->render($currentStage->getTemplateName(), $templateParams));
    }
}
```

[![Flowchart](wizard.png)](wizard.png)

###  Health Score

36

—

LowBetter than 82% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity31

Limited adoption so far

Community19

Small or concentrated contributor base

Maturity63

Established project with proven stability

 Bus Factor1

Top contributor holds 64.7% 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 ~248 days

Recently: every ~157 days

Total

8

Last Release

1983d ago

Major Versions

1.4 → 2.0.02017-06-03

2.0.0 → 3.0.02019-03-05

PHP version history (3 changes)1.4PHP &gt;=5.3.2

2.0.0PHP &gt;=5.4.1

3.0.0PHP &gt;=7.2.0

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/277531?v=4)[Axel Guckelsberger](/maintainers/Guite)[@Guite](https://github.com/Guite)

![](https://www.gravatar.com/avatar/5c734940cf6be6b254dad0d0f6f1b7e2dd10f049946398e30db9d39d76131af4?d=identicon)[craigh](/maintainers/craigh)

![](https://www.gravatar.com/avatar/05bffe6f4f72d34970f0d8f6682b283bd19fbe8c2b2cc7eda48867a3a7f3db4c?d=identicon)[zikula](/maintainers/zikula)

---

Top Contributors

[![Guite](https://avatars.githubusercontent.com/u/277531?v=4)](https://github.com/Guite "Guite (55 commits)")[![craigh](https://avatars.githubusercontent.com/u/350048?v=4)](https://github.com/craigh "craigh (18 commits)")[![github-actions[bot]](https://avatars.githubusercontent.com/in/15368?v=4)](https://github.com/github-actions[bot] "github-actions[bot] (11 commits)")[![cmfcmf](https://avatars.githubusercontent.com/u/2145092?v=4)](https://github.com/cmfcmf "cmfcmf (1 commits)")

---

Tags

phpsymfonysymfony-formswizardSymfony2Formswizardstepstage

### Embed Badge

![Health badge](/badges/zikula-wizard/health.svg)

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

###  Alternatives

[sylius/sylius

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

8.4k5.6M651](/packages/sylius-sylius)[prestashop/prestashop

PrestaShop is an Open Source e-commerce platform, committed to providing the best shopping cart experience for both merchants and customers.

9.0k15.4k](/packages/prestashop-prestashop)[contao/core-bundle

Contao Open Source CMS

1231.6M2.4k](/packages/contao-core-bundle)[ec-cube/ec-cube

EC-CUBE EC open platform.

78527.0k1](/packages/ec-cube-ec-cube)[netgen/layouts-core

Netgen Layouts enables you to build and manage complex web pages in a simpler way and with less coding. This is the core of Netgen Layouts, its heart and soul.

3689.4k10](/packages/netgen-layouts-core)[netgen/content-browser

Netgen Content Browser is a Symfony bundle that provides an interface which selects items from any kind of backend and returns the IDs of selected items back to the calling code.

14112.1k8](/packages/netgen-content-browser)

PHPackages © 2026

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