File: symfony2.md

package info (click to toggle)
php-di 7.1.1-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 2,932 kB
  • sloc: php: 10,572; makefile: 42; xml: 17; sh: 10; pascal: 5
file content (177 lines) | stat: -rw-r--r-- 4,643 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
---
layout: documentation
current_menu: symfony
---

# PHP-DI in Symfony

PHP-DI provides an easy and clean integration with Symfony that does not replace the original container:
all bundles and existing code still work the same.

Just to be clear: PHP-DI will work alongside Symfony's container. So you can use both at the same time.

## Installation

First install the bridge:

```
composer require php-di/symfony-bridge
```

Now you need to make your `AppKernel` extend `DI\Bridge\Symfony\Kernel` instead of Symfony's Kernel class:

```php
class AppKernel extends \DI\Bridge\Symfony\Kernel
{
    // ...

    protected function buildPHPDIContainer(ContainerBuilder $builder)
    {
        // Configure your container here
        // https://php-di.org/doc/container-configuration.html
        $builder->addDefinitions(__DIR__ . '/config/config.php');

        return $builder->build();
    }
}
```

You will need to implement the `buildPHPDIContainer()` method. That method allows you to configure PHP-DI.

## Usage

You can now define [controllers as services](http://symfony.com/doc/current/cookbook/controller/service.html),
without any configuration, using PHP-DI's power.

Example for the routing configuration:

```yaml
my_route:
    pattern:  /product-stock/clear
    defaults: { _controller: MyBundle\Controller\ProductController:clearAction }
```

**Careful! Note that you need to use `:` as a separator, not `::` (else it will not go through the container).**
The `:` notation means `service_id:method`, whereas the `::` notation means `class::method`.

Example with constructor injection:

```php
class ProductController
{
    private $productService;

    public function __construct(ProductService $productService)
    {
        $this->productService = $productService;
    }

    public function clearAction()
    {
        $this->productService->clearStock();
    }
}
```

Example with property injection:

```php
use DI\Attribute\Inject;

class ProductController
{
    #[Inject]
    private ProductService $productService;

    public function clearAction()
    {
        $this->productService->clearStock();
    }
}
```

### Routing annotations

It is possible to use [annotations for routing](http://richardmiller.co.uk/2011/10/25/symfony2-routing-to-controller-as-service-with-annotations/) and still have the controller created by PHP-DI.

You achieve that by specifying the service ID in the `@Route` annotation (which is most probably the class name itself unless you have a custom setup):

```php
/**
 * @Route(service="My\TestController")
 */
class TestController extends Controller
{
    private $dependency;

    public function __construct(SomeDependency $dependency)
    {
        $this->dependency = $dependency;
    }

    /**
     * @Route("test")
     */
    public function testAction()
    {
        return new Response('ok');
    }
}
```


## Using Symfony's services in PHP-DI

Let's say you want to inject the `EntityManager` in your controller: the entity manager is defined
in Symfony's container, and the controller is resolved by PHP-DI.

**You can reference services that are in Symfony's container in PHP-DI's configuration**:

```php
return [
    'AppBundle\Controller\ProductController' => DI\create()
        ->constructor(DI\get('doctrine.orm.entity_manager')),
];
```

**You can also inject PHP-DI services in a Symfony service**:

```yaml
services:
    # app.user_service is a Symfony service
    app.user_service:
        class: 'AppBundle\\Service\\UserService'
        arguments:
            # UserRepository is created by PHP-DI
            - '@AppBundle\\Service\\UserRepository'
```

### Service name aliases

PHP-DI can also work with autowiring or PHP attributes. These rely on the fact that the service name
is the class name (or interface name), e.g. you reference the entity manager by its class name
instead of `doctrine.orm.entity_manager`.

If you want to enjoy autowiring or attributes, you can simplify your life and write simple aliases
like these:

```php
return [
    ObjectManager::class => DI\get('doctrine.orm.entity_manager'),
];
```

Keep in mind that it's always better to type-hint against interfaces instead of class names!
So write your aliases with interfaces as much as possible.


## FOSRestBundle

There was a bug in FOSRestBundle that would prevent using "Controller as services" in some cases.

This bug has been fixed in FOSRestBundle **>=1.3.2**. Full details are here: [FOSRestBundle#743](https://github.com/FriendsOfSymfony/FOSRestBundle/pull/743)


## More

Read more on the [Symfony-Bridge project on GitHub](https://github.com/PHP-DI/Symfony-Bridge).