Service Proxy is a library that provides functionality to manage technical code over a class:
- Transactional context
- Security access
- Cache management
- Events
- Logs (not implemented yet)
The easiest way to install ServiceProxy is via composer.
Create the following composer.json
file and run the php composer.phar install
command to install it.
{
"require": {
"openclassrooms/service-proxy": "*"
}
}
<?php
require 'vendor/autoload.php';
use OpenClassrooms\ServiceProxy\ServiceProxy;
//do things
Interceptors are used as decorators to react to the method execution.
for example using @Cache
annotation, is a condition to enable the cache interceptor.
There is two types of interceptors:
Interceptors that are called before the method execution, they must implement OpenClassrooms\ServiceProxy\Interceptor\Contract\PrefixInterceptor
Three methods are called:
prefix
: called before the method execution. Should return instance ofOpenClassrooms\ServiceProxy\Interceptor\Response\Response
.supportsPrefix
: called to know if the interceptor should be called, for example in the case of the cache interceptor, it will check that the method has the@Cache
annotation.getPrefixPriority
: called to know the priority of the interceptor, the higher the priority, the earlier the interceptor will be called.
Interceptors that are called after the method execution, even if an exception is thrown, they must implement OpenClassrooms\ServiceProxy\Interceptor\Contract\SuffixInterceptor
Three methods are called:
suffix
: called after the method execution even if an exception is thrown. should return instance ofOpenClassrooms\ServiceProxy\Interceptor\Response\Response
.supportsSuffix
: called to know if the interceptor should be called, for example in the case of the cache interceptor, it will check that the method has the@Cache
annotation.getSuffixPriority
: called to know the priority of the interceptor, the higher the priority, the earlier the interceptor will be called.
If you want to react to an exception thrown by the method, you can check for the exception in the suffix interceptor.
- To check
$instance->method()->threwException()
- To get the exception (null if no exception was thrown)
$instance->method()->getException()
- To get the return value (null in case of an exception)
$instance->method()->getReturnValue()
- If a prefix interceptor returns a response with early return parameter set to
true
ex:Response($data, true)
, the method won't be executed and the suffix interceptors won't be called. - If a suffix interceptor returns a response with early return parameter set to
true
, the exception won't be thrown, in the case of a method that throws an exception.
You can create your own interceptors, or use the built-in ones:
Handlers are used by interceptors to manage the infrastructure code. To be able to use built-in interceptors, you need to implement the built-in handlers contracts.
- All handles need to implement
OpenClassrooms\ServiceProxy\Handler\Contract\AnnotationHandler
. - Each handler must have a unique name, you can use the
getName
method to return it. - Each handler must return true if it's the default handler or false if not, you can use the
isDefault
method to return it. - You can't have two handlers with the same name by annotation.
- You can have only one default handler, by annotation.
- If you have only one handler by annotation, it will be the default one.
example:
use OpenClassrooms\ServiceProxy\Annotation\Cache;
/**
* @Cache(handler="in_memory")
* to select the in_memory handler
*/
Check out the ServiceProxyBundle. The bundle provides an easy configuration option for this library.
First implement the handlers
use OpenClassrooms\ServiceProxy\Handler\Contract\CacheHandler;
class InMemoryCacheHandler implements CacheHandler
{
public function getName(): string
{
return 'in_memory';
}
...
}
class RedisCacheHandler implements CacheHandler
{
public function getName(): string
{
return 'redis';
}
...
}
Then you can inject the handlers into the interceptors:
$cacheInterceptor = new CacheInterceptor([new ArrayCacheHandler(), new RedisCacheHandler()]);
$prefixInterceptors = [
$cacheInterceptor,
new EventInterceptor([/* event handlers */]),
new TransactionInterceptor([/* transaction handlers */]),
new SecurityInterceptor([/* security handlers */]),
];
$suffixInterceptors = [
$cacheInterceptor,
new EventInterceptor(),
new TransactionInterceptor(),
];
$serviceProxyFactory = new ProxyFactory(
new Configuration(), //if no proxies directory is provided, the system tmp dir is used
$prefixInterceptors,
$SecurityInterceptor,
);
$proxy = $serviceProxyFactory->createProxy(new Class());
This library is based on Ocramius\ProxyManager.