Plötzlich kein autoload?

3Dnavigator

Erfahrenes Mitglied
Hallo zusammen
Ich komme hier irgendwie nicht weiter. Ich habe eine Autoload-Funktion, welche mir Klassen-Dateien laden soll, falls noch nicht geschehen:

PHP:
function __autoload($className){
	$arrDirectories = array(
		PATH_APP_CLASS,
		PATH_APP_CONTR,
		PATH_APP_MODEL,
		PATH_AR_CLASS,
		PATH_AR_CONTR,
		PATH_AR_FUNCT,
		PATH_AR_MODEL
	);
	foreach($arrDirectories as $directory){
		if(file_exists($directory.'/'.$className.'.php')){
			require($directory.'/'.$className.'.php');
			break;
		}
	}
}

Die Konstanten, welche die unterschiedlichen Verzeichnisse enthalten sind korrekt.
Nun funktioniert so weit auch. Nun habe ich eine Methode geschrieben, welche eine neue Instanz einer Klasse generieren und allfällige Argumente mitgeben soll:

PHP:
class arHelper {

	static public function newInstance(){
		$className = func_get_arg(0);
		$numArgs = func_num_args();
		if($numArgs > 1){
			$arrArgs = func_get_args();
			$argList = '';
			foreach($arrArgs as $key => $arg){
				if($key > 0){
					$argList .= '$arrArgs['.$key.'],';
				}
			}
			$argList = substr($argList, 0, -1);
		}
		if(isset($argList)){
			$res = eval("return new $className($argList);");
		} else{
			return new $className;
		}
	}

}

Das funktioniert so weit eigentlich auch.
Doch in dem folgenden Code, wird auf der zweiten Zeile der Methode initExtension() versucht eine Instanz der Klasse 'ar_login' zu erstellen.
Dabei tritt folgender Fehler auf: Fatal error: Class 'ar_login' not found in /Users/username/Sites/applicationname/ar/class/arHelper.php(18) : eval()'d code on line 1
Und dies, ohne (!) überhaupt die Autoloader-Funktion ausgeführt zu haben!

PHP:
<?php
class arBase {

	protected $output = 'html';
	protected $arrCss = array();
	protected $arrJs = array();
	
	function __construct(){
		$GLOBALS['DB'] = arHelper::newInstance('arDatabase', DB_HOST, DB_USER, DB_PASS, DB_DBASE, DB_PORT);
	}
	
	public function createOutput(){
		if(APP_LOGIN_NECESSARY && !isset($_SESSION['userId'])){
			$currentExt = 'ar';
			$currentCtr = 'login';
			$currentAct = 'index';
		}
		
		$this->tmpl = arHelper::newInstance('arTemplate');
		$this->tmpl->setOutput($this->getOutput());
		$this->tmpl->assign(array(
			'appAuthor' => APP_AUTHOR,
			'appTitle' => APP_NAME,
			'appCharset' => APP_CHARSET,
			'appDescription' => APP_DESCRIPTION,
			'appKeywords' => APP_KEYWORDS
		));
		$this->tmpl->addJsArr($this->getJsArr());
		$this->tmpl->assign('content', $this->initExtension($currentExt, $currentCtr, $currentAct));
		return $this->tmpl->create(PATH_TEMPLATE_MAIN);
	}
	
	protected function getJsArr(){
		return $this->arrJs;
	}
	
	public function getOutput(){
		return $this->output;
	}
	
	protected function initExtension($ext, $ctr, $act){
		$extensionName = $ext.'_'.$ctr;
		$extension = arHelper::newInstance($extensionName, $ext, $ctr, $act);
//		return $extension->$act();
	}

}
?>

Was ist da falsch? Ich stehe da total auf dem Schlauch...
Vielen Dank schon im Voraus für jede Hilfe!

Grüsse,
3Dnavigator
 
Weiss keiner einen Rat?

Ich habe in meiner Verzweiflung weiter gesucht und folgendes festgestellt:
1. In der constructor-Methode der arBase-Klasse funktioniert der Aufruf von arHelper::newInstance() problemlos. Auch wie Parameter werden alle übergeben, die notwendige Klasse inkl. Elternklassen werden korrekt und sauber gesucht und geladen.

2. Egal wie ich in der Methode createOutput() der gleichen Klasse diese Methode aufrufe, schlägt diese jedoch mit der genannten Fehlermeldung fehl.

Ich komme aber nicht drauf, was zu diesem Verhaltensunterschied führt.. Weiss jemand was nützliches?

Besten Dank schon im Voraus & Grüsse!
 
Da evil, äh eval, eine eigene PHP-Instanz darstellt denke ich, dass diese PHP-Instanz deinen Autoloader und eben auch die zu instanzierende Klasse nicht kennt.

Ist die Klasse ar_login die einzige Klasse die Argumente im Konstruktor erwartet?

Gruß
 
@Raisch: Nein, auch andere Klassen (siehe arDatabase in der arBase::__constructor Methode) erwartet Argumente. Dort funktionierts.

Konnte aber nun das Problem beheben;
Habe herausgefunden, dass das Problem lediglich nach dem Import der Smarty.class.php Datei auftrat (wird im Rahmen der arTemplate-Klasse geladen). Ich gehe deshalb nun davon aus, dass diese Klasse meine Autoloader-Methode überschreibt.
Nun habe ich als Lösung die initExtension-Methode einfach vor dem Instanzieren von arTemplate (und damit auch der Smarty-Klasse) gesetzt.
Nun funktioniert es wie erwartet..

Das war wohl eine Zangengeburt... grmpf..

Aber danke für die Überlegungen!

Grüsse aus der Schweiz
 
Um Autoloadkollisionen zu vermeiden, kann ich Dir dieses empfehlen:
  1. spl_autoload()
  2. spl_autoload_register()

Ich hatte das mal so gelöst:
PHP:
/**
 * Class to load unloaded classfiles.
 * 
 * @abstract
 * @author Rainer Schulz
 * @link http://raischblog.de/
 * @copyright 2011 - Rainer Schulz
 * @license CC BY-NC-SA 3.0 <http://creativecommons.org/licenses/by-nc-sa/3.0/>
 * @version 2.0 02/12/2011 14:13
 */
abstract class RsAutoLoad
{
    private static $arrPath = null;
    private static $arrExt  = null;

    public static function init( $strClassPath,
                                 $strInterfacePath,
                                 $strLibraryPath,
                                 $strModelPath,
                                 $strViewPath,
                                 $strControllerPath )
    {
        self::$arrPath = array (
            'class'      => $strClassPath,
            'interface'  => $strInterfacePath,
            'library'    => $strLibraryPath,
            'model'      => $strModelPath,
            'view'       => $strViewPath,
            'controller' => $strControllerPath
        );

        self::$arrExt = array(
            'class'     => '.class.php',
            'interface' => '.interface.php',
            'library'   => '.library.php'
        );

        spl_autoload_register( 'RsAutoLoad::loadClass' );
        spl_autoload_register( 'RsAutoLoad::loadLibrary' );
        spl_autoload_register( 'RsAutoLoad::loadController' );
        spl_autoload_register( 'RsAutoLoad::loadModel' );
        spl_autoload_register( 'RsAutoLoad::loadView' );
        spl_autoload_register( 'RsAutoLoad::loadInterface' );
    }

    public static function loadClass( $strClass )
    {
        return self::registerClass(
            self::$arrPath['class'].$strClass.self::$arrExt['class']
        );
    }

    public static function loadInterface( $strClass )
    {
        return self::registerClass(
            self::$arrPath['interface'].$strClass.self::$arrExt['interface']
        );
    }

    public static function loadLibrary( $strClass )
    {
        return self::registerClass(
            self::$arrPath['library'].$strClass.self::$arrExt['library']
        );
    }

    public static function loadModel( $strClass )
    {
        return self::registerClass(
            self::$arrPath['model'].$strClass.self::$arrExt['class']
        );
    }

    public static function loadView( $strClass )
    {
        return self::registerClass(
            self::$arrPath['view'].$strClass.self::$arrExt['class']
        );
    }

    public static function loadController( $strClass )
    {
        return self::registerClass(
            self::$arrPath['controller'].$strClass.self::$arrExt['class']
        );
    }

    private static function registerClass( $strFile )
    {
        if ( is_file( $strFile ) )
        {
            require $strFile;
            return true;
        }

        return false;
    }
}

Gruß
 
Wow, das ist ja genial! Hab' ich bereits vereinfacht bei mir implementiert und funktioniert nun auch sauber nach dem Include von Smarty.class.php!

Vielen vielen Dank - da hab' ich mal wieder was gescheites gelernt!
 
Zurück