0

Symfony's documentation for service factories explains how to allow the service container to instantiate services using factories, but does not explain what the recommended best practice is when creation fails, i.e. when the service is not available for whatever reason.

For example; imagine a Redis memory caching service. Inside the factory class, you have a method that will instantiate and return a Redis client object;

public function createRedisClient() {
  $redis = new \Redis();
  $connectionResult = $redis->connect($host, $port);

  return $redis;
}

If the Redis server is temporarily not available, and I would like to be able to gracefully fall back to another solution for storing whatever data we have, should the factory return null, throw an exception of some specific kind, or simply not care about availability?

Jay
  • 3
  • 2
  • Assuming that you expect the connection to be almost always available, just toss an exception. If you really do want a graceful degradation then do the chain thing and return some sort of fake cache as the answer below suggests. – Cerad Jun 06 '18 at 12:57

2 Answers2

0

You can use PHP's is_object method :

    public function createRedisClient() {
      $redis = new \Redis();
      $connectionResult = $redis->connect($host, $port);
      if (!is_object($redis)) {
        return false;
      }
      return $redis;
}

Return Value :

Returns TRUE if var is an object, FALSE otherwise.

Reference : PHP is_object

5eeker
  • 1,016
  • 1
  • 9
  • 30
  • I don't think this would be correct, as `$redis` would always be an object regardless if it managed to connect to the Redis server or not. – Jay Jun 07 '18 at 03:18
0

If you want a "fallback" solution best practice here is to group those kind of services under a common interface, than try to instantiate one at a time like a "chain of responsibility": first that can be instantiated, returns. Of course in your clients you'll use the interface so this process will be completely straightforward for "client developer".

Best way to obtain this is to have something like SessionStorageFactory (so a generic one) where you can "register" all concrete factories (RedisFactory, ... , DefaultSessionStorageFactory) and try to instantiate one at a time.

Of course the drawback is that if you could need a "superset" of attribute (like host, port and so on) that are useless for all factories but the concrete one where the parameter is required.

DonCallisto
  • 29,419
  • 9
  • 72
  • 100