私は、与えられた変数からクラスをロードしてインスタンス化するある種の関数を作成しようとしています。このようなもの:
<?php
function loadClass($class) {
$sClassPath = SYSPATH."/classes/{$class}.php";
if (file_exists($sClassPath)) {
require_once($sClassPath);
$class = $class::getInstance();
}
}
?>
このように使用する場合:
<?php
loadClass('session');
?>
セッションクラスを含めてインスタンス化する必要があります。
ところで:静的getInstance関数は、このコードから来ています:
<?php
function getCallingClass() {
$backtrace = debug_backtrace();
$method = $backtrace[1]['function'];
$file = file($backtrace[1]['file']);
$line = $file[($backtrace[1]['line'] - 1)];
$class = trim(preg_replace("/^.+?([A-Za-z0-9_]*)::{$method}\(.*$/s", "\\1\\2", $line));
if(! class_exists($class)) {
return false;
} return $class;
}
class Core {
protected static $instances = array();
public static function getInstance() {
$class = getCallingClass();
if (!isset(self::$instances[$class])) {
self::$instances[$class] = new $class();
} return self::$instances[$class];
}
}
?>
問題は、現在、クラスで関数を使用する方法は次のとおりであるということです。
<?php
$session = session::getInstance();
?>
しかし、私はそれを関数に組み込みたいので、そのコード行を二度と使用する必要はありません。 loadClass( 'session');とだけ言います。そして、$ session-> blablablafunction()を使用できるよりも。
変数クラス名で静的関数を呼び出すことは、PHP 5.3:
Foo::aStaticMethod();
$classname = 'Foo';
$classname::aStaticMethod(); // As of PHP 5.3.0
http://php.net/manual/en/language.oop5.static.php
間違いなく自分で今すぐ使用できます。
それまでは、ロードするすべてのクラスがシングルトンになるように設計されていると想定することはできません。 5.3未満を使用している限り、クラスをロードし、コンストラクタを介してインスタンス化する必要があります。
function loadClass($class) {
$sClassPath = SYSPATH."/classes/{$class}.php";
if (file_exists($sClassPath)) {
require_once($sClassPath);
$class = new $class;
}
}
OR
オブジェクトを作成せずにクラスをロードするだけです。次に、シングルトンを対象とするものに対して「:: getInstance()」を呼び出し、そうでないものについては「new」をloadClass()関数の外部から呼び出します。
ただし、他の人が以前に指摘したように、__ autoload()はおそらくうまくいくでしょう。
call_user_func()
を使用できます。
$class = call_user_func(array($class, 'getInstance'));
最初の引数は、この場合のクラス名とメソッド名を含む callback
タイプです。
遅い静的バインディングはあなたのために働くと思います。各クラスのコンストラクトで以下を実行します。
class ClassName
{
public static $instances = array();
public function __construct()
{
self::$instances[] = $this;
}
}
それから...ここに私が作成したオートローダーがあります。これでジレンマが解決されるかどうかを確認してください。
// Shorten constants for convenience
define ('DS', DIRECTORY_SEPARATOR);
define ('PS', PATH_SEPARATOR);
$template = "default";
// Define an application path constants
define ('APP_ROOT', realpath('.').DS);
define ('VIEW', APP_ROOT . 'Views' . DS);
define ('MODEL', APP_ROOT . 'Models' . DS);
define ('CONTROLLER', APP_ROOT . 'Controllers' . DS);
define ('TEMPLATE', VIEW."templates".DS.$template.DS);
define ('CONTENT', VIEW."content".DS);
define ('HELPERS', MODEL."helpers".DS);
// Check if application is in development stage and set error reporting and
// logging accordingly
error_reporting(E_ALL);
if (defined('DEVELOPMENT')) {
ini_set('display_errors', 1);
} else {
ini_set('display_errors', 0);
ini_set('log_errors', 'On');
ini_set('error_log', APP_ROOT.'error.log');
}
$paths = array(APP_ROOT, VIEW, MODEL, CONTROLLER, TEMPLATE, CONTENT, HELPERS);
// Set the include path from Config Object
set_include_path(implode(PS, $paths));
// Autoloader
function __autoload($class)
{
require_once $class.'.php';
return;
}
その後、あなたがしなければならないのは
$var = new ClassName();
ただし、ClassName.phpという名前のphpファイルが必要です。ClassNameは、インスタンス化するクラスの名前と同じです。
PHPの現在の実装の静的バインディングと戦っているようです。これが、getCallingClassでフープをジャンプしている理由です。経験から教えていただけますが、おそらく静的メソッドを介して親クラスにインスタンス化を試みることをやめるべきです。最終的にはより多くの問題が発生します。 PHP 5.3は "late static binding" を実装し、あなたの問題を解決するはずですが、明らかに今は役に立ちません。
恐らく、kodishaが言及したautoload機能を堅実なシングルトン実装と組み合わせて使用したほうがよいでしょう。あなたの目標が構文糖衣であるかどうかはわかりませんが、長い目で見れば、数人のキャラクターを救おうとすることを避ける方が良いと思います。
私の頭の上で、テスト、検証などが必要です:
<?php
function loadClass($className) {
if (is_object($GLOBALS[$className]))
return;
$sClassPath = SYSPATH."/classes/{$className}.php";
if (file_exists($sClassPath)) {
require_once($sClassPath);
$reflect = new ReflectionClass($className);
$classObj = $reflect->newInstanceArgs();
$GLOBALS[$className] = $classObj;
}
}
?>