Skip to content

Commit

Permalink
[Doc] Guide: How to create a single-file plugin
Browse files Browse the repository at this point in the history
  • Loading branch information
gregurco committed Sep 3, 2018
1 parent 3646df6 commit c082ff6
Showing 1 changed file with 45 additions and 37 deletions.
82 changes: 45 additions & 37 deletions src/Resources/doc/how-to-create-a-plugin.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
# How to create a single-file plugin

The possibility to create plugins was introduced in version [7.0][1] of Guzzle Bundle and several plugins have already been published and downloaded thousands of times.
The possibility of creating plugins was introduced in version [7.0][1] of Guzzle Bundle and several plugins have already been published and downloaded thousands of times.

Let’s see how easy it is to create your own single-file plugin!

### Middleware

The main scope of plugins is to provide possibility to configure middlewares for each guzzle client individually.
> If you are not familiar with `middleware` definition, then first read this great article provided by Guzzle team:
> [http://docs.guzzlephp.org/en/stable/handlers-and-middleware.html#middleware][6]
So, first we need a middleware. Suppose we have one that adds some magic value to magic header for all the requests:
The primary goal of plugins is to provide possibility of configuration of middlewares for each guzzle client individually.

So, first we need a middleware. Suppose we have one that adds some "magic header" with "magic value" to all the requests:

```php
// src/GuzzleMiddleware/MagicHeaderMiddleware.php
Expand Down Expand Up @@ -51,7 +54,7 @@ class MagicHeaderMiddleware

### Client

Also we need a client, that will be used to perform requests:
Also we need a guzzle client, that will be used to perform requests:

```yaml
# config/packages/eight_points_guzzle.yaml
Expand Down Expand Up @@ -81,14 +84,15 @@ eight_points_guzzle:
header_value: magic-value
```
Try to clear cache and you will observe an error:
Adjust your configuration file and try to clear cache using command `bin/console cache:clear` and you will observe an error:

```bash
In ArrayNode.php line 311:
Unrecognized option "magic_header" under "eight_points_guzzle.clients.httpbin_client.plugin"
```

It’s OK, because Guzzle Bundle does not know anything about `magic_header` plugin and our new plugin will help to handle this configuration.
It’s OK, because Guzzle Bundle does not know anything about `magic_header` plugin and such a configuration.
The plugin we plan to make will help Guzzle Bundle to do it.

### Plugin

Expand All @@ -108,12 +112,19 @@ use Symfony\Component\HttpKernel\Bundle\Bundle;
class MagicHeaderPlugin extends Bundle implements EightPointsGuzzleBundlePlugin
{
/**
* @param array $configs
* @param ContainerBuilder $container
* @return string
*/
public function load(array $configs, ContainerBuilder $container)
public function getPluginName() : string
{
}
/**
* @param ArrayNodeDefinition $pluginNode
*/
public function addConfiguration(ArrayNodeDefinition $pluginNode)
{
}
/**
Expand All @@ -124,49 +135,42 @@ class MagicHeaderPlugin extends Bundle implements EightPointsGuzzleBundlePlugin
*/
public function loadForClient(array $config, ContainerBuilder $container, string $clientName, Definition $handler)
{

}
/**
* @param ArrayNodeDefinition $pluginNode
*/
public function addConfiguration(ArrayNodeDefinition $pluginNode)
{

}
/**
* @return string
* @param array $configs
* @param ContainerBuilder $container
*/
public function getPluginName() : string
public function load(array $configs, ContainerBuilder $container)
{
}
}
```

Note that we implemented `EightPointsGuzzleBundlePlugin` interface and defined 4 methods:
- `load` - used to load xml/yaml/etc configuration
- `loadForClient` - called after clients services are defined in container builder
- `addConfiguration` - called when configuration tree of Guzzle Bundle is build
- `getPluginName` - called to get plugin identifier (name)
- `addConfiguration` - called when configuration tree of Guzzle Bundle is being built
- `getPluginName` - called to get plugin identifier *(plugin name)*

First define plugin name:

```php
// ...
class MagicHeaderPlugin extends Bundle implements EightPointsGuzzleBundlePlugin
{
// ...

{
/**
* @return string
*/
public function getPluginName() : string
{
return 'magic_header';
}
// ...
}
```

Expand Down Expand Up @@ -195,14 +199,14 @@ class MagicHeaderPlugin extends Bundle implements EightPointsGuzzleBundlePlugin
}
```

During the build of configuration tree of Guzzle Bundle the node is created for each plugin and this node is passed to each plugin in `addConfiguration` method.
During the construction of configuration tree of Guzzle Bundle the node is created for each plugin and this node is passed to each plugin in `addConfiguration` method.
Here you have possibility to add any nodes you want. In out case we added just one scalar and nullable node with key `header_value`.

You can read more about configuration [here][2].

### Connect Plugin with Guzzle Bundle

The plugin does little more, but it is ready to be connected to Guzzle Bundle:
The plugin does not do anything significant, but it is ready to be connected to Guzzle Bundle:

```diff
// src/Kernel.php
Expand Down Expand Up @@ -235,13 +239,13 @@ The plugin does little more, but it is ready to be connected to Guzzle Bundle:
}
```

Clearing of cache will end with success now.
Clearing of cache will end with success.

### Connect Plugin with Middleware

To connect plugin and middleware we have to modify `loadForClient` method from `MagicHeaderPlugin` class.
At this stage we receive control on process of build container.
Having the value of `header_value` option provided from configuration file we can define middleware as a service and inject it to handle stack of the client:
To connect the plugin and middleware we need to modify `loadForClient` method from `MagicHeaderPlugin` class.
At this stage we get control over the process of building the container.
Having the value of `header_value` option provided from configuration file we can define middleware as a service and inject it to handler stack of the client:

```php
// ...
Expand Down Expand Up @@ -280,13 +284,15 @@ class MagicHeaderPlugin extends Bundle implements EightPointsGuzzleBundlePlugin
}
```

Notice that this method is executed for each client defined in `eight_points_guzzle` configuration file.
Note that `loadForClient` method is executed for each client defined in `eight_points_guzzle` configuration file.

Read more about handler stack [here][6].

### Testing

It’s time to test!

Just call anywhere the client and execute get request:
Just call anywhere the client and execute GET request:

```php
$this->get('eight_points_guzzle.client.httpbin_client')->get('');
Expand All @@ -296,11 +302,11 @@ Trigger this action and open Symfony Profiler:

![Symfony Profiler: check magic-header](./img/magic_header_middleware.png)

Notice header with name `magic-header` and value provided from configuration: `magic-value`.
Note in the request information the header with name `magic-header` and value provided from configuration: `magic-value`.

### Conclusion

In this article you saw how easy it is to create single-file plugin and to extend base functionality provided by Guzzle Bundle.
In this article we found out how easy it is to create single-file plugin and to extend base functionality provided by Guzzle Bundle.

In the next article, we'll figure out how to create standalone plugin ready to be published on [packagist.org][3].

Expand All @@ -314,3 +320,5 @@ In the next article, we'll figure out how to create standalone plugin ready to b
[3]: https://packagist.org
[4]: https://github.com/8p/EightPointsGuzzleBundle#known-and-supported-plugins
[5]: https://packagist.org/?query=middleware&tags=guzzle~middleware
[6]: http://docs.guzzlephp.org/en/stable/handlers-and-middleware.html#handlerstack
[7]: http://docs.guzzlephp.org/en/stable/handlers-and-middleware.html#middleware

0 comments on commit c082ff6

Please sign in to comment.