257 lines
8.0 KiB
ReStructuredText
257 lines
8.0 KiB
ReStructuredText
Providers
|
|
=========
|
|
|
|
Providers allow the developer to reuse parts of an application into another
|
|
one. Silex provides two types of providers defined by two interfaces:
|
|
``ServiceProviderInterface`` for services and ``ControllerProviderInterface``
|
|
for controllers.
|
|
|
|
Service Providers
|
|
-----------------
|
|
|
|
Loading providers
|
|
~~~~~~~~~~~~~~~~~
|
|
|
|
In order to load and use a service provider, you must register it on the
|
|
application::
|
|
|
|
$app = new Silex\Application();
|
|
|
|
$app->register(new Acme\DatabaseServiceProvider());
|
|
|
|
You can also provide some parameters as a second argument. These will be set
|
|
**after** the provider is registered, but **before** it is booted::
|
|
|
|
$app->register(new Acme\DatabaseServiceProvider(), array(
|
|
'database.dsn' => 'mysql:host=localhost;dbname=myapp',
|
|
'database.user' => 'root',
|
|
'database.password' => 'secret_root_password',
|
|
));
|
|
|
|
Conventions
|
|
~~~~~~~~~~~
|
|
|
|
You need to watch out in what order you do certain things when interacting
|
|
with providers. Just keep these rules in mind:
|
|
|
|
* Overriding existing services must occur **after** the provider is
|
|
registered.
|
|
|
|
*Reason: If the service already exists, the provider will overwrite it.*
|
|
|
|
* You can set parameters any time **after** the provider is registered, but
|
|
**before** the service is accessed.
|
|
|
|
*Reason: Providers can set default values for parameters. Just like with
|
|
services, the provider will overwrite existing values.*
|
|
|
|
Included providers
|
|
~~~~~~~~~~~~~~~~~~
|
|
|
|
There are a few providers that you get out of the box. All of these are within
|
|
the ``Silex\Provider`` namespace:
|
|
|
|
* :doc:`DoctrineServiceProvider <providers/doctrine>`
|
|
* :doc:`FormServiceProvider <providers/form>`
|
|
* :doc:`HttpCacheServiceProvider <providers/http_cache>`
|
|
* :doc:`MonologServiceProvider <providers/monolog>`
|
|
* :doc:`RememberMeServiceProvider <providers/remember_me>`
|
|
* :doc:`SecurityServiceProvider <providers/security>`
|
|
* :doc:`SerializerServiceProvider <providers/serializer>`
|
|
* :doc:`ServiceControllerServiceProvider <providers/service_controller>`
|
|
* :doc:`SessionServiceProvider <providers/session>`
|
|
* :doc:`SwiftmailerServiceProvider <providers/swiftmailer>`
|
|
* :doc:`TranslationServiceProvider <providers/translation>`
|
|
* :doc:`TwigServiceProvider <providers/twig>`
|
|
* :doc:`ValidatorServiceProvider <providers/validator>`
|
|
|
|
.. note::
|
|
|
|
The Silex core team maintains a `WebProfiler
|
|
<https://github.com/silexphp/Silex-WebProfiler>`_ provider that helps debug
|
|
code in the development environment thanks to the Symfony web debug toolbar
|
|
and the Symfony profiler.
|
|
|
|
Third party providers
|
|
~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
Some service providers are developed by the community. Those third-party
|
|
providers are listed on `Silex' repository wiki
|
|
<https://github.com/silexphp/Silex/wiki/Third-Party-ServiceProviders>`_.
|
|
|
|
You are encouraged to share yours.
|
|
|
|
Creating a provider
|
|
~~~~~~~~~~~~~~~~~~~
|
|
|
|
Providers must implement the ``Pimple\ServiceProviderInterface``::
|
|
|
|
interface ServiceProviderInterface
|
|
{
|
|
public function register(Container $container);
|
|
}
|
|
|
|
This is very straight forward, just create a new class that implements the
|
|
register method. In the ``register()`` method, you can define services on the
|
|
application which then may make use of other services and parameters.
|
|
|
|
.. tip::
|
|
|
|
The ``Pimple\ServiceProviderInterface`` belongs to the Pimple package, so
|
|
take care to only use the API of ``Pimple\Container`` within your
|
|
``register`` method. Not only is this a good practice due to the way Pimple
|
|
and Silex work, but may allow your provider to be used outside of Silex.
|
|
|
|
Optionally, your service provider can implement the
|
|
``Silex\Api\BootableProviderInterface``. A bootable provider must
|
|
implement the ``boot()`` method, with which you can configure the application, just
|
|
before it handles a request::
|
|
|
|
interface BootableProviderInterface
|
|
{
|
|
function boot(Application $app);
|
|
}
|
|
|
|
Another optional interface, is the ``Silex\Api\EventListenerProviderInterface``.
|
|
This interface contains the ``subscribe()`` method, which allows your provider to
|
|
subscribe event listener with Silex's EventDispatcher, just before it handles a
|
|
request::
|
|
|
|
interface EventListenerProviderInterface
|
|
{
|
|
function subscribe(Container $app, EventDispatcherInterface $dispatcher);
|
|
}
|
|
|
|
Here is an example of such a provider::
|
|
|
|
namespace Acme;
|
|
|
|
use Pimple\Container;
|
|
use Pimple\ServiceProviderInterface;
|
|
use Silex\Application;
|
|
use Silex\Api\BootableProviderInterface;
|
|
use Silex\Api\EventListenerProviderInterface;
|
|
use Symfony\Component\HttpKernel\KernelEvents;
|
|
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
|
|
|
|
class HelloServiceProvider implements ServiceProviderInterface, BootableProviderInterface, EventListenerProviderInterface
|
|
{
|
|
public function register(Container $app)
|
|
{
|
|
$app['hello'] = $app->protect(function ($name) use ($app) {
|
|
$default = $app['hello.default_name'] ? $app['hello.default_name'] : '';
|
|
$name = $name ?: $default;
|
|
|
|
return 'Hello '.$app->escape($name);
|
|
});
|
|
}
|
|
|
|
public function boot(Application $app)
|
|
{
|
|
// do something
|
|
}
|
|
|
|
public function subscribe(Container $app, EventDispatcherInterface $dispatcher)
|
|
{
|
|
$dispatcher->addListener(KernelEvents::REQUEST, function(FilterResponseEvent $event) use ($app) {
|
|
// do something
|
|
});
|
|
}
|
|
}
|
|
|
|
This class provides a ``hello`` service which is a protected closure. It takes
|
|
a ``name`` argument and will return ``hello.default_name`` if no name is
|
|
given. If the default is also missing, it will use an empty string.
|
|
|
|
You can now use this provider as follows::
|
|
|
|
use Symfony\Component\HttpFoundation\Request;
|
|
|
|
$app = new Silex\Application();
|
|
|
|
$app->register(new Acme\HelloServiceProvider(), array(
|
|
'hello.default_name' => 'Igor',
|
|
));
|
|
|
|
$app->get('/hello', function (Request $request) use ($app) {
|
|
$name = $request->get('name');
|
|
|
|
return $app['hello']($name);
|
|
});
|
|
|
|
In this example we are getting the ``name`` parameter from the query string,
|
|
so the request path would have to be ``/hello?name=Fabien``.
|
|
|
|
.. _controller-providers:
|
|
|
|
Controller Providers
|
|
--------------------
|
|
|
|
Loading providers
|
|
~~~~~~~~~~~~~~~~~
|
|
|
|
In order to load and use a controller provider, you must "mount" its
|
|
controllers under a path::
|
|
|
|
$app = new Silex\Application();
|
|
|
|
$app->mount('/blog', new Acme\BlogControllerProvider());
|
|
|
|
All controllers defined by the provider will now be available under the
|
|
``/blog`` path.
|
|
|
|
Creating a provider
|
|
~~~~~~~~~~~~~~~~~~~
|
|
|
|
Providers must implement the ``Silex\Api\ControllerProviderInterface``::
|
|
|
|
interface ControllerProviderInterface
|
|
{
|
|
public function connect(Application $app);
|
|
}
|
|
|
|
Here is an example of such a provider::
|
|
|
|
namespace Acme;
|
|
|
|
use Silex\Application;
|
|
use Silex\Api\ControllerProviderInterface;
|
|
|
|
class HelloControllerProvider implements ControllerProviderInterface
|
|
{
|
|
public function connect(Application $app)
|
|
{
|
|
// creates a new controller based on the default route
|
|
$controllers = $app['controllers_factory'];
|
|
|
|
$controllers->get('/', function (Application $app) {
|
|
return $app->redirect('/hello');
|
|
});
|
|
|
|
return $controllers;
|
|
}
|
|
}
|
|
|
|
The ``connect`` method must return an instance of ``ControllerCollection``.
|
|
``ControllerCollection`` is the class where all controller related methods are
|
|
defined (like ``get``, ``post``, ``match``, ...).
|
|
|
|
.. tip::
|
|
|
|
The ``Application`` class acts in fact as a proxy for these methods.
|
|
|
|
You can use this provider as follows::
|
|
|
|
$app = new Silex\Application();
|
|
|
|
$app->mount('/blog', new Acme\HelloControllerProvider());
|
|
|
|
In this example, the ``/blog/`` path now references the controller defined in
|
|
the provider.
|
|
|
|
.. tip::
|
|
|
|
You can also define a provider that implements both the service and the
|
|
controller provider interface and package in the same class the services
|
|
needed to make your controllers work.
|