Bundle to integrate Tactician with Symfony projects

Related tags

API tactician-bundle
Overview

TacticianBundle

Build Status Scrutinizer Code Quality

Symfony2 Bundle for the Tactician library https://github.com/thephpleague/tactician/

Installation

Step 1: Download the Bundle

Open a command console, enter your project directory and execute the following command to download the latest stable release for this bundle:

$ composer require league/tactician-bundle

This command requires you to have Composer installed globally, as explained in the installation chapter of the Composer documentation.

Step 2: Enable the Bundle

Then, enable the bundle by adding it to the list of registered bundles in the app/AppKernel.php file of your project:

<?php
// app/AppKernel.php

// ...
class AppKernel extends Kernel
{
    public function registerBundles()
    {
        $bundles = array(
            // ...

            new League\Tactician\Bundle\TacticianBundle(),
        );

        // ...
    }

    // ...
}

Using the Command Bus

Create a service and inject the command bus:

services:
    app.your_controller:
        class: AppBundle\Controller\YourNameController
        arguments:
            - '@tactician.commandbus'

Then pass a command to the command bus for execution:

<?php namespace AppBundle\Controller;

use League\Tactician\CommandBus;
use AppBundle\Commands\DoSomethingCommand;

class YourNameController
{
    private $commandBus;

    public function __construct(CommandBus $commandBus)
    {
        $this->commandBus = $commandBus;
    }

    public function doSomething()
    {
        $command = new DoSomethingCommand();
        $this->commandBus->handle($command);
    }
}

Autowiring

If Symfony autowire feature is enabled (available from Symfony 2.8), instead of creating a service for each controller using the default commandbus you can inject and use it as follows:

<?php namespace AppBundle\Controller;

use League\Tactician\CommandBus;
use AppBundle\Commands\DoSomethingCommand;

class YourNameController
{
    public function doSomething(CommandBus $commandBus)
    {
        $command = new DoSomethingCommand();
        $commandBus->handle($command);
    }
}

Note that this only works for the default commandbus, if you want to inject other than the default one you can override the config through an alias with:

services:
    League\Tactician\CommandBus: '@tactician.commandbus.your_commandbus'

If you have multiple buses, you can use named parameter aliases by using the bus name as part of the parameter name. For example, if you want to inject the command bus named default, name the parameter defaultBus. The syntax always follows {bus_name}Bus.

This feature is only available from Symfony 4.2

<?php namespace AppBundle\Controller;

use League\Tactician\CommandBus;

class YourNameController
{
    public function doSomething(CommandBus $defaultBus)
    {
        //
    }
}

Configuring Command Handlers

When you pass a command to Tactician, the ultimate goal is to have it mapped to a Handler.

Since handlers often have extra dependencies and are best lazily-loaded, you'll want to register them in the service container.

There's a few different ways to map your Commands to a Handler, all of which can be combined. We'll walk through them below:

1. Manually Mapping

Let's say we have two classes, RegisterUserCommand and RegisterUserHandler. We'll register the Handler in the service container, along with a repository it needs.

foo.user.register_user_handler:
    class: Foo\User\RegisterUserHandler
    arguments:
        - '@foo.user.user_repository'

However, we still need to map the Command to the Handler. We can do this by adding a tag to the Handler's DI definition.

The tag should have two attributes: the tag name, which should always be tactician.handler, and the command, which should be the FQCN of the Command.

foo.user.register_user_handler:
    class: Foo\User\RegisterUserHandler
    arguments:
        - '@foo.user.user_repository'
    tags:
        - { name: tactician.handler, command: Foo\User\RegisterUserCommand }

2. Map Based On Typehints

Rather than repeating the command's full class name, we can also reflect on the Handler's method typehints.

foo.user.register_user_handler:
    class: Foo\User\RegisterUserHandler
    arguments:
        - '@foo.user.user_repository'
    tags:
        - { name: tactician.handler, typehints: true }

This detects what commands this handler receives by inspecting the class' methods. The rules for matching are:

  1. The method must be public.
  2. The method must accept only one parameter.
  3. The parameter must be typehinted with a class name.

In other words, the RegisterUserHandler class should look like this:

<?php
class RegisterUserHandler
{
    public function handle(RegisterUser $command)
    {
       // do stuff
    }
}

If you have multiple commands going into a single handler, they will all be detected, provided they follow the rules above. The actual name of the method is NOT important.

If you're using typehints AND FQCN mappings, then the FQCN mapping always wins out.

Registering by typehints can be very useful if you're using the autowiring features in the latest versions of Symfony.

3. Custom Mapping Rules

If you'd like to define your own rules for automatically mapping commands to handlers in the container, you can do that as well.

First, implement the HandlerMapping interface. During compile time, you'll receive a ContainerBuilder and a Tactician Router object you can use to map your commands to your handler services.

There's a good chance that your strategy will involve using container tags of some sort. If that's the case, look into extending the TagBasedMapping abstract class. This will save you some of the boiler plate associated with handling multiple buses.

Once your object is ready, pass it to the TacticianBundle instance when setting your AppKernel.php:

<?php
// app/AppKernel.php

// ...
class AppKernel extends Kernel
{
    public function registerBundles()
    {
        $bundles = array(
            // ...
            new League\Tactician\Bundle\TacticianBundle(
                new My\Custom\HandlerMapping()
            ),
        );
    }
}

4. Combining Mapping Strategies

If you have multiple strategies you'd like to chain together, you can use the CompositeMapping object to chain them together.

<?php
// app/AppKernel.php

// ...
class AppKernel extends Kernel
{
    public function registerBundles()
    {
        $bundles = array(
            // ...
            new League\Tactician\Bundle\TacticianBundle(
                new League\Tactician\Bundle\DependencyInjection\HandlerMapping\CompositeMapping(
                    new League\Tactician\Bundle\DependencyInjection\HandlerMapping\ClassNameMapping(), // standard command: "FQCN" mapping
                    new League\Tactician\Bundle\DependencyInjection\HandlerMapping\TypeHintMapping(), // standard typehints: true mapping
                    new My\Custom\HandlerMapping() // your custom routing
                )
            ),
        );
    }
}

If multiple HandlerMapping strategies detect the same Command, but different Handlers, then the last mentioned mapping strategy wins. Therefore, it's usually best to put your custom strategy last OR the ClassNameMapping last so you can make full overrides when necessary.

5. Write Your Own Middleware

Remember, Tactician is based purely on middleware. If you don't want to mess around with all this and you have a simple convention based way of mapping commands to handlers, just write your own middleware to execute Handlers.

Checking your wiring

You can run the debug:tactician command to get a list of which commands are mapped to which services.

Configuring Middleware

Everything inside Tactician is a middleware plugin. Without any middleware configured, nothing will happen when you pass a command to $commandBus->handle().

By default, the only Middleware enabled is the Command Handler support. You can override this and add your own middleware in the app/config.yml.

tactician:
    commandbus:
        default:
            middleware:
                # service ids for all your middlewares, top down. First in, last out.
                - tactician.middleware.locking
                - my.custom.middleware.plugin
                - tactician.middleware.command_handler

Important: Adding your own middleware is absolutely encouraged, just be sure to always add tactician.middleware.command_handler as the final middleware. Otherwise, your commands won't actually be executed.

Check the Tactician docs for more info and a complete list of middleware.

Configuring Multiple Command Buses

The bundle is pre-configured with a command bus called "default", with the service id tactician.commandbus. Some users want to configure more than one command bus though.

Let's say you're integrating a remote accounting system into your application and you'd like to use a separate command bus for just those commands. You can wire up two command buses like this:

You can do this via configuration, like so:

tactician:
    commandbus:
        default:    # the "regular" command bus in your application
            middleware:
                - tactician.middleware.validator
                - tactician.middleware.command_handler
        accounting: # the command bus for accounting specific commands
            middleware:
                - tactician.middleware.locking
                - some.middleware.service.to.call.the.remote.accounting.app
                - tactician.commandbus.accounting.middleware.command_handler # Because "tactician.middleware.command_handler" refers to the default bus

The configuration defines two buses: "default" and "accounting". These buses will be registered as the tactician.commandbus.default and tactician.commandbus.accounting services respectively.

Take note that each bus now has configured their own command handler middleware: tactician.middleware.command_handler for the default and tactician.commandbus.accounting.middleware.command_handler for the account one.

If you want, you can also change which command handler is registered to tactician.commandbus. You can do this by setting the default_bus value in the configuration, like so:

tactician:
    default_bus: accounting
    commandbus:
        default:
            middleware:
                # ...
        accounting:
            middleware:
                # ...

By default, all commands are available in each bus. If you want to make a command available only to a specific bus, you need to specify its id :

foo.user.register_user_handler:
    class: Foo\User\RegisterUserHandler
    arguments:
        - '@foo.user.user_repository'
    tags:
        - { name: tactician.handler, command: Foo\User\RegisterUserCommand, bus: accounting }

and you will be able to handle this command only on the accounting bus:

$bus = $container->get('tactician.commandbus.accounting');
$bus->handle(new Foo\User\RegisterUserCommand('my', 'arguments'));

Extra Bundled Middleware

This bundles ships with a few pre-configured middlewares. To enable them, add them to the middlewares list in your bus configuration (see Configuring Middleware)

Validator Middleware (tactician.middleware.validator)

This middleware uses Symfony's validator to check the command object before passing it along. In practice, this means you can add any Symfony validator annotations to your command to ensure it's fully correct before execution. This isn't a full replacement for writing your objects in an internally consistent style but it can be very helpful.

Constraints can be added via configuration or annotations like in default Symfony practices, please refer to their docs.

If the command fails, it will throw a League\Tactician\Bundle\Middleware\InvalidCommandException. This exception also contains the ConstraintViolationList produced by the validator so you can inspect or log the errors yourself.

Locking Middleware (tactician.middleware.locking)

This middleware is bundled in Tactician, please refer to the official documentation for details.

Logger Middleware (tactician.middleware.logger)

This middleware is bundled in Tactician, please refer to the official documentation for details.

Security Middleware (tactician.middleware.security)

The security middleware will perform authorization on handling all commands. By default an AccessDenied exception will be thrown if the user is not authorized.

tactician:
    security:
        My\User\Command:
            - 'ROLE_USER'
        My\Admin\Command:
            - 'ROLE_ADMIN'
        My\UserAndAdmin\Command:
            - 'ROLE_USER'
            - 'ROLE_ADMIN'

This middleware is based on Symfony's AccessDecisionManager and voter system. We recommend familiarizing yourself with it before trying to use this middleware. If you'd like to configure more complex scenarios, consider implementing a custom Symfony voter.

As a precaution, the middleware requires you to register the command in the security configuration before it will be evaluated by Symfony's AccessDecisionManager.

Furthermore, while the security middleware is based on trusted components, we always recommend a defense in depth strategy. Simply hooking your command bus up to a public web endpoint and relying fully on this middleware may not be sufficient coverage for your application.

The Security middleware is disabled by default.

Command Handler Middleware (tactician.middleware.command_handler)

Always ensure this is the last middleware listed

This is the plugin that actually matches your command to a handler and executes it. If you have complex matching logic, feel free to implement your own variant and leave this middleware off.

However, for 99% of users, this should be enabled and set as the last middleware in the list.

Customizing the MethodNameInflector used by the tactician.middleware.command_handler middleware

By default, the bundle uses HandleInflector from Tactician core. That is to say, it expects your Command Handlers to have a handle() method that receives the command to execute.

However, if you prefer a different inflector, you can pass the service name in config.yml.

tactician:
    method_inflector: my_inflector.service.id

Tactician core offers a list of custom Inflectors, all of which are supported in this bundle. Assuming a class called My\App\RegisterUserCommand(), the invoked methods on the handler would be:

  • tactician.handler.method_name_inflector.handle - handle()
  • tactician.handler.method_name_inflector.handle_class_name - handleRegisterUserCommand()
  • tactician.handler.method_name_inflector.handle_class_name_without_suffix - handleRegisterUser()
  • tactician.handler.method_name_inflector.invoke - __invoke()

While handle() is a reasonable default, using one of the class name methods allows you to handle multiple commands on a single class (possibly useful if they share common dependencies or fit together in some fashion). Likewise, __invoke can be useful if you're mapping to a list of closures.

When using multiple buses, you can also specify the method_inflector of particular bus :

tactician:
    commandbus:
        command:
            middleware:
                - tactician.middleware.command_handler
        query:
            middleware:
                - tactician.middleware.command_handler
            method_inflector: tactician.handler.method_name_inflector.handle_class_name_without_suffix

Testing

$ ./vendor/bin/phpunit

Security

Disclosure information can be found on the main Tactician repo.

License

The MIT License (MIT). Please see License File for more information.

Comments
  • Security middleware

    Security middleware

    This will close #23

    I'm currently thinking about how to implement the actual security checks, I see several options:

    • Add a Voter that reads out some config that maps commands to roles and check if the user has the required roles. This would put all security logic in the security system.
    • Instead of the Voter the mapping could be injected into the middleware, allowing the isGranted call to be called with the required role instead of the current handle. People are used to having isGranted called with a role attribute, so the approach is familiar. But not all security will be in the security system, some will be in the commandbus middleware.
    • Add a SecuredCommand interface that has a method getRequiredRole, call isGranted on that role. Such an approach would be easy to understand and use. But we won't have:

    image

    What do you think?

    opened by RonRademaker 19
  • [WIP] tactician:debug CLI helper

    [WIP] tactician:debug CLI helper

    Hi, I tried to implement #71 and probably don't understand container building process sufficiently.

    https://github.com/thephpleague/tactician-bundle/compare/master...kejwmen:feature/tactician-debug-command?expand=1#diff-ad045f4d615459e9b10db0108e3c5368R55

    tactician.debug.report is not available when trying to use it as service argument: https://github.com/thephpleague/tactician-bundle/compare/master...kejwmen:feature/tactician-debug-command?expand=1#diff-25ec658f2378af65501d443d6090edddR25

    So I tried registering command inside compiler pass but it wasn't registered as a command in my example app: https://github.com/thephpleague/tactician-bundle/compare/master...kejwmen:feature/tactician-debug-command?expand=1#diff-ad045f4d615459e9b10db0108e3c5368R57

    Is it even a good direction? I would love to help but need some guidance.

    opened by mateuszsip 15
  • WIP Allow tagging handlers per bus

    WIP Allow tagging handlers per bus

    Addresses #19

    There are a number of different possible ways that this feature could be implemented. Currently the bundle places all tagged handlers into a single instance of ContainerBasedHandlerLocator and relies on the user to register this handler as a middleware of their bus (or use the default tactician.middleware.command_handler service which includes it).

    The approach I took was to leave that as-is for any handlers which are explicitly tagged as belonging to a specific bus.

    However if the user tags a handler for a specific bus by using the "bus" key in the tag definition then this code does the following:

    1. Do not add the handler to the default locator
    2. Create a new service called tactician.handler.locator.symfony.bus_name with only those handlers tagged explicitly for that bus

    This means that if you want as soon as you tag a handler for a specific bus, that bus will now ONLY include handlers explicitly tagged for it.

    This also means that the user needs to be sure they configure the bus with an instance of CommandHandlerMiddleware since they can't use the default tactician.middleware.command_handler

    There are some other possible approaches improvements I thought of, I wanted to post this WIP code and get feedback before I proceed any further. Here are some other ideas

    1. Create a copy of the tactician.middleware.command_handler for each bus that has handlers tagged for it explicitly. This would be identical to the default command_handler but with a different locator. The user would still need to attach the right tactician.middleware.command_handler.BUS_NAME as the final middleware.
    2. Automatically push the command_handler onto the middleware for the bus (deviates from the way this bundle works right now where you have to include the command handler as the final middleware)
    3. If the user configures multiple buses we could throw an exception if they dont tag all their handler services (probably not a good idea)

    @rosstuck @boekkooi Let me know your thoughts, It seems like at least the first item would be necessary to make this feature easy to use (automatically create a copy of the default command_handler middleware with the custom locator if the user tags any of their handler services)

    opened by benglass 15
  • RFC: Command class guessing during compilation

    RFC: Command class guessing during compilation

    Currently it's required to pass a command value to the tag in your service configuration, this seems redundant to me. If the chosen strategy supports guessing the method (e.g. handle or __invoke), it can also guess which command it should use as it's defined in the method signature.

    During container compilation, the compiler pass knows the class of the handler and it knows the strategy. Based on this (if the tag doesn't define the command), reflection could be used to guess the actual command class and fill it in.

    Advantage of this method is that it won't rely on auto-wiring.

    Slightly related to #44

    opened by linaori 13
  • Test against different Symfony versions

    Test against different Symfony versions

    This bundle claims Symfony 2.3 - 3.0 support, but it only tests against 2.3 and 2.8. Let's test all supported Symfony versions that didn't reach end of life yet.

    Also, this PR updates the config to use the new docker-based Travis environment. This will speed up tests quite a bit and makes it possible to cache directories (e.g. Composer packages).

    opened by wouterj 13
  • Refactor and add support for Handler Mapping Strategies

    Refactor and add support for Handler Mapping Strategies

    As discussed in #44 and #60, this (very broken, very Work in Progress) PR does two things:

    1. Refactor some of our most tangled internals
    2. Add support for letting folks autowire their own command -> mapping strategies

    What does it change?

    It guts the TacticianExtension and CommandHandlerCompilerPass, separating their contents out into three objects: BusBuilder(s), HandlerMapping, and Routing. Each part is now much more testable and a lot of the spooky-action-at-a-distance-pass-data-through-container-parameters stuff is eliminated.

    How do folks add their own?

    Implement your own HandlerMapping interface and pass it to the TacticianBundle when instantiating it in your AppKernel. For prior art, see: https://github.com/matthiasnoback/symfony-bundle-plugins

    I know hat's not the normal way of doing things in Symfony, folks would expect a "tactician.handler_mapping" container tag or a config option for a service value but here's the problem: most of the configuration methods that people want to use rely on manipulating/reading the container data (tags, mapping, etc). However, in our case the container isn't built yet (because we're in the process of building it), so we can't rely on anything we'd in it. The best we could do is a FQCN in the config class but considering you might want to put them in a Composite/Chained HandlerMapping strategy, that's awkward too.

    In the end, this is the best way I've found to inject strategies into the Bundle's compilation process and the "surprise" of it is something we can easily mitigate with good documentation.

    What will this not support?

    Basically, the type of mappings strategies you'd want to run after the container is built, maybe those that use complex object graphs or an external cache to build/keep performant. The only usecase I actually seeing us missing out on is probably annotations but the longer I look at how that would work in practice, the more inclined I am to push people towards using the DI config. Besides, folks could still do that if they want or use JMS/Metadata as autoloading is active at this point.

    I looked at using a CacheWarmer instead of a Compilation step to keep the command routing performant yet customizable. In the end, it gets very awkward since the implementation for pre-compilation and post-compilation routing would be very different.

    Honestly, if folks have very specific needs/wishes, they should just write their own replacement for the command handler middleware. They'll be done in 30-50 lines what would take us hundreds to support in configuration.

    What remains to be done?

    • [x] The new objects all need tests. Some of the old ones have been ported but it's not enough.
    • [x] Need to review the old tests and see which ones would be better off being relocated.
    • [x] Implement the new strategies we'll support (starting with a reflection based one that looks at the typehints on unary handler methods)
    • [x] Decide what the new starting ones will be
    • [x] Documentation
    • [ ] Add a "tactician:debug" command which shows which commands are routed to what services
    • [x] Much, much remaining cleanup.

    What will make it go faster?

    • Let me know if you have any feedback on the new design, it's just an idea. :)
    • Send PRs for the above points, I'm happy to get 'em!

    BC breaks

    • Removed the tactician.commandbus.class parameter
    • Some different exceptions are now thrown in container building error cases
    help wanted 
    opened by rosstuck 12
  • Create CommandHandlerInterface for autowiring-configure of CommandHandlers in Symfony

    Create CommandHandlerInterface for autowiring-configure of CommandHandlers in Symfony

    Hey! I love this bundle, and I'm starting to discover the power of the command bus pattern. It would be really cool to include a CommandHandlerInterface whose sole purpose is going to be signaling a concrete command handler for autowiring and autoconfigure. I've implemented this in my project manually, but I think it could be a very neat feature to have! :)

    opened by mnavarrocarter 11
  • Symfony 3.4: By default all services are private.

    Symfony 3.4: By default all services are private.

    Hi, in own project, after the upgrade the Symfony to 3.4 version, we have many deprecated notices after running functional tests.

    Origin problem: https://symfony.com/blog/new-in-symfony-3-4-services-are-private-by-default

    • We use directly command bus on own tests $container->get('tactician.commandbus.default').
    • All handlers of commands is private by default.
    The "tactician.commandbus.default" service is private, getting it from the container is deprecated since Symfony 3.2 and will fail in 4.0. You should either make the service public, or stop using the container directly and use dependency injection instead:
    
    opened by ZhukV 11
  • Allow tagging handlers per bus

    Allow tagging handlers per bus

    Following #20

    Just let the check of tactician.middleware.command_handler as I'm not sure to get what is wrong with it.

    Let me know what we need to go forward.

    opened by tyx 10
  • Removed method inflector service check

    Removed method inflector service check

    This small PR only removes the method inflector service check (mentioned by @boekkooi in https://github.com/thephpleague/tactician-bundle/issues/3#issuecomment-115632201), so it is possible to define the custom method name inflector.

    opened by elcuro 10
  • Default command bus is not service  Symfony 4.3

    Default command bus is not service Symfony 4.3

    Hello, I was Installed your bundle, but I have problem with run command bus.. I Using autowiring, and this bundle throw me

    $commandBus" of method "__construct()" references class "League\Tactician\CommandBus" but no such service exists. i

    How do fix it>?

    opened by Pablossoo 9
  • After upgrading symfony from 3.4 to 4.4(without flex) getting The \

    After upgrading symfony from 3.4 to 4.4(without flex) getting The \"tactician.commandbus\" service or alias has been removed or inlined when the container was compiled. You should either make it public, or stop using the container directly and use dependency injection instead

    Hi After updating symfony from 3.4 to 4.4(without flex) i am getting this error The "tactician.commandbus" service or alias has been removed or inlined when the container was compiled. You should either make it public, or stop using the container directly and use dependency injection instead

    symfony (4.4.42) league/tactician-bundle (v1.4.0)

    have injected commnd bus using DI in Controller

    class MngmtController extends AbstractFOSRestController
    {
       /**
         * @var CommandBus
         */
        private $commandBus;
    
        /**
         * @var CommandBus
         */
        private $mngmtCommandBus;
    
        /**
         * @var MngmtService
         */
        private $mngmtService;
    
        /**
         * @var LoggerInterface
         */
        private $logger;
    
        /**
         * @param ContainerInterface $container
         * @param CommandBus         $commandBus
         * @param CommandBus         $mngmtCommandBus
         * @param MngmtService       $mngmtService
         * @param LoggerInterface    $logger
         *
         * @DI\InjectParams({
         *     "container" = @DI\Inject("service_container"),
         *     "commandBus" = @DI\Inject("tactician.commandbus"),
         *     "mngmtCommandBus" = @DI\Inject("tactician.commandbus.mngmt"),
         *     "mngmtService" = @DI\Inject("app.services.mngmt_service"),
         *     "logger" = @DI\Inject("logger")
         * })
         */
        public function __construct(
            ContainerInterface $container,
            CommandBus $commandBus,
            CommandBus $mngmtCommandBus,
            MngmtService $mngmtService,
            LoggerInterface $logger
        ) {
            $this->container = $container;
            $this->commandBus = $commandBus;
            $this->mngmtCommandBus = $mngmtCommandBus;
            $this->mngmtService = $mngmtService;
            $this->logger = $logger;
        }
    

    command and handler mapping in Handler

    /**
     * Class UpdateMngmtCommandHandler.
     *
     * @DI\Service("app.update_mngmt_command_handler")
     * @DI\Tag("tactician.handler", attributes= {"command" = "AppBundle\CommandBus\UpdateMngmtCommand"})
     */
    class MngmtCommandHandler {
    

    middleware configuraion in config.yml

     tactician:
        commandbus:
            default:
                middleware:
                    - tactician.middleware.locking
                    - tactician.middleware.doctrine
                    - tactician.middleware.command_handler
            mngmt:
                middleware:
                    - tactician.middleware.locking
                    - app.commandbus.middleware.lock_component
                    - app.commandbus.middleware.transaction
                    - app.commandbus.middleware.mngmt_block
                    - tactician.middleware.command_handler
    
    opened by vasanth-kumar-m-y 0
  • DebugCommand return value

    DebugCommand return value

    When using the debug command (debug:tactician), I get the following error:

    In Command.php line 258:
       Return value of "League\Tactician\Bundle\Command\DebugCommand::execute()" must be of the type int, "NULL" returned.
    
    opened by hafkenscheid 4
  • Tactician v2

    Tactician v2

    I started working on v2

    • [ ] How to do debug command? With v2 the command handler map is not known in advance, mapping is done in runtime through locators. We would need inverse locator for this.
    • [ ] Tests
    • [ ] Update readme
    • [ ] Tag based mapping/handling stuff
    • [x] should DoctrineMiddlewarePass, SecurityMiddlewarePass, ValidatorMiddlewarePass be part of this?
    • [x] Let's only support modern versions of Symfony
    • [ ] Maybe we can move more of this out of the config.yml and more into the services.yml. Most of the work around the config.yml is just doing multiple command buses and adding middleware to them. These are tasks that I think would be better off in the services.yml where it's much simpler for folks to manage and work with them, instead of guessing at the autogenerated names (which are a repeatedly filed bug). The only services we need to auto generate then are the command locators, so maybe there's no need for the config.yml work at all.
    opened by simPod 4
  • [WIP] Moves validator middleware into another package

    [WIP] Moves validator middleware into another package

    I suggest to move validator middleware into another package in order to use it in another context without the need to import the bundle. I created a package with the middleware that can be integrated in the League organization. The validator middleware package has been defined as suggested package in the composer file as is currently not used by default.

    BC breaks:

    • rename middleware from League\Tactician\Bundle\Middleware\ValidatorMiddleware to League\Tactician\Validator\ValidatorMiddleware
    opened by neeckeloo 8
  • Roadmap

    Roadmap

    Road to 1.0

    • [x] Integration tests for the security middleware
    • [x] Review SecurityMiddlewareTest assertions (and label the data fixtures to see if we're hitting all the main points)
    • [x] Port DoctrineMiddlewarePass away from mocks (see https://github.com/thephpleague/tactician-bundle/blob/master/tests/DependencyInjection/Compiler/DoctrineMiddlewarePassTest.php for an example)
    • [x] Port CommandHandlerPassTest away from mocks
    • [x] Port ContainerBasedHandlerLocator away from mocks
    • [x] Fix incorrect docblocks (a number of them are missing type annotations, have old params, etc)
    • [x] Review Documentation

    1.1

    • [x] Reduce complexity of main compiler pass
    • [x] Add Autowiring features (see #44)
    • [x] Add SecurityMiddlewarePassTest
    • [x] Add ValidatorMiddlewarePassTest
    • [x] Add tactician
    • [x] Add tactician:debug command to see command->handler service routing (see #73 )
    • [x] Review docs & changelog

    1.2

    • [ ] Split validator middleware into separate package?

    2.0

    • [ ] Support Tactician2...someday.

    Misc

    • [ ] Start reorganizing README into the wiki or multiple markdown files
    help wanted 
    opened by rosstuck 36
Releases(v1.3.2)
Owner
The League of Extraordinary Packages
A group of developers who have banded together to build solid, well tested PHP packages using modern coding standards.
The League of Extraordinary Packages
This bundle provides tools to build a complete GraphQL server in your Symfony App.

OverblogGraphQLBundle This Symfony bundle provides integration of GraphQL using webonyx/graphql-php and GraphQL Relay. It also supports: batching with

Webedia - Overblog 720 Dec 25, 2022
Pure PHP implementation of GraphQL Server – Symfony Bundle

Symfony GraphQl Bundle This is a bundle based on the pure PHP GraphQL Server implementation This bundle provides you with: Full compatibility with the

null 283 Dec 15, 2022
DataTables bundle for Symfony

Symfony DataTables Bundle This bundle provides convenient integration of the popular DataTables jQuery library for realtime Ajax tables in your Symfon

Omines Internetbureau 199 Jan 3, 2023
GraphQL Bundle for Symfony 2.

Symfony 2 GraphQl Bundle Use Facebook GraphQL with Symfony 2. This library port laravel-graphql. It is based on the PHP implementation here. Installat

Sergey Varibrus 35 Nov 17, 2022
An Unleash bundle for Symfony applications to provide an easy way to use feature flags

Unleash Bundle An Unleash bundle for Symfony applications. This provide an easy way to implement feature flags using Gitlab Feature Flags Feature. Ins

Stogon 7 Oct 20, 2022
Symfony Health Check Bundle Monitoring Project Status

Symfony Health Check Bundle Version Build Status Code Coverage master develop Installation Step 1: Download the Bundle Open a command console, enter y

MacPaw Inc. 27 Jul 7, 2022
A bundle providing routes and glue code between Symfony and a WOPI connector.

WOPI Bundle A Symfony bundle to facilitate the implementation of the WOPI endpoints and protocol. Description The Web Application Open Platform Interf

Champs-Libres 5 Aug 20, 2022
Mediator - CQRS Symfony bundle. Auto Command/Query routing to corresponding handlers.

Installation $ composer require whsv26/mediator Bundle configuration // config/packages/mediator.php return static function (MediatorConfig $config)

Alexander Sv. 6 Aug 31, 2022
Symfony bundle for EventSauce (WIP)

Symfony EventSauce (WIP) This bundle provides the basic and extended container configuration of symfony for the EventSauce library. Before using it, I

Andrew Pakula 8 Dec 19, 2022
Symfony bundle integrating server-sent native notifications

Symfony UX Notify Symfony UX Notify is a Symfony bundle integrating server-sent native notifications in Symfony applications using Mercure. It is part

Symfony 6 Dec 15, 2022
A Symfony bundle that provides #StandWithUkraine banner and has some built-in features to block access to your resource for Russian-speaking users.

StandWithUkraineBundle На русском? Смотри README.ru.md This bundle provides a built-in StandWithUkraine banner for your Symfony application and has so

Victor Bocharsky 10 Nov 12, 2022
OpenAPI(v3) Validators for Symfony http-foundation, using `league/openapi-psr7-validator` and `symfony/psr-http-message-bridge`.

openapi-http-foundation-validator OpenAPI(v3) Validators for Symfony http-foundation, using league/openapi-psr7-validator and symfony/psr-http-message

n1215 2 Nov 19, 2021
Fork of Symfony Rate Limiter Component for Symfony 4

Rate Limiter Component Fork (Compatible with Symfony <=4.4) The Rate Limiter component provides a Token Bucket implementation to rate limit input and

AvaiBook by idealista 4 Apr 19, 2022
Enter-to-the-Matrix-with-Symfony-Console - Reproduction of the "Matrix characterfall" effect with the Symfony Console component.

Enter to the Matrix (with Symfony Console) Reproduction of the "Matrix characterfall" effect with the Symfony Console component. Run Clone the project

Yoan Bernabeu 23 Aug 28, 2022
Easily integrate custom-made NPS (Net Promoter Score) into your application

Laravel NPS Easily integrate custom-made NPS (Net Promoter Score) to your application. Installation You can install the package via composer: composer

H-FARM Innovation 48 Oct 27, 2022
The perfect starting point to integrate Algolia within your PHP project

⚡️ A fully-featured and blazing-fast PHP API client to interact with Algolia.

Algolia 629 Jan 4, 2023
Provides tools for building modules that integrate Nosto into your e-commerce platform

php-sdk Provides tools for building modules that integrate Nosto into your e-commerce platform. Requirements The Nosto PHP SDK requires at least PHP v

Nosto 5 Dec 21, 2021
Copy of hautelook/alice-bundle v2.9.0

AliceBundle A Symfony bundle to manage fixtures with nelmio/alice and fzaninotto/Faker. The database support is done in FidryAliceDataFixtures. Check

Global4Net Ltd. 3 Sep 10, 2021
The maker bundle allows you to generate content elements, front end modules

Contao 4 maker bundle The maker bundle allows you to generate content elements, front end modules, event listener, callbacks and hooks using interacti

Contao 7 Aug 3, 2022