• This repository has been archived on 15/Nov/2018
  • Stars
    star
    258
  • Rank 158,189 (Top 4 %)
  • Language
    PHP
  • License
    MIT License
  • Created almost 9 years ago
  • Updated over 7 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Symfony controllers, redesigned

DunglasActionBundle: Symfony controllers, redesigned

Build Status Build status SensioLabsInsight Scrutinizer Code Quality StyleCI

This bundle is a replacement for the controller system of the Symfony framework and for its command system.

It is as convenient as the original but doesn't suffer from its drawbacks:

  • Action and console classes are automatically registered as services by the bundle
  • Their dependencies are explicitly injected in the constructor (no more ugly access to the service container) using the autowiring feature of the Dependency Injection Component
  • Only one action per class thanks to the __invoke() method (but you're still free to create classes with more than 1 action if you want to)
  • 100% compatible with common libraries and bundles including SensioFrameworkExtraBundle annotations

DunglasActionBundle allows to create reusable, framework agnostic (especially when used with the PSR-7 bridge) and easy to unit test classes.

See symfony/symfony#16863 (comment) for the history behind this bundle.

Note for Symfony >=3.3 users

If you use Symfony at version 3.3 or superior, you do not need to use this bundle as all the features were ported in Symfony. You can learn more about it in the Symfony blog or in the Symfony documentation.

Installation

Use Composer to install this bundle:

composer require dunglas/action-bundle

Add the bundle in your application kernel:

// app/AppKernel.php

public function registerBundles()
{
    return [
        // ...
        new Dunglas\ActionBundle\DunglasActionBundle(),
        // ...
    ];
}

Optional: to use the @Route annotation add the following lines in app/config/routing.yml:

app:
    resource: '@AppBundle/Action/' # Use @AppBundle/Controller/ if you prefer
    type:     'annotation'

If you don't want to use annotations but prefer raw YAML, use the following syntax:

foo:
    path:      /foo/{bar}
    defaults:  { _controller: 'AppBundle\Action\Homepage' } # this is the name of the autoregistered service corresponding to this action

Usage

  1. Create an invokable class in the Action\ namespace of your bundle:
// src/AppBundle/Action/MyAction.php

namespace AppBundle\Action;

use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Routing\RouterInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;

class Homepage
{
    private $router;
    private $twig;

    /**
     * The action is automatically registered as a service and dependencies are autowired.
     * Typehint any service you need, it will be automatically injected.
     */
    public function __construct(RouterInterface $router, \Twig_Environment $twig)
    {
        $this->router = $router;
        $this->twig = $twig;
    }

    /**
     * @Route("/myaction", name="my_action")
     *
     * Using annotations is not mandatory, XML and YAML configuration files can be used instead.
     * If you want to decouple your actions from the framework, don't use annotations.
     */
    public function __invoke(Request $request)
    {
        if (!$request->isMethod('GET')) {
            // Redirect to the current URL using the the GET method if it's not the current one
            return new RedirectResponse($this->router->generateUrl('my_action'), 301);
        }

        return new Response($this->twig->render('mytemplate.html.twig'));
    }
}

Alternatively, you can create a typical Symfony controller class with several *Action methods in the Controller directory of your bundle, it will be autowired the same way.

There is no step 2! You're already done.

All classes inside Action/ and Controller/ directories of your project bundles are automatically registered as services. By convention, the service name is the Fully Qualified Name of the class.

For instance, the class in the example is automatically registered with the name AppBundle\Action\Homepage.

There are other classes/tags supported:

Class Name Tag automatically added Directory
Command console.command Command
EventSubscriberInterface kernel.event_subscriber EventSubscriber
Twig_ExtensionInterface twig.extension Twig

Thanks to the autowiring feature of the Dependency Injection Component, you can just typehint dependencies you need in the constructor, they will be automatically initialized and injected.

Service definition can easily be customized by explicitly defining a service named according to the same convention:

# app/config/services.yml

services:
    # This is a custom service definition
    'AppBundle\Action\MyAction':
        arguments: [ '@router', '@twig' ]

    'AppBundle\Command\MyCommand':
        arguments: [ '@router', '@twig' ]
        tags:
            - { name: console.command }

    # With Symfony < 3.3
    'AppBundle\EventSubscriber\MySubscriber':
        class: 'AppBundle\EventSubscriber\MySubscriber'
        tags:
            - { name: kernel.event_subscriber }

This bundle also hooks into the Routing Component (if it is available): when the @Route annotation is used as in the example, the route is automatically registered: the bundle guesses the service to map with the path specified in the annotation.

Dive into the TestBundle to discover more examples such as using custom services with ease (no configuration at all) or classes containing several actions.

Using the Symfony Micro Framework

You might be interested to see how this bundle can be used together with the Symfony "Micro" framework.

Here we go:

// MyMicroKernel.php

use AppBundle\Action\Homepage;
use Symfony\Bundle\FrameworkBundle\Kernel\MicroKernelTrait;
use Symfony\Component\Config\Loader\LoaderInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\HttpKernel\Kernel;
use Symfony\Component\Routing\RouteCollectionBuilder;

final class MyMicroKernel extends Kernel
{
    use MicroKernelTrait;

    public function registerBundles()
    {
        return [
            new Symfony\Bundle\FrameworkBundle\FrameworkBundle(),
            new Dunglas\ActionBundle\DunglasActionBundle(),
            new AppBundle\AppBundle(),
        ];
    }

    protected function configureRoutes(RouteCollectionBuilder $routes)
    {
        // Specify explicitly the controller
        $routes->add('/', Homepage::class, 'my_route');
        // Alternatively, use @Route annotations
        // $routes->import('@AppBundle/Action/', '/', 'annotation');
    }

    protected function configureContainer(ContainerBuilder $c, LoaderInterface $loader)
    {
        $c->loadFromExtension('framework', ['secret' => 'MySecretKey']);
    }
}

Amazing isn't it?

Want to see a more advanced example? Checkout our test micro kernel.

Configuration

# app/config/config.yml

dunglas_action:
    directories: # List of directories relative to the kernel root directory containing classes to auto-register.
        - '../src/*Bundle/{Controller,Action,Command,EventSubscriber}'
        # This one is not registered by default
        - '../src/*Bundle/My/Uncommon/Directory'
    tags:
        'Symfony\Component\Console\Command\Command': console.command
        'Symfony\Component\EventDispatcher\EventSubscriberInterface': kernel.event_subscriber
        'My\Custom\Interface\To\Auto\Tag':
            - 'my_custom.tag'
            - [ 'my_custom.tag_with_attributes', { attribute: 'value' } ]

Credits

This bundle is brought to you by Kévin Dunglas and awesome contributors. Sponsored by Les-Tilleuls.coop.

More Repositories

1

frankenphp

🧟 The modern PHP app server
Go
6,849
star
2

vulcain

🔨 Fast and idiomatic client-driven REST APIs.
Go
3,513
star
3

mercure

An open, easy, fast, reliable and battery-efficient solution for real-time communications
Go
3,349
star
4

symfony-docker

A Docker-based installer and runtime for Symfony. Install: download and `docker compose up`.
Dockerfile
2,354
star
5

react-esi

React ESI: Blazing-fast Server-Side Rendering for React and Next.js
TypeScript
677
star
6

doctrine-json-odm

An object document mapper for Doctrine ORM using JSON types of modern RDBMS.
PHP
525
star
7

phpdoc-to-typehint

Add scalar type hints and return types to existing PHP projects using PHPDoc annotations
PHP
226
star
8

DunglasAngularCsrfBundle

Automatic CSRF protection for JavaScript apps using a Symfony API
PHP
151
star
9

vaccin.click

Une extension Firefox pour trouver et réserver automatiquement votre créneau de vaccination COVID-19.
JavaScript
94
star
10

php-torcontrol

PHP TorControl, a library to control TOR
PHP
86
star
11

php-socialshare

Server-side social networks share counts and share links retriever
PHP
80
star
12

DunglasTodoMVCBundle

A TodoMVC implementation wrote with Symfony, Chaplin.js and Backbone.js
PHP
78
star
13

solid-client-php

PHP library for accessing data and managing permissions on data stored in a Solid Pod
PHP
59
star
14

frankenphp-demo

Demo app for FrankenPHP
HTML
59
star
15

httpsfv

A Go library to parse and serialize HTTP structured field values
Go
57
star
16

symfonycon-lisbon

A joind.in clone built with Symfony 4 and Vue.js
PHP
39
star
17

demo-vulcain-api-platform

Use API Platform with the Vulcain protocol and Varnish!
JavaScript
34
star
18

php-to-json-schema

Creates a JSON Schema from a PHP class
PHP
32
star
19

stack2slack

A Slack bot to monitor StackOverflow/StackExchange tags
Go
29
star
20

frankenphp-wordpress

WordPress on FrankenPHP
Dockerfile
29
star
21

php-property-info

Retrieve type and description of PHP properties using various sources
PHP
27
star
22

prestashop-html5-theme

HTML5 Prestashop tempate enhanced for SEO with Google Rich Snippets support
Smarty
27
star
23

DunglasDigitalOceanBundle

DigitalOcean API v2 client for Symfony and API Platform
PHP
25
star
24

frankenphp-drupal

Drupal on FrankenPHP
Dockerfile
23
star
25

blog-api

A demonstration blog API for the API Platform framework
PHP
22
star
26

stripe-invoice-exporter

Download all your Stripe PDF invoices in bulk.
PHP
20
star
27

jquery.confirmExit

jQuery confirm before exit plugin
JavaScript
16
star
28

calavera

A (static) Single Page Application generator using Markdown files
Go
16
star
29

ShopApiPlugin

PHP
16
star
30

kdDoctrineGuardFacebookConnectPlugin

Facebook Connect symfony plugin (extends sfGuardPlugin)
PHP
16
star
31

demo-postgres-listen-notify

Demo of the PostgreSQL LISTEN/NOTIFY support in Symfony Messenger
PHP
14
star
32

DunglasTorControlBundle

Integration of PHP TorControl library in Symfony
PHP
13
star
33

blog-client

A demonstration blog client for the API Platform framework
ApacheConf
12
star
34

symfony-demo-mercure

A demo project using Symfony's Mercure integration
PHP
10
star
35

docker-private-composer-packages

Example: Securely Access Private Composer Packages
Dockerfile
9
star
36

uri-template-tester

Test if a URI matches a given URI template (RFC6570)
HTML
8
star
37

planning

Planning management written in Symfony2 and Doctrine 2
PHP
8
star
38

symfony-lock

Symfony lock
8
star
39

piy

A modern self-managed Content Management System
PHP
7
star
40

api-parallelism-benchmark

A benchmark comparing HTTP/2 Server Push to GraphQL-Like compound documents
HTML
6
star
41

Elgg-profile_friendlyurl

Creates friendly URLs for user's Elgg profiles as subdomains.
PHP
6
star
42

forumphp2016

PHP
6
star
43

api-platform-heroku

Helpers to use API Platform and Symfony applications on Heroku.
PHP
5
star
44

Elgg-fblink

Link a Facebook and an Elgg account
PHP
5
star
45

dunglas

My GitHub profile!
5
star
46

php-basics

Cours de PHP (en français)
JavaScript
5
star
47

Elgg-presence

Friends Online on Elgg, Facebook and Twitter
PHP
4
star
48

frankenphp-website

The website of FrankenPHP
HTML
4
star
49

Elgg-twitterlogin

Login to Elgg using Twitter
PHP
4
star
50

Signal-TLS-Proxy

Dockerfile
3
star
51

vclient-web

Web interface for Viessmann Vito heating system
Python
3
star
52

debian-hosting

Automatically exported from code.google.com/p/debian-hosting
Python
3
star
53

Elgg-groups_bookmarkswidget

Elgg plugin to display a bookmarks widget in groups homepages
PHP
3
star
54

workshop-mercure

Code produced during my Mercure workshop
PHP
3
star
55

mercure-reproducer-cors

Reproducer for CORS issues with the Mercure.rocks Hub
HTML
3
star
56

slides-sfLive-2015

Slides de ma présentation au Symfony Live 2015
JavaScript
3
star
57

php-documention-generator

3
star
58

workshop-panther

Code produced during by Panther workshop
PHP
2
star
59

demo-autowiring

Symfony autowiring demo
PHP
2
star
60

slides-sfPot-2015-07-10

Slides: using PSR-7 with the Symfony framework
JavaScript
2
star
61

.github

My GitHub files
2
star
62

api-platform-crud-demo

JavaScript
2
star
63

slides-sfPot-2015-01-15

API-first et Linked Data avec Symfony
JavaScript
2
star
64

symfony-psr7-benchmark

Benchmark PSR-7 support in Symfony
PHP
1
star
65

ajax-syntax-highlighter

Automatically exported from code.google.com/p/ajax-syntax-highlighter
JavaScript
1
star
66

selfpublish

Automatically exported from code.google.com/p/selfpublish
PHP
1
star
67

training-apr-19

PHP
1
star
68

test-again

Vue
1
star
69

symfony-4-0

Symfony 4.0 benchmark on phpbenchmarks.com
PHP
1
star
70

scoopeo

Automatically exported from code.google.com/p/scoopeo
1
star
71

easyubuntu

Automatically exported from code.google.com/p/easyubuntu
1
star
72

serializer-pack

1
star
73

panther-legacy

Legacy releases of symfony/panther (including old versions of ChromeDriver and Geckodriver)
PHP
1
star
74

platform-on-platform-workshop

#APIDays: API Platform on Platform.sh workshop
JavaScript
1
star
75

crypt-manager

Automatically exported from code.google.com/p/crypt-manager
Python
1
star