Skip to content

Instantly share code, notes, and snippets.

@AmyStephen
Created December 2, 2012 16:57
Show Gist options
  • Save AmyStephen/4189804 to your computer and use it in GitHub Desktop.
Save AmyStephen/4189804 to your computer and use it in GitHub Desktop.
Services Mock up
<?php
/**
* @package Molajo
* @copyright 2012 Amy Stephen. All rights reserved.
* @license GNU GPL v 2, or later and MIT, see License folder
*/
namespace Molajo\Service;
use Molajo\Application;
use Molajo\Service\Services\Configuration\ConfigurationService;
defined('MOLAJO') or die;
/**
* Service
*
* The Services Class serves as a facade and can be useful over time for these goals:
*
* 1) Simplify application interface for developers
*
* 2) Provide a cushioning layer for change where backwards compatibility can be better insured
*
* 3) Serves as an abstraction layer for the API, making changes in the framework easier to implement
* while ensuring base services continue to produce expected results
*
* @return boolean
* @since 1.0
*/
Class Services
{
/**
* Used to connect to service either dynamically or reuse of an existing connection
*
* @static
* @param string $name
* @param array $arguments
*
* @return object
* @since 1.0
*/
public static function __callStatic($name, $arguments)
{
return Application::Services()->get($name . 'Service');
}
/**
* Connect Service
*
* @param string $key
*
* @return mixed
* @since 1.0
*
* @throws \BadMethodCallException
*/
protected function get($key)
{
try {
$serviceClass = 'Molajo\\Service\\Services\\'
. substr($key, 0, strlen($key) - strlen('service'))
. '\\'
. $key;
return $this->getClassInstance($serviceClass);
} catch (\Exception $e) {
$trace = debug_backtrace();
$caller = array_shift($trace);
$error_message = "Called by {$caller['function']}";
if (isset($caller['class'])) {
$error_message .= " in {$caller['class']}";
}
throw new \Exception($error_message);
}
}
/**
* Get Class Instance
*
* @param string $entry
* @param $folder $entry
*
* @return mixed
* @since 1.0
*/
private function getClassInstance($serviceClass)
{
if (class_exists($serviceClass)) {
} else {
throw new \Exception('Service Class ' . $serviceClass . ' does not exist.');
}
return new $serviceClass();
}
}
@AmyStephen
Copy link
Author

In the Front Controller: ( http://en.wikipedia.org/wiki/Front_Controller_pattern )

  • declare the namespace:
    use Molajo\Service\Services;

  • define a static property:
    /**

    • Application::Services
      *
    • @var object Services
    • @SInCE 1.0
      */
      protected static $services = null;
  • Include a connectivity method for the Services Class:

    /**

    • Application::Services
      *

    • @static

    • @return Services

    • @throws \RuntimeException

    • @SInCE 1.0
      */
      public static function Services()
      {
      if (self::$services) {
      } else {
      try {
      self::$services = new Services();
      } catch (\RuntimeException $e) {
      echo 'Instantiate Service Exception : ', $e->getMessage(), "\n";
      die;
      }
      }

      return self::$services;
      }

Within the application, calls to the Services connections can look like:

$results = Services::Registry()->set($key, $value);

$connection = Services::Database()->connect($configuration);

$user = Services::User()->get($id);

All of these calls use a dynamic, not static, instance of the underlying class which is handled by the Services Class.

The benefit is an abstracted layer between the application and the platform where "logic can occur." This can be useful in ushering in change without impacting the application.

Over time, it can also help to drive focus on simplifying the API and moving towards providing a level of service (for example, send email, save row, schedule event), without tying those services so closely to class and method names. In that sense, if phpmailer was swapped out for another email option, the change could be made without the application even being aware.

Given the foundation separation effort, a facade is also a useful approach to various groupings of underlying services.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment