¿Debo usar spl_autoload_register () en mi complemento?

11

Cuando uso spl_autoload_register en mi complemento, obtengo:

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

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

Leí un poco y encontré varias soluciones. Uno en SO dijo que no usara spl_autoload_register con WordPress.

¿Es eso exacto?

Estoy seguro de que puedo encontrar una "solución" para el error, pero no estoy seguro de querer hacerlo con cada versión de WP.

Si no uso la función de carga automática, ¿cómo debo cargar mis clases? Esto es lo que se rompe ahora:

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

use MyPluginClasses\Student as MS;

$student = new MS\Student();

echo $student->sayHello();

En estudiante:

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

        }

    }
}

Este diseño funciona bien fuera de WordPress.

johnny
fuente
44
He actualizado mi respuesta . Si lo hace correctamente, con una función de devolución de llamada, puede usarlo spl_autoload_register()sin efectos secundarios negativos.
fuxia
1
@toscho ¿Su código sigue siendo la mejor manera de cargar automáticamente en WP?
johnny
No, no es. La forma más rápida es ir glob()al directorio una vez, luego entregar las clases cuando se necesiten spl_autoload_register().
fuxia
1
Escribiré una respuesta más tarde, mostrando nuestra solución actual (aún no publicada) de Multilingual Press.
fuxia

Respuestas:

1

Realmente no estoy seguro de si es una buena o mala práctica cargar automáticamente las clases en el complemento WP. Para mí, no veo efectos secundarios del uso spl_autoload_register(rendimiento no probado)

Entonces, para responder a su pregunta, me gustaría compartir una clase de mi próximo complemento que estoy usando para cargar automáticamente las clases desde un solo directorio sin ningún problema y hasta ahora me ha ido bien.

/**
 * 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();

Para romper esta clase simple en partes como ves, estoy usando el patrón Singleton. Constructores privado y instance()y $_instancepertenece al patrón. El constructor tiene spl_autoload_registerfunción.

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

que es llamar al loadmétodo de la auto clase. Las dos primeras líneas de este método son:

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

que es bastante directo si sigue WPCS, lo alienta a seguir una convención de nomenclatura de clase con el prefijo word class y luego el nombre de la clase. por supuesto, cualquier guión bajo (_) se reemplaza con un guión (-).

entonces un nombre de archivo de clase WPSE_Postseríaclass-wpse-post.php

Menores nombres de clase de carcasa con strtolowery usando str_replacepara reemplazar guiones bajos con guiones. así que WPSE_Postahora se hace wpse-post. finalmente agregando un prefijo class-en la siguiente línea.

Estoy usando una is_readabledeclaración condicional que es intercambiable con file_exists. asumiendo que YOUR_PLUGIN_PATHes la ruta base del complemento y classes-direstá bajo el directorio principal del complemento que contiene todas sus clases que necesitan carga automática.

include_once se usa para cargar el archivo real en la llamada.

Uso:

solo necesita incluir la clase de cargador automático anterior en el archivo base de su complemento

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

y luego llame a sus clases a pedido.

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

Nota: No estoy utilizando el método de espacio de nombres en mi solución, por lo que puede o no ajustarse de acuerdo a sus necesidades, pero publicado aquí con la esperanza de que alguien obtenga al menos los beneficios de cargar clases dinámicamente.

Anwer AR
fuente
-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();
Meldin Xavier
fuente
2
Aunque publicar código es bueno, debe explicar cómo y por qué esto responde la pregunta.
Laxmana
1
Como su complemento no es el único en el sistema, el código que solo carga clases sin verificar primero que son suyos, creará problemas tarde o temprano al intentar cargar el archivo incorrecto para una clase declarada en otro complemento.
Mark Kaplun