Tự động tải là gì; Làm thế nào để bạn sử dụng spl_autoload, __autoload và spl_autoload_register?


203

Tôi đang học các tiêu chuẩn PHP nâng cao và cố gắng thực hiện các phương thức mới và hữu ích. Trước đây tôi đã sử dụng __autoloadchỉ để thoát bao gồm nhiều tệp trên mỗi trang, nhưng gần đây tôi đã thấy một mẹo trên__autoload manual

spl_autoload_register () cung cấp một sự thay thế linh hoạt hơn cho các lớp tự động tải. Vì lý do này, việc sử dụng __autoload () không được khuyến khích và có thể không được chấp nhận hoặc bị xóa trong tương lai.

nhưng tôi thực sự không thể tìm ra cách thực hiện spl_autoloadspl_autoload_register

Câu trả lời:


334

spl_autoload_register() cho phép bạn đăng ký nhiều hàm (hoặc phương thức tĩnh từ lớp Autoload của riêng bạn) mà PHP sẽ đưa vào ngăn xếp / hàng đợi và gọi tuần tự khi một "Lớp mới" được khai báo.

Ví dụ:

spl_autoload_register('myAutoloader');

function myAutoloader($className)
{
    $path = '/path/to/class/';

    include $path.$className.'.php';
}

//-------------------------------------

$myClass = new MyClass();

Trong ví dụ trên, "MyClass" là tên của lớp mà bạn đang cố khởi tạo, PHP chuyển tên này thành một chuỗi spl_autoload_register(), cho phép bạn chọn biến và sử dụng nó để "bao gồm" lớp / tệp thích hợp . Do đó, bạn không nhất thiết phải bao gồm lớp đó thông qua câu lệnh bao gồm / yêu cầu ...

Chỉ cần gọi lớp bạn muốn khởi tạo như trong ví dụ trên và vì bạn đã đăng ký một hàm (thông qua spl_autoload_register()) của chính bạn sẽ tìm ra vị trí của tất cả các lớp của bạn, PHP sẽ sử dụng hàm đó.

Lợi ích của việc sử dụng spl_autoload_register()là không giống như __autoload()bạn không cần phải thực hiện chức năng tự động tải trong mọi tệp bạn tạo. spl_autoload_register()cũng cho phép bạn đăng ký nhiều chức năng tự động tải để tăng tốc độ tự động tải và làm cho nó thậm chí còn dễ dàng hơn.

Thí dụ:

spl_autoload_register('MyAutoloader::ClassLoader');
spl_autoload_register('MyAutoloader::LibraryLoader');
spl_autoload_register('MyAutoloader::HelperLoader');
spl_autoload_register('MyAutoloader::DatabaseLoader');

class MyAutoloader
{
    public static function ClassLoader($className)
    {
         //your loading logic here
    }


    public static function LibraryLoader($className)
    {
         //your loading logic here
    }

Liên quan đến spl_autoload , hướng dẫn sử dụng nêu:

Chức năng này được dự định sẽ được sử dụng như là một triển khai mặc định cho __autoload(). Nếu không có gì khác được chỉ định và spl_autoload_register()được gọi mà không có bất kỳ tham số nào thì chức năng này sẽ được sử dụng cho bất kỳ cuộc gọi nào sau này __autoload().

Nói một cách thực tế hơn, nếu tất cả các tệp của bạn nằm trong một thư mục và ứng dụng của bạn không chỉ sử dụng các tệp .php, mà cả các tệp cấu hình tùy chỉnh với phần mở rộng .inc, thì một chiến lược bạn có thể sử dụng là thêm thư mục chứa tất cả các tệp đến PHP bao gồm đường dẫn (thông qua set_include_path()).
Và vì bạn cũng yêu cầu các tệp cấu hình của mình, bạn sẽ sử dụng spl_autoload_extensions()để liệt kê các phần mở rộng mà bạn muốn PHP tìm kiếm.

Thí dụ:

set_include_path(get_include_path().PATH_SEPARATOR.'path/to/my/directory/');
spl_autoload_extensions('.php, .inc');
spl_autoload_register();

Vì spl_autoload là cách triển khai mặc định của __autoload()phương thức ma thuật, nên PHP sẽ gọi spl_autoload khi bạn thử và khởi tạo một lớp mới.

Hi vọng điêu nay co ich...


35
Đây có thể là một trong những câu trả lời hay nhất trong lịch sử câu trả lời. Sự tôn trọng. Tôi đã có một trong những "OMG! Bây giờ tất cả đều có ý nghĩa!" Khoảnh khắc vì em, người đàn ông tốt của anh. Tôi nghĩ rằng tôi có thể chỉ cần bắt đầu một câu lạc bộ fan hâm mộ.
Chỉ đơn giản là

2
Để làm cho câu trả lời tốt nhất trong tất cả các câu trả lời ngay cả trong các vũ trụ thay thế, vui lòng thêm spl_autoload rất, ừm, "hữu ích" (?) Chuyển đổi tất cả tên tệp thành chữ thường (xem nhận xét của tôi thành @user bên dưới). Không thể sử dụng spl_autoload_register () vanilla nếu bạn thích CapitalLettersAndStuff của mình.
Chỉ đơn giản là High High

6
@Just Plain High Tôi không gặp phải vấn đề đó và tất cả các tệp trong lớp của tôi đều được gắn liền. BTW, đây là một câu trả lời tuyệt vời. Nó giúp tôi hiểu được một khái niệm đơn giản mà tôi không thể hiểu cho đến khi tôi đọc bài viết này! Dòng 85 (và đang phát triển) của tôi bao gồm tệp bao gồm tất cả các tệp lớp của tôi hiện là 7 dòng!
kyle

2
Đây thực sự là một câu trả lời tốt nhưng tôi đang thiếu một điều. Các chức năng mặc định thực tế là gì? Với các lớp tôi biết, nó sử dụng không gian tên làm đường dẫn và tên lớp làm tên tệp. Mặc dù tôi không thể tìm ra cách nó hoạt động với các chức năng.
SiXoS

2
Không phải là một trong những lợi ích to lớn khi sử dụng spl_autoload_register()(và __autoload()nói chung) rằng nó lười tải bao gồm các tệp / lớp? Điều này được ngụ ý bởi câu trả lời, nhưng không được nêu rõ ràng. Đối với tôi, đây là thông tin quan trọng sẽ là hoàn hảo để đưa vào câu trả lời của bạn! :)
rinogo

13

Kể từ PHP 5.3, bạn có thể sử dụng spl_autoload_register()với các không gian tên, điều đó có nghĩa là bạn có thể tổ chức dự án của mình và tự động tải các lớp php của bạn mà không cần bất kỳ yêu cầu hoặc bao gồm và không xác định lại __autoload()chức năng.

Để thể hiện hành vi này, chỉ cần tạo một tệp có tên là index.php:

<?php
spl_autoload_register();
var_dump(new Main\Application);

Sau đó tạo một thư mục có tên Main nằm ngay bên cạnh tệp index.php. Cuối cùng, tạo một tệp có tên Application.php nằm trong Main và dán đoạn mã sau vào đó:

<?php namespace Main;
class Application{}

9
Một lưu ý từ câu đố của tôi với tất cả những điều này: spl_autoload () - và do đó spl_autoload_register () - chuyển đổi tên tệp thành chữ thường (mặc dù báo cáo lỗi, lời cầu xin và bỏ phiếu giận dữ). Điều này có nghĩa là bạn có thể đang tìm kiếm "Main \ Application" nhưng spl_autoload đang tìm kiếm "main \ application". Nếu bạn thích lạc đà, giống như tôi, bạn sẽ phải viết chức năng của riêng mình. Có một ví dụ khởi đầu tốt đẹp ở đây: github.com/ircmaxell/PHP-CryptLib/blob/ mẹo
Just Plain High

1
Ưu điểm: spl_autoload_register () là phương thức tự động tải nhanh nhất Nhược điểm: nó sẽ chỉ hoạt động với các tệp / lớp chữ thường và cả không gian tên, mà ngày nay và tuổi tác chỉ là thời gian lớn (không có tùy chọn nào để sử dụng CamelCase, v.v.). Nhưng nếu bạn có thể sống với cấu trúc không gian tên / classname.php, đừng tìm đâu xa.
stamster

1
spl_autoload_register()thực hiện mặc định là không thể tìm thấy các lớp kế thừa. Vì vậy, bằng cách sử dụng mặc định, tệp chữ thường và thư mục phản ánh đường dẫn không gian tên, mọi thứ đều hoạt động tốt trừ khi tôi có một lớp mở rộng một lớp khác (cha mẹ). PHP sau đó đưa ra lỗi mà nó không thể tìm thấy lớp cha đó, thậm chí tất cả chúng đều nằm trong cùng một thư mục / không gian tên! Điều khó hiểu là chỉ có các lớp cấp đầu tiên được tìm thấy, vì vậy tôi đã phải đặt một lớp khác spl_autoload_register()với quy tắc hàm ẩn danh ngay sau lớp 1 theo thứ tự o bao gồm các lớp cha / thừa kế bị thiếu.
stamster

1

Đây là cách tôi sử dụng Autoload. Trong ví dụ đã cho, tôi muốn tải các lớp từ 3 thư mục khác nhau.

function namespaceAutoload($rawClass){

$class = str_replace('\\', DIRECTORY_SEPARATOR, $rawClass);

$possiblePaths[] = '..\sys\class\file.php';
$possiblePaths[] = '..\sys\class\lib\file.php';
$possiblePaths[] = '..\sys\class\class.file.inc.php';

foreach ($possiblePaths as $templatePath) {
    $path = str_replace(["\\", "file"], [DIRECTORY_SEPARATOR, $class], $templatePath);
    if (file_exists($path)) {
        require_once "$path";
        break;
    }
} spl_autoload_register("namespaceAutoload"); 

Tôi lấy ví dụ đã cho, PHP sẽ tìm không gian tên \ class trong ba thư mục này bằng ba định dạng tên tệp khác nhau này.

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.