2009-03-13 10 views
29

Ich versuche, eine Art von Funktion zu erstellen, die eine Klasse aus einer gegebenen Variablen lädt und instanziiert. Etwas wie folgt aus:Wie kann ich eine statische Methode für eine Variablenklasse aufrufen?

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

Wenn ich es so:

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

Es sollte die Sitzungsklasse gehören und instanziiert.

BTW: die statische getInstance Funktion kommt von 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 gerade jetzt die Möglichkeit, die Funktionen in einer Klasse zu verwenden, ist dies:

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

Aber jetzt möchte ich das in eine Funktion einbauen, damit ich nie wieder diese Codezeile benutzen muss. Ich sage nur loadClass ('Sitzung'); und dann kann ich $ session-> blablablafunction() verwenden;

Antwort

36

können Sie call_user_func() verwenden:

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

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

0

Es sieht so aus, als bekämpfest du PHPs aktuelle statische Implementierung der Implementierung, weshalb du mit getCallingClass durch die Ringe springst. Ich kann Ihnen aus Erfahrung sagen, dass Sie wahrscheinlich aufgeben sollten, Instantiierung in eine Elternklasse durch eine statische Methode zu setzen. Es wird dir am Ende mehr Probleme bereiten. PHP 5.3 wird "late static binding" implementieren und sollte Ihr Problem lösen, aber das hilft jetzt offensichtlich nicht.

Sie sind wahrscheinlich besser dran mit der von kodisha genannten Autoload-Funktionalität in Kombination mit einer soliden Singleton-Implementierung. Ich bin mir nicht sicher, ob Ihr Ziel syntaktischer Zucker ist oder nicht, aber Sie denken, dass Sie auf lange Sicht bessere Ergebnisse erzielen werden, wenn Sie versuchen, ein paar Zeichen zu sparen.

0

Aus der Spitze von meinem Kopf, muss Prüfung, Validierung 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; 
     } 
    } 

?> 
36

Aufruf statische Funktionen auf einen Namen Variable Klasse ist in PHP 5.3 anscheinend zur Verfügung:

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

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

Könnte ich jetzt definitiv selbst benutzen.

Bis dahin kann man nicht wirklich davon ausgehen, dass jede geladene Klasse ein Singleton ist. Solange Sie < 5 verwenden.3 Sie müssen nur die Klasse laden und instantiieren über den Konstruktor:

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

}

OR

einfach die Klasse laden, ohne ein Objekt von ihm zu schaffen. Rufen Sie dann ":: getInstance()" für diejenigen auf, die Singletons sein sollen, und "new" für diejenigen, die nicht von außerhalb der Funktion loadClass() stammen.

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

0

Späte statische Bindungen werden für Sie arbeiten, denke ich. In dem Konstrukt jeder Klasse zu tun:

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

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

Then ... Hier ist ein Autoloader ich herstellte. 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 alles, was Sie tun müssen, ist

$var = new ClassName(); 

aber Sie haben eine PHP-Datei in dem Pfad haben, mit dem Namen ClassName.php wo Klassenname der gleiche wie der Name der ist Klasse, die Sie instanziieren möchten.