Как я могу вызвать статический метод в классе переменных?
Я пытаюсь сделать какую-то функцию, которая загружает и создает экземпляр класса из заданной переменной. Что-то вроде этого:
<?php
function loadClass($class) {
$sClassPath = SYSPATH."/classes/{$class}.php";
if (file_exists($sClassPath)) {
require_once($sClassPath);
$class = $class::getInstance();
}
}
?>
Если я использую его следующим образом:
<?php
loadClass('session');
?>
Он должен включать и создавать экземпляр класса сеанса.
BTW: статическая функция 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();
Ответы
Ответ 1
Вызов статических функций в имени класса переменных, по-видимому, доступен в 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;
}
}
ИЛИ
Просто загрузите класс, не создавая из него объект. Затем вызовите ":: getInstance()" для тех, которые предназначены для синглонов, и "новые" для тех, которые не являются, из-за функции loadClass().
Хотя, как указывали другие ранее, __autoload(), вероятно, будет хорошо работать для вас.
Ответ 2
Вы можете использовать call_user_func()
:
$class = call_user_func(array($class, 'getInstance'));
Первый аргумент - это callback
, содержащий имя класса и имя метода в этом случае.
Ответ 3
Почему бы не использовать функцию __autoload()?
http://www.php.net/autoload
тогда вы просто создаете объект при необходимости.
Ответ 4
Похоже, вы боретесь с текущей реализацией текущей реализации PHP, поэтому вы прыгаете через обручи с помощью getCallingClass. Я могу сказать вам по опыту, вы, вероятно, должны отказаться от попытки создания экземпляра в родительском классе с помощью статического метода. В конце концов это вызовет больше проблем. PHP 5.3 будет реализовывать "late static binding" и должен решить вашу проблему, но это, очевидно, сейчас не помогает.
Вероятно, вам лучше использовать функциональность автозагрузки, упомянутую kodisha, в сочетании с твердой реализацией Singleton. Я не уверен, что ваша цель - синтаксический сахар или нет, но он думает, что в конечном итоге вы добьетесь большего успеха, чтобы избежать попыток сохранить несколько символов.
Ответ 5
Сверху моей головы нужно тестирование, проверка и т.д.:
<?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;
}
}
?>
Ответ 6
Позднее статические привязки будут работать для вас, я думаю. В конструкции каждого класса do:
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();
но вы должны иметь php файл в пути с именем ClassName.php
где ClassName совпадает с именем класса, который вы хотите создать.