Tôi có nên sử dụng spl_autoload_register () trong plugin của mình không?


11

Khi tôi sử dụng spl_autoload_register trong plugin của mình, tôi nhận được:

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

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

Tôi đã đọc một số và tìm thấy các bản sửa lỗi khác nhau. Một người trên SO nói không sử dụng spl_autoload_register với WordPress.

Điều đó có chính xác không?

Tôi chắc chắn rằng tôi có thể tìm thấy một "sửa chữa" cho lỗi, nhưng tôi không chắc chắn tôi muốn làm điều đó với mỗi bản phát hành WP.

Nếu tôi không sử dụng chức năng tự động tải, tôi nên tải các lớp của mình như thế nào? Đây là những gì phá vỡ bây giờ:

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

use MyPluginClasses\Student as MS;

$student = new MS\Student();

echo $student->sayHello();

Trong học sinh:

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

        }

    }
}

Thiết kế này hoạt động tốt bên ngoài WordPress.


4
Tôi đã cập nhật câu trả lời của tôi . Nếu bạn làm đúng - với chức năng gọi lại - bạn có thể sử dụng spl_autoload_register()mà không có tác dụng phụ tiêu cực.
fuxia

1
@toscho Mã của bạn vẫn là cách tốt nhất để tự động tải trong WP?
johnny

Không có nó không phải là. Cách nhanh nhất là vào glob()thư mục một lần, sau đó phân phối các lớp khi chúng cần spl_autoload_register().
fuxia

1
Tôi sẽ viết một câu trả lời sau, cho thấy giải pháp hiện tại (chưa được công bố) của chúng tôi từ Báo chí đa ngôn ngữ.
fuxia

Câu trả lời:


1

Tôi thực sự không chắc chắn liệu nó tốt hay xấu khi tự động tải các lớp trong plugin WP. Đối với tôi, tôi thấy không có tác dụng phụ của việc sử dụng spl_autoload_register(không được kiểm tra hiệu suất)

Vì vậy, để trả lời câu hỏi của bạn, tôi muốn chia sẻ một lớp từ plugin sắp tới mà tôi đang sử dụng để tự động tải các lớp từ một thư mục mà không có bất kỳ vấn đề nào và cho đến nay nó vẫn tốt cho tôi.

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

Để phá vỡ lớp đơn giản này trong các phần như bạn thấy tôi đang sử dụng mẫu Singleton. Constructorlà riêng tư và instance()& $_instancethuộc về mẫu. Con constructor có spl_autoload_registerchức năng.

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

đó là loadphương thức gọi từ lớp tự. Hai dòng đầu tiên của phương pháp này là:

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

đó là khá thẳng. nếu bạn theo WPCS, nó khuyến khích bạn tuân theo quy ước đặt tên lớp có tiền tố với lớp từ và sau đó là tên lớp. tất cả mọi dấu gạch dưới (_) được thay thế bằng dấu gạch ngang (-).

vì vậy một tên tập tin của lớp WPSE_Postsẽ làclass-wpse-post.php

Tên lớp vỏ thấp hơn với strtolowervà sử dụng str_replaceđể thay thế dấu gạch dưới bằng dấu gạch ngang. vì vậy WPSE_Postbây giờ trở thành wpse-post. cuối cùng thêm một tiền tố class-vào dòng tiếp theo.

tôi đang sử dụng is_readabletrong tuyên bố có điều kiện có thể trao đổi với file_exists. giả sử YOUR_PLUGIN_PATHlà đường dẫn cơ sở của plugin và classes-dirnằm dưới đường dẫn plugin chính chứa tất cả các lớp của bạn cần tự động tải.

include_once được sử dụng để tải tập tin thực tế trong cuộc gọi.

Sử dụng:

bạn chỉ cần đưa lớp trình tải tự động ở trên vào tệp cơ sở của plugin

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

và sau đó gọi các lớp học của bạn theo yêu cầu.

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

Lưu ý: Tôi không sử dụng phương thức không gian tên trong giải pháp của mình để nó có thể phù hợp hoặc không phù hợp với nhu cầu của bạn nhưng được đăng ở đây với hy vọng rằng ai đó ít nhất sẽ nhận được lợi ích của việc tải các lớp một cách linh hoạt.


-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
Mặc dù đăng mã là tốt, bạn nên giải thích làm thế nào và tại sao điều này trả lời câu hỏi.
Laxmana

1
vì plugin của bạn không phải là plugin duy nhất trong hệ thống, mã chỉ tải các lớp mà không cần xác minh trước rằng chúng là của bạn, sẽ sớm gây rắc rối bằng cách tải tệp sai cho một lớp được khai báo trong một plugin khác.
Đánh dấu Kaplun
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.