Czy powinienem używać spl_autoload_register () w mojej wtyczce?


11

Kiedy używam spl_autoload_register w mojej wtyczce, otrzymuję:

    Fatal error: Uncaught exception 'LogicException' with message
   'Class wp_atom_server could not be loaded'

    wp-includes\pluggable-deprecated.php on line 182

Przeczytałem i znalazłem różne poprawki. Jeden z SO powiedział, aby nie używać spl_autoload_register z WordPress.

Czy to jest dokładne?

Jestem pewien, że mogę znaleźć „naprawę” błędu, ale nie jestem pewien, czy chcę to zrobić z każdą wersją WP.

Jeśli nie używam funkcji automatycznego ładowania, jak powinienem ładować moje klasy? Oto, co się teraz psuje:

spl_autoload_extensions(".php");
spl_autoload_register();

use MyPluginClasses\Student as MS;

$student = new MS\Student();

echo $student->sayHello();

W uczniu:

<?PHP
namespace MyPluginClasses\Student
{
    class Student{
        public function __Construct(){
            echo "Hello Johnny";
        }
        public function sayHello(){
            echo "Hello Johnny's Method";

        }

    }
}

Ten projekt działa dobrze poza WordPress.


4
Zaktualizowałem swoją odpowiedź . Jeśli zrobisz to dobrze - z funkcją oddzwaniania - możesz używać spl_autoload_register()bez negatywnych skutków ubocznych.
fuxia

1
@toscho Czy Twój kod jest nadal najlepszym sposobem na automatyczne ładowanie w WP?
Johnny

Nie, nie jest. Najszybszym sposobem jest przejście do glob()katalogu jeden raz, a następnie dostarczenie klas, gdy są potrzebne spl_autoload_register().
fuxia

1
Później napiszę odpowiedź, pokazując nasze obecne (jeszcze nieopublikowane) rozwiązanie z Multilingual Press.
fuxia

Odpowiedzi:


1

Naprawdę nie jestem pewien, czy dobrą lub złą praktyką jest automatyczne ładowanie klas we wtyczce WP. Dla mnie nie widzę żadnych skutków ubocznych używania spl_autoload_register(nie testowana wydajność)

Aby odpowiedzieć na twoje pytanie, chciałbym podzielić się klasą z mojej nadchodzącej wtyczki, której używam do automatycznego ładowania klas z jednego katalogu bez żadnych problemów i jak dla mnie to dobrze.

/**
 * Annframe Class Autoloader.
 *
 * @package Annframe
 * @since 0.1.0
 */
class Annframe_Autoloader {
    /**
     * Singleton.
     *
     * @since 0.1.0
     * @var Annframe_Autoloader - Single instance.
     */
    private static $_instance = null;

    /**
     * Private Construct.
     *
     * @package Annframe
     * @since 0.1.0
     */
    private function __construct() {
        spl_autoload_register( array( $this, 'load' ) );
    }

    /**
     * Singleton method.
     *
     * @package Annframe
     * @since 0.1.0
     */
    public static function _instance() {
        if ( ! self::$_instance ) {
            self::$_instance = new Annframe_Autoloader();
        }
        return self::$_instance;
    }

    /**
     * Class Loader.
     *
     * @package Annframe
     * @since 0.1.0
     *
     * @param string $class_name - Class name to load.
     * @return null - Do not return anything.
     */
    public function load( $class_name ) {
        $file = str_replace( '_', '-', strtolower( $class_name ) );
        $file = 'class-' . $file;
        if ( is_readable( trailingslashit( YOUR_PLUGIN_PATH. '/classes-dir' ) . $file . '.php' ) ) {
            include_once trailingslashit( YOUR_PLUGIN_PATH. '/classes-dir' ) . $file . '.php';
        }
        return;
    }
}

Annframe_Autoloader::_instance();

Aby rozbić tę prostą klasę na części, jak widać, używam wzorca Singleton. Constructorsą prywatne instance()i $_instancenależący do wzorca. Konstruktor ma spl_autoload_registerfunkcję.

spl_autoload_register( array( $this, 'load' ) );

która wywołuje loadmetodę z klasy własnej. Pierwsze dwie linie tej metody to:

$file = str_replace( '_', '-', strtolower( $class_name ) );
$file = 'class-' . $file;

co jest całkiem proste. jeśli postępujesz zgodnie z WPCS , zachęca cię do przestrzegania konwencji nazewnictwa klas poprzedzonej słowem class, a następnie nazwa klasy. oczywiście wszelkie podkreślenia (_) są zastępowane myślnikiem (-).

więc nazwa pliku klasy WPSE_Posttoclass-wpse-post.php

Niższe nazwy klas obudów za strtolowerpomocą i za pomocą str_replacezastępuj podkreślniki myślnikami. tak WPSE_Postteraz staje się wpse-post. w końcu dodając prefiks class-w następnym wierszu.

używam is_readablew warunkowym oświadczeniu, które można wymienić file_exists. zakładając, że YOUR_PLUGIN_PATHjest to podstawowa ścieżka wtyczki i classes-dirznajduje się pod głównym katalogiem wtyczek, w którym przechowywane są wszystkie klasy, które wymagają automatycznego ładowania.

include_once służy do ładowania rzeczywistego pliku podczas połączenia.

Stosowanie:

wystarczy dołączyć powyższą klasę modułu ładującego do pliku podstawowego wtyczki

/**
 * Class autoloader.
 */
if ( ! class_exists( 'Annframe_Autoloader' ) ) {
    include_once YOUR_PLUGIN_PATH/class-annframe-autoloader.php';
}

a następnie zadzwoń na zajęcia na żądanie.

new XYX_Class();
Another_Class::instance(); // etc

Uwaga: w moim rozwiązaniu nie używam metody przestrzeni nazw, więc może ona, ale nie musi, pasować do twoich potrzeb, ale opublikowałem ją tutaj, mając nadzieję, że przynajmniej ktoś uzyska korzyści z dynamicznego ładowania klas.


-1
    function MyPluginClasses_autoloader( $class_name ) {
  if ( false !== strpos( $class_name, 'MyPluginClasses' ) ) {
    $parts = explode('\\', $class_name);
    require_once RoothPath . DIRECTORY_SEPARATOR .'lib'.DIRECTORY_SEPARATOR.end($parts) . '.php';
  }
}
spl_autoload_register( 'MyPluginClasses_autoloader' );
use MyPluginClasses\Student as MS;
$student = new MS\Student();
echo $student->sayHello();

2
Chociaż kod pocztowy jest dobry, należy wyjaśnić, w jaki sposób i dlaczego odpowiada on na pytanie.
Laxmana

1
ponieważ twoja wtyczka nie jest jedyną wtyczką w systemie, kod, który po prostu ładuje klasy bez uprzedniego sprawdzenia, że ​​są twoje, spowoduje prędzej czy później problemy, próbując załadować niewłaściwy plik dla klasy zadeklarowanej w innej wtyczce.
Mark Kaplun
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.