Skip to content

Services

Kyle Spraggs edited this page Jul 20, 2014 · 17 revisions

Services

Services in SpiffyFramework are managed by the SpiffyInject component. SpiffyInject is SpiffyFramework's light-weight inversion of control container and is part of the foundation to the entire framework.

SpiffyInject also manage's package parameters. You can read more about this feature in the package documentation.

Creating services

You can create services in the following ways:

  • Setting using a string class name
  • Setting the service directly
  • Creating the service through a closure
  • Using the array configuration
  • Using an object that implements ServiceFactory

All services are set through the nject() method regardless of which style you choose. Each style has it's own advantages and disadvantages. It's you to you to decide which is the best approach to take for your application.

By default, each package loads services using the services.php file in config/services.php. Below is a simple example of the config/services.php file.

// file: application/config/services.php
// 'service_name' => 'service_specification'
return [
    'application.service' => 'Application\Service',
];

String class name

// file: application/config/services.php
return [
    'application.service' => 'Application\Service',
];

Referencing application.service would return an object that's an instance of Application\Service.

Setting the service directly

// file: application/config/services.php
return [
    'application.service' => new \Application\Service(),
];

Referencing application.service would return an object that's an instance of Application\Service but would create the service on every request. In general this method is not recommended because it's impossible to lazy-load the service.

Using a closure

// file: application/config/services.php
return [
    'application.service' => function(\Spiffy\Inject\Injector $i) { 
        new \Application\Service($i->nvoke('foo')); 
    },
];

Using a closure allows you to inject additional dependencies before returning the service. A closure is good for rapid prototyping but is not recommended for production because closures can not be serialized. This means that you can not cache the package manager configuration.

Implementing a ServiceFactory

// file:: application/src/MyServiceFactory;
namespace Application;

use Spiffy\Inject\Injector;
use Spiffy\Inject\ServiceFactory;

class MyServiceFactory implements ServiceFactory
{
    public function createService(Injector $i)
    {
        return new Service($i->nvoke('foo'));
    }
}
// file: application/config/services.php
return [
    'application.service' => 'Application\MyServiceFactory'
];

Using a service factory is the first preferred method for creating services. By using a factory you can inject additional dependencies, cache the package manager configuration, and easily unit test your factory. A factory also provides you with the most flexibility for complex services.

Using the array configuration

// file: application/config/services.php
return [
    'foo' => '\StdClass',
    'application.service' => ['Application\Service', ['@foo']]
];

This is identical to the service factory above. An instance of Application\Service is created and the 'foo' service is injected into the constructor. The array configuration is designed to provide you a rapid way to basic services with basic dependencies. This method is also able to be cached. This is the preferred method for creating services.

Read on for more information on the array configuration.

Constructor injection

The array configuration allows constructor injection through the second array parameter passed to the service.

// file: application/config/services.php
return [
    'foo' => '\StdClass',
    'application.service' => ['Application\Service', ['@foo']]
];

The special '@' notation references another service for injection. In the example above Application\Service would be constructor injected with the @foo service which is an instance of StdClass. Constructor injection should be used for immutable dependencies.

Setter injection

// file: application/config/services.php
return [
    'foo' => '\StdClass',
    'application.service' => ['Application\Service', [], ['setFoo' => '@foo']]
];

SpiffyInject allows for setter injection in addition to constructor injection through the third array parameter. The key should be the name of the method and the value should be the value to inject. The example above creates the Application\Service and then injects the @foo service using the setFoo() method. Setter injection should be used for mutable dependencies.