여기에 가득 :
당신이 class_exists
을 사용하고 두 번째 인수로 true
을 통과 한 후, 클래스를 인스턴스화 할 수 있는지 여부를 확인하려면
(또는 그것을두고는,
true
이 기본값입니다) 자동 로딩, 네임 스페이스 지원, 비 정적 인스턴스의 호출 가능 (변수 경로 포함), 로딩 오류 및 사용자 정의 예외 처리를 나타내는 팩토리 된 객체입니다.
abstract class AbstractFactory implements \ArrayAccess
{
protected $manifest;
function __construct($manifest)
{
$this->manifest = $manifest;
}
abstract function produce($name);
public function offsetExists($offset)
{
return isset($this->manifest[$offset]);
}
public function offsetGet($offset)
{
return $this->produce($offset);
}
//implement stubs for other ArrayAccess funcs
}
abstract class SimpleFactory extends AbstractFactory {
protected $description;
protected $path;
protected $namespace;
function __construct($manifest, $path, $namespace = "jj\\") {
parent::__construct($manifest);
$this->path = $path;
$this->namespace = $namespace;
if (! spl_autoload_register(array($this, 'autoload'), false)) //throws exceptions on its own, but we want a custom one
throw new \RuntimeException(get_class($this)." failed to register autoload.");
}
function __destruct()
{
spl_autoload_unregister(array($this, 'autoload'));
}
public function autoload($class_name) {
$file = str_replace($this->namespace, '', $class_name);
$filename = $this->path.$file.'.php';
if (file_exists($filename))
try {
require $filename; //TODO add global set_error_handler and try clause to catch parse errors
} catch (Exception $e) {} //autoload exceptions are not passed by design, nothing to do
}
function produce($name) {
if (isset($this->manifest[$name])) {
$class = $this->namespace.$this->manifest[$name];
if (class_exists($class, $autoload = true)) {
return new $class();
} else throw new \jj\SystemConfigurationException('Factory '.get_class($this)." was unable to produce a new class {$class}", 'SYSTEM_ERROR', $this);
//an example of a custom exception with a string code and data container
} else throw new LogicException("Unknown {$this->description} {$name}.");
}
function __toString() //description function if custom exception class wants a string explanation for its container
{
return $this->description." factory ".get_class($this)."(path={$this->path}, namespace={$this->namespace}, map: ".json_encode($this->manifest).")";
}
}
마지막 예
:
namespace jj;
require_once('lib/AbstractFactory.php');
require_once('lib/CurrenciesProvider.php'); //base abstract class for all banking objects that are created
class CurrencyProviders extends SimpleFactory
{
function __construct()
{
$manifest = array(
'Germany' => 'GermanBankCurrencies',
'Switzerland' => 'SwissBankCurrencies'
);
parent::__construct($manifest, __DIR__.'/CurrencyProviders/', //you have total control over relative or absolute paths here
'banks\');
$this->description = 'currency provider country name';
}
}
지금
$currencies_cache = (new \jj\CurrencyProviders())['Germany'];
또는
$currencies_cache = (new \jj\CurrencyProviders())['Ukraine'];
LogicException("Unknown currency provider country name Ukraine")
은 더는 존재하지 않는 경우/CurrencyProviders /에서 SwissCurrencies.php 파일, 충분히 노력으로
\jj\SystemConfigurationException('Factory jj\CurrencyProviders was unable to produce a new class banks\SwissCurrencies. Debug data: currency provider country name factory jj\CurrencyProviders(path=/var/www/hosted/site/.../CurrencyProviders/, namespace=banks\, map: {"Germany": "GermanBankCurrencies", "Switzerland":"SwissBankCurrencies"}')
이 공장은 오류 (How to catch error of require() or include() in PHP?를) 구문 분석 잡을 생성자에 인수를 전달하는 확장 할 수 있습니다.
정확히 어떻게됩니까? 당신은 실패했다고 말했지만 실패하는 것은 아닙니다. – Charles
위의 코드를 호출하면 예외가 발생하지 않고 대신 표준 "치명적 오류 : 클래스 'foobarDomain'이 (가) bla에 없습니다."라는 메시지가 표시됩니다. 그리고 스크립트의 실행이 종료됩니다. – clops
좋습니다. 고마워요. 포함되기 전에 예외를 던지면 어떻게됩니까? – Charles