Подтвердить что ты не робот

Как я могу вызвать статический метод в классе переменных?

Я пытаюсь сделать какую-то функцию, которая загружает и создает экземпляр класса из заданной переменной. Что-то вроде этого:

<?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();

4b9b3361

Ответ 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 совпадает с именем класса, который вы хотите создать.