Skip to content

Instantly share code, notes, and snippets.

@Great-Antique
Created September 23, 2015 14:52
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Great-Antique/4a503c4993dd6739f939 to your computer and use it in GitHub Desktop.
Save Great-Antique/4a503c4993dd6739f939 to your computer and use it in GitHub Desktop.
Simple PHP Service Locator
<?php
/**
* Class ServiceLocator
*
* Simple service locator class
*/
class ServiceLocator implements ServiceLocatorInterface
{
/** @var array */
protected $servicesDefinitions = [];
/** @var Closure[]|mixed */
protected $services = [];
/**
* @param string $name
*
* @throw RuntimeException
*
* @return mixed
*/
public function get($name)
{
if (!is_string($name) || strlen($name) < 1) {
throw new RuntimeException(
"The service name is required."
);
}
if (!$this->has($name)) {
throw new RuntimeException(
"The service {$name} has not been registered with the locator."
);
}
$service = $this->servicesDefinitions[$name]['definition'];
$isFactory = $this->servicesDefinitions[$name]['isFactory'];
if (is_object($service) && !is_callable($service)) {
return $service;
} elseif (!$isFactory && isset($this->services[$name])) {
return $this->services[$name];
} elseif (is_callable($service)) {
$createdService = call_user_func_array($service, [$this]);
if ($isFactory) {
return $createdService;
} else {
$this->services[$name] = $createdService;
return $this->services[$name];
}
}
throw new RuntimeException(
"The service {$name} has not been registered correctly."
);
}
/**
* @param string $name
* @param Closure|mixed $service
* @param bool $isFactory
*
* @throw RuntimeException
*
* @return $this
*/
public function set($name, $service, $isFactory = false)
{
if (!is_string($name) || strlen($name) < 1) {
throw new RuntimeException(
"The service name is required."
);
}
if (isset($this->servicesDefinitions[$name])) {
$this->remove($name);
}
if (
!is_object($service)
&& !is_callable($service)
) {
$type = gettype($service);
throw new RuntimeException(
"Only objects and callable can be registered with the locator but '{$name}' has type '{$type}'."
);
}
if (!is_bool($isFactory)) {
$type = gettype($isFactory);
throw new RuntimeException(
"IsFactory parameter must be a boolean but '{$name}' has type '{$type}'."
);
}
$this->servicesDefinitions[$name] = [
'definition' => $service,
'isFactory' => $isFactory,
];
return $this;
}
/**
* @param string $name
*
* @return bool
*/
public function has($name)
{
return is_string($name)
&& strlen($name) > 1
&& isset($name, $this->servicesDefinitions)
&& isset($this->servicesDefinitions[$name]['definition'])
&& isset($this->servicesDefinitions[$name]['isFactory'])
? true
: false;
}
/**
* @param string $name
*
* @return $this
*/
public function remove($name)
{
if ($this->has($name)) {
unset($this->servicesDefinitions[$name]);
if (isset($this->services[$name])) {
unset($this->services[$name]);
}
}
return $this;
}
/**
* @return $this
*/
public function clear()
{
$this->services = [];
$this->servicesDefinitions = [];
return $this;
}
}
<?php
/**
* Interface ServiceLocatorInterface
*/
interface ServiceLocatorInterface
{
/**
* @param string $name
*
* @throw RuntimeException
*
* @return mixed
*/
public function get($name);
/**
* @param string $name
* @param Closure|mixed $service
* @param bool $isFactory
*
* @throw RuntimeException
*
* @return $this
*/
public function set($name, $service, $isFactory = false);
/**
* @param string $name
*
* @return bool
*/
public function has($name);
/**
* @param string $name
*
* @return $this
*/
public function remove($name);
/**
* @return $this
*/
public function clear();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment