it-swarm.com.de

Wie kann ich eine statische Methode für eine Variablenklasse aufrufen?

Ich versuche, eine Art Funktion zu erstellen, die eine Klasse aus einer gegebenen Variablen lädt und instanziiert. Etwas wie das:

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

Wenn ich es so benutze:

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

Die Session-Klasse sollte eingeschlossen und instanziiert werden.

Übrigens: Die statische getInstance-Funktion stammt aus diesem Code:

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

  }

?>

Die Sache ist, dass die Funktionen in einer Klasse jetzt so zu verwenden sind:

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

Aber jetzt möchte ich das in eine Funktion einbauen, so dass ich diese Codezeile nie mehr verwenden muss. Ich sage nur loadClass ('session'); );

34
Jelle Spekken

Das Aufrufen statischer Funktionen für einen Variablenklassennamen ist anscheinend in PHP 5.3 verfügbar.

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

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

Könnte das jetzt definitiv selbst verwenden.

Bis dahin können Sie nicht wirklich annehmen, dass jede Klasse, die Sie laden, als Einzelspieler konzipiert ist. Solange Sie <5.3 verwenden, müssen Sie einfach die Klasse laden und über den Konstruktor instanziieren:

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

}

OR

Laden Sie einfach die Klasse, ohne daraus ein Objekt zu erstellen. Rufen Sie dann ":: getInstance ()" für diejenigen auf, die als Singletons gedacht sind, und "new" für diejenigen, die nicht außerhalb der loadClass () - Funktion sind.

Obwohl, wie andere bereits erwähnt haben, ein __autoload () wahrscheinlich für Sie gut funktionieren würde.

44
talentedmrjones

Sie können call_user_func() verwenden:

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

Das erste Argument ist ein callback -Typ, der in diesem Fall den Klassennamen und den Methodennamen enthält.

38
Greg

Warum nicht die __autoload () - Funktion verwenden?

http://www.php.net/autoload

dann instanziieren Sie das Objekt, wenn es benötigt wird.

2
kodisha

Späte statische Bindungen funktionieren für Sie, denke ich. Im Konstrukt jeder Klasse:

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

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

Dann ....__ Hier ist ein Autoloader, den ich erstellt habe. Sehen Sie, ob dies Ihr Dilemma löst.

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

Dann müssen Sie nur noch etwas tun

$var = new ClassName();

sie müssen jedoch eine PHP-Datei mit dem Namen .__ im Pfad haben. ClassName.php Dabei entspricht ClassName dem Namen der Klasse, die Sie instanziieren möchten.

0
Corey Ray

Es sieht so aus, als würden Sie die derzeitige statische Bindung von PHP bekämpfen, weshalb Sie mit getCallingClass durch die Reifen springen. Ich kann Ihnen aus Erfahrung sagen, dass Sie den Versuch, eine Instanziierung durch eine statische Methode in eine übergeordnete Klasse einzufügen, wahrscheinlich aufgeben sollten. Es wird am Ende mehr Probleme verursachen. PHP 5.3 wird "spätes statisches Binden" implementieren und sollte Ihr Problem lösen, aber das hilft jetzt offensichtlich nicht. 

Sie können die von kodisha erwähnte Autoload-Funktionalität in Kombination mit einer soliden Singleton-Implementierung wahrscheinlich besser nutzen. Ich bin mir nicht sicher, ob Ihr Ziel syntaktischer Zucker ist oder nicht, aber Sie denken, Sie werden es auf lange Sicht besser machen, wenn Sie versuchen, ein paar Zeichen zu retten.

0
Barrett Conrad

Ganz oben auf dem Kopf, muss getestet, validiert werden usw.:

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

?>
0
J.C. Inacio