简体   繁体   English

如何在变量类上调用静态方法?

[英]How can I call a static method on a variable class?

I'm trying to make some kind of function that loads and instantiates a class from a given variable. 我正在尝试创建一种从给定变量加载和实例化类的函数。 Something like this: 像这样的东西:

<?php
function loadClass($class) {
  $sClassPath = SYSPATH."/classes/{$class}.php";
  if (file_exists($sClassPath)) {
    require_once($sClassPath);
    $class = $class::getInstance();
  }
}
?>

If I use it like this: 如果我像这样使用它:

<?php
  loadClass('session');
?>

It should include and instantiate the session class. 它应该包括并实例化会话类。

BTW: the static getInstance function comes from this code: 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];
    }

  }

?>

The thing is that right now the way to use the functions in a class is this: 问题是,现在使用类中的函数的方法是这样的:

<?php
  $session = session::getInstance();
?>

But now I want to build that into a function so that I never again have to use that line of code. 但是现在我想将它构建成一个函数,以便我再也不必使用那行代码。 I just say loadClass('session'); 我只是说loadClass('session'); and than I can use $session->blablablafunction(); 而且我可以使用$ session-> blablablafunction();

Calling static functions on a variable class name is apparently available in PHP 5.3: 在PHP 5.3中显然可以在变量类名上调用静态函数:

Foo::aStaticMethod();
$classname = 'Foo';
$classname::aStaticMethod(); // As of PHP 5.3.0

http://php.net/manual/en/language.oop5.static.php http://php.net/manual/en/language.oop5.static.php

Could definitely use that right now myself. 我自己肯定可以使用它。

Until then you can't really assume that every class you are loading is designed to be a singleton. 在此之前,您无法真正假设您正在加载的每个类都设计为单例。 So long as you are using < 5.3 you'll have to just load the class and instantiate via the constructor: 只要你使用<5.3,就必须加载类并通过构造函数实例化:

function loadClass($class) {
  $sClassPath = SYSPATH."/classes/{$class}.php";
  if (file_exists($sClassPath)) {
    require_once($sClassPath);
    $class = new $class;
  }

} }

OR 要么

Just load the class without creating an object from it. 只需加载类而不从中创建对象。 Then call "::getInstance()" on those meant to be singletons, and "new" on those that are not, from outside of the loadClass() function. 然后在那些意味着是单例的东西上调用“:: getInstance()”,在loadClass()函数之外调用那些不是“new”的东西。

Although, as others have pointed out earlier, an __autoload() would probably work well for you. 虽然,正如其他人早先指出的那样,__ autoload()可能对您有用。

You can use call_user_func() : 您可以使用call_user_func()

$class = call_user_func(array($class, 'getInstance'));

The first argument is a callback type containing the classname and method name in this case. 第一个参数是一个callback类型,在这种情况下包含类名和方法名。

Why not use __autoload() function? 为什么不使用__autoload()函数?

http://www.php.net/autoload http://www.php.net/autoload

then you just instantiate object when needed. 那么你只需要在需要时实例化对象。

Late static bindings will work for you I think. 我认为,后期静态绑定对你有用。 In the construct of each class do: 在每个类的构造中做:

class ClassName
{
    public static $instances = array();

    public function __construct()
    {
        self::$instances[] = $this;
    }
}

Then... Here is an autoloader I created. 然后......这是我创建的自动加载器。 See if this solves your dilemma. 看看这是否解决了你的困境。

// 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;
}

Then all you have to do is 那么你所要做的就是

$var = new ClassName();

but you have to have a php file in the path with the name ClassName.php where ClassName is the same as the name of the class you want to instantiate. 但是你必须在名为ClassName.php的路径中有一个php文件,其中ClassName与要实例化的类的名称相同。

It looks like you are fighting PHP's current implementation static binding, which is why you are jumping through hoops with getCallingClass. 看起来你正在与PHP的当前实现静态绑定作斗争,这就是你使用getCallingClass跳过箍的原因。 I can tell you from experience, you should probably abandon trying to put instantiation in a parent class through a static method. 我可以从经验告诉你,你应该放弃尝试通过静态方法将实例化放在父类中。 It will cause you more problems in the end. 它最终会给你带来更多问题。 PHP 5.3 will implement "late static binding" and should solve your problem, but that obviously doesn't help now. PHP 5.3将实现“后期静态绑定”并应解决您的问题,但现在显然没有帮助。

You are probably better off using the autoload functionality mentioned by kodisha combined with a solid Singleton implementation. 你可能最好使用kodisha提到的自动加载功能和一个可靠的Singleton实现。 I'm not sure if your goal is syntactic sugar or not, but it think you will do better in the long run to steer clear of trying to save a few characters. 我不确定你的目标是否是语法糖,但它认为从长远来看你会做得更好,避免试图保存一些角色。

Off the top of my head, needs testing, validation etc: 在我的头顶,需要测试,验证等:

<?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;
        }
    }

?>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM