it-swarm.com.de

Probleme beim automatischen Laden von Klassen über sp_autoload_register/möglicherweise störender WP-spezifischer Autoloader

Ich arbeite an einem Plugin, in dem ich für Autoloading-Klassen Folgendes mache:

function TFSLAutoload($class) {
    $classfile = dirname(__FILE__).'/includes/'.strtolower($class).'.php';
    include $classfile;
} // function TFSLAutoload
spl_autoload_register('TFSLAutoload');

Im Plugin (Klassen) kann ich Klassen instanziieren (z. B. $myClassXYZ = new MyClassXYZ(); verwenden) sowie statische Funktionen (z. B. MyClassXYZ::my_static_func();) verwenden, ohne die Datei einzuschließen/zu erfordern, die die Klasse selbst definiert. Kurz gesagt, alles funktioniert wie erwartet.

Wenn WP_DEBUG auf true gesetzt ist, werden jedoch die folgenden Warnungen angezeigt:

Warning: include(/var/www/vhosts/MY-DOMAIN.TLD/wp-content/plugins/tf-song-list/includes/wp_atom_server.php): failed to open stream: No such file or directory in /var/www/vhosts/MY-DOMAIN.TLD/wp-content/plugins/tf-song-list/tf-song-list.php on line 31 
Warning: include(): Failed opening '/var/www/vhosts/MY-DOMAIN.TLD/wp-content/plugins/tf-song-list/includes/wp_atom_server.php' for inclusion (include_path='.:') in /var/www/vhosts/MY-DOMAIN.TLD/wp-content/plugins/tf-song-list/tf-song-list.php on line 31 
Warning: include(/var/www/vhosts/MY-DOMAIN.TLD/wp-content/plugins/tf-song-list/includes/Recursive_ArrayAccess.php): failed to open stream: No such file or directory in /var/www/vhosts/MY-DOMAIN.TLD/wp-content/plugins/tf-song-list/tf-song-list.php on line 31 
Warning: include(): Failed opening '/var/www/vhosts/MY-DOMAIN.TLD/wp-content/plugins/tf-song-list/includes/Recursive_ArrayAccess.php' for inclusion (include_path='.:') in /var/www/vhosts/MY-DOMAIN.TLD/wp-content/plugins/tf-song-list/tf-song-list.php on line 31
Warning: include(/var/www/vhosts/MY-DOMAIN.TLD/wp-content/plugins/tf-song-list/includes/WP_Session.php): failed to open stream: No such file or directory in /var/www/vhosts/MY-DOMAIN.TLD/wp-content/plugins/tf-song-list/tf-song-list.php on line 31 
Warning: include(): Failed opening '/var/www/vhosts/MY-DOMAIN.TLD/wp-content/plugins/tf-song-list/includes/WP_Session.php' for inclusion (include_path='.:') in /var/www/vhosts/MY-DOMAIN.TLD/wp-content/plugins/tf-song-list/tf-song-list.php on line 31

Ich habe dann meine Autoload-Funktion geändert, um zuerst zu überprüfen, ob die Datei existiert:

function TFSLAutoload($class) {
    $classfile = dirname(__FILE__).'/includes/'.strtolower($class).'.php';
    if (file_exists($classfile)) include $classfile;
    else echo "File »$classfile« does not exist.".PHP_EOL;
} // function TFSLAutoload
spl_autoload_register('TFSLAutoload');

Jetzt werden nur meine eigenen Plugin-Klassendateien vom Autoloader geladen, da sie die einzigen Dateien sind, die im vordefinierten Ordner abgelegt sind.

Wenn die drei genannten WordPress-Klassen jedoch immer noch durch meine Autolaoder-Klasse "gesendet" werden, werden sie von WP überhaupt (tatsächlich) korrekt geladen? Oder konkurriert mein Autoloader mit dem eingebauten Autoloader von WP? Wie kann ich das überprüfen? Oder: Mache ich das ganze Autoloading falsch?

Und warum werden diese drei Klassen an meinen Autoloader gesendet? Sind sie die einzigen, die nach dem Laden der Plugins geladen werden?

5
tfrommen

Es gibt keinen eingebauten Autoloader in WordPress. Andere Plugins oder ein Thema haben möglicherweise einen Autoloader registriert, und je nach Ausführungsreihenfolge werden diese früher oder später als Ihre aufgerufen.


Update 21. 08. 2014 Diese Antwort ist nicht mehr das, was ich empfehlen würde. Verwenden Sie gegebenenfalls einen Autoloader.


Die einzige Möglichkeit, sicherzustellen, dass die aufgerufene Klasse in der Verantwortung Ihres Codes liegt, besteht darin, mit file_exists() zu prüfen und den Klassennamen zu testen.

file_exists() ist langsam und das Ergebnis wird vom Dateisystem zwischengespeichert, sodass Sie sich sowieso nicht darauf verlassen können.

Ich empfehle keinen Autoloader zu verwenden . Verwenden Sie stattdessen ein Plugin-spezifisches Klassenladeprogramm.

Beispiel:

/**
 * Load a class from /php/ directory.
 *
 * There is no file_exists() check to improve performance.
 *
 * @param  string  $class         Class name
 * @param  boolean $create_object Return an object or TRUE
 * @return bool|$class
 */
function t5_es_load_class( $class, $create_object = FALSE )
{
    // create the path base just once
    static $base = FALSE;

    ! $base && $base = plugin_dir_path( __FILE__ ) . 'php';
    ! class_exists( $class ) && require "$base/class.$class.php";

    return $create_object ? new $class : TRUE;
}

Jetzt können Sie mit dieser Funktion entweder nur die Klasse einschließen ...

t5_es_load_class( 'T5_Metabox_Base' );
$metabox = new T5_Metabox_Base( 'preview' );

… Oder ein Objekt erstellen…

$data               = t5_es_load_class( 'T5_Property_List', TRUE );
$data->plugin_url   = plugin_dir_url( __FILE__ );
$data->plugin_path  = plugin_dir_path( __FILE__ );

Schneller, zuverlässiger, flexibler.

4
fuxia

Wenn Sie einen eindeutigen Namespace für Ihre Klassen haben, funktioniert dies. Ich benutze dieses Schema:

  1. Stellen Sie alle Ihre Klassen in den Namespace, sagen wir myplugin (Sie können natürlich weitere Namespaces haben, wie myplugin\otherstuff\...).

  2. Erstellen Sie einen Autoloader, der die Klassen nur in diesem Namespace lädt. Sie können diesen verwenden, indem Sie ihn auf Ihre Plugin-Datei setzen:

    define("MYPLUGIN_DIR", plugin_dir_path(__FILE__));
    
    // Notice strlen(...) calls should be written as number for speed
    spl_autoload_register(function ($className) {           
        // Make sure the class included is in this plugins namespace
        if (substr($className, 0, strlen("myplugin\\")) === "myplugin\\") {
            // Remove myplugin namespace from the className
            // Replace \ with / which works as directory separator for further namespaces
            $classNameShort = str_replace("\\", "/", substr($className, strlen("myplugin\\")));
            include_once MYPLUGIN_DIR . "classes/$classNameShort.php";
        }
    });
    

Das ist es, es funktioniert gut für mehrere Plugins, wenn Sie für jedes einen anderen Namespace haben (und Sie sollten es trotzdem tun).

5
Ciantic

Sie können jetzt ein Plugin WordPress Autoloader verwenden. Es unterstützt auch Ihre eigenen Autoload-Methoden.

Weitere Informationen finden Sie auf der Seite WordPress-Plugin .

Durch die ordnungsgemäße Verwendung von PHP __autoload kann die Ladezeit von WP Websites drastisch reduziert werden.

Ein Beispiel Ihrer eigenen __autoload-Funktion ist problematisch. Sie sollten über eine Sortierüberprüfung verfügen, um sicherzustellen, dass Sie nur Ihre eigenen Klassen laden, um Probleme zu vermeiden.

Bitte beachten Sie, dass beim Laden von Klassen die Verwendung von require_once oder i empfohlen wird

0
D.A.H