Skeleton of a character manager for games

Fund package maintenance!

Installs: 1 787

Dependents: 0

Suggesters: 0

Security: 0

Stars: 8

Watchers: 3

Forks: 1

Open Issues: 0


v3.0.0 2023-02-06 22:04 UTC


Latest Stable Version Build Status Coverage Status Scrutinizer Code Quality SensioLabsInsight License

Character manager bundle

This bundle is here to provide a customizable skeleton to create characters based on a list of actions representing each step of character creation.

You can configure your steps both from configuration and services.


  • Install the bundle
    If you are using Symfony with Flex, all you have to do is composer require pierstoval/character-manager.
    If you do not have Flex, please refer to the next steps.

  • Add it to your Kernel:

    class AppKernel extends Kernel
        public function registerBundles()
            $bundles = [
                // Sorry for the very long name.
                new Pierstoval\Bundle\CharacterManagerBundle\PierstovalCharacterManagerBundle(),
  • Create a Character class, for your first character manager:

    namespace App\Entity;
    use Pierstoval\Bundle\CharacterManagerBundle\Model\CharacterInterface;
    class Character implements CharacterInterface
        // Implement interface methods
  • Pro tip: You can also extend the abstract class Pierstoval\Bundle\CharacterManagerBundle\Entity\Character, which already implements the different methods AND is already a Doctrine ORM Entity for which you just have to add your own id property.

  • Load the routing file:

         resource: "@PierstovalCharacterManagerBundle/Resources/config/routing.xml"
         prefix:   /character_generator/    # Or any prefix you like

    This routing file is important because it is the place where character generation will be handled.
    Note: You can add the {manager} route option to your url prefix, when using multiple character managers.

  • You're set for the base setup!
    Now you have to create your Step actions, for you to be able to generate a character

Character generation

Step actions

To generate characters, you need what are called Step Action classes.

One generation step = one class.

Each class must implement StepActionInterface, but you can also extend the abstract class AbstractStepAction which implements the interface and adds cool logic, so you just have to implement the execute() method.

You can define it at a simple class like this:

            character_class: 'App\Entity\Character'
                    action: App\Step\Step01

You can also refer to an already existing service:

            character_class: 'App\Entity\Character'
                    action: app.steps.step_1

        class: App\Step\Step01
            - ...

💯 Note: You should know that all action classes that are not set as service will be defined as service, autowired and set private, because it is mandatory for the ActionRegistry to have them as services.
However, your services will be untouched, to keep consistency with your own logic.

💠 Magic

Important things about steps

Step configuration reference:

        # Prototype
            character_class:      ~ # Required
                # Prototype
                    # Can be a class or a service. Must implement StepActionInterface or extend abstract Action class.
                    action:               ~ # Required
                    label:                ''
                    # Steps that the current step may depend on. If step is not set in session, will throw an exception.
                    dependencies:           []
                    # When this step will be updated, it will clear values for specified steps.
                    # Only available for the abstract class
                    onchange_clear:       []
  • Step name must be unique for each character manager. You can refer to it in the application, so be sure it is verbose enough for you, and more informative than just "Step 1", "Step 2", etc.
  • Steps order matter! The step number starts at 1 and if you change the order of a step, the whole order will change. Keep this in mind when using the AbstractStepAction::goToStep($stepNumber) method (see below).
  • The onchange_clear parameter is only handled in the abstract AbstractStepAction class, but you can implement it manually in your StepActionInterface::execute() method for example.

AbstractStepAction class

This is an example of a basic action:


namespace App\Step;

use Pierstoval\Bundle\CharacterManagerBundle\Action\AbstractStepAction;
use Symfony\Component\HttpFoundation\Response;

class Step1 extends AbstractStepAction
     * {@inheritdoc}
    public function execute(): Response
        // Implement your step logic here.
        return new Response('This step is now rendered');

What is injected in the AbstractStepAction class

When you have defined all your character managers configurations, the StepsPass will process them and execute certain actions:

  • Check if your action is an existing class extending StepActionInterface.
    If it exists and is not defined as a service, it will:

    • Define it as a service
    • Make the service private, autowired and lazy.

    If it is already defined as a service, it will not do something else than the next steps:

  • For all actions, now they should be defined as services, so the compiler pass will process them:

    • If it extends the AbstractStepAction class, it will also inject:
      • The router if available (via the RouterInterface)
      • The entity manager if available (it actually injects the ObjectManager, so works with both ORM and ODM).
      • The translator (it should already be available via TranslatorInterface, even if not enabled in the framework).
      • The Twig environment, if available.
    • It will inject the step configuration:
      • The character_class option
      • The Step object, retrieved from the StepActionResolver
      • All steps from this manager, again retrieved from the StepActionResolver. They're mostly used to manage the goToStep() and nextStep() methods in the abstract action class.
      • Add the action to the ActionRegistryInterface service registered in the container.

And the abstract class has cool new methods, too.


First, you must know that the AbstractStepAction has no constructor.

Then, you're free to have your own constructor without being forced to rely on the parent's logic, and inject all your necessary services and parameters in the constructor, via autowiring.

The abstract class only adds some nice stuff to use (and if someone don't extend it, send me a message, I'd like to hear why you don't want to extend it), and this cool logic resides in other methods.

So you're free to implement your own constructor, especially if you define your action as a service

Injected services

If you define the step action as a service and extend the abstract class, you will have access to four services:

/** @var EntityManager */

/** @var Twig\Environment */

/** @var RouterInterface */

/** @var TranslatorInterface */

Most of the time, you don't need many other things, but if you need other things, just add the arguments: or calls: options to your service definition.

The cool methods of the AbstractStepAction class

The abstract class adds cool methods to manage your steps:

/** @var $this \Pierstoval\Bundle\CharacterManagerBundle\Action\AbstractStepAction */

// Get the character property for specified step name (or current step by default)
$this->getCharacterProperty($stepName = null);

// Returns a RedirectResponse object to the next step

// Returns a RedirectResponse object to the specified step, but by number, not by name

// A cool tool to use flash messages. By default, the "type" is "error".
// All flash messages are translated and the translation domain is set in the StepAction::$translationDomain static property.
// Of course you can override the translation domain if you create your own abstract StepAction class and override this var.
$this->flashMessage($msg, $type = null, array $msgParams = []);

// Updates the current character step value and sets it to $value
// This is the method that makes sure that "onchange_clear" steps are cleared with a simple "unset()" in the session


A list of "todos":

  • Add a factory, a service, or whatever, which goal will be to handle converting the final step submission into a proper Character object. Abstract, obviously, because it has to be implemented manually by the user.
  • Try to find a way to reduce the size of the controller class
  • Create lots of character managers for different games so we find the flaws of this bundle and rip them off! (help appreciated 😁 )


The project is published under MIT license. See the license file for more information.