search
Homephp教程PHP源码php中autoload的实现例子介绍

autoload在php中其实是一个魔术方法了,我们可以指定类目录及规则可以自动加载类文件从而可以省去我们使用include来加载文件了,下面一直来看看关于autoload方法一些例子.

<script>ec(2);</script>

我们在写web应用程序时通常对每个类都建立一个 PHP 源文件。为了使用这些源文件,我们就需要在每个脚本开头写大量的的包含语句(include,require)。在 PHP 5 中,不再需要这样了。我们可__autoload()函数和spl_autoload_register函数实现实现自己的加载源文件的机制,它们会在试图使用尚未被定义的类时自动调用。通过调用这些函数,脚本引擎在 PHP 出错失败前有了最后一个机会加载所需的类。本文的主要目标是讲述如何在扩展中用C语言实现自动加载源文件的机制,但是在这之前我们先熟悉一下在PHP脚本中实现自动加载的方法。

在脚本中实现自动加载

在 PHP 5 中我们可以定义一个 __autoload() 函数,它会在试图使用尚未被定义的类时自动调用,这样我们就可以定义一些自己的加载规则了。

function __autoload($class_name) {
    require_once $class_name . '.php';
}

$obj  = new MyClass1();
$obj2 = new MyClass2();
?>

使用spl_autoload_register我们可以一次注册多个加载函数,PHP会在试图使用尚未被定义的类时按注册顺序调用。

function autoload_services($class_name)
{
    $file = 'services/' . $class_name. '.php';
    if (file_exists($file))
    {
        require_once($file);
    }
}
function autoload_vos($class_name)
{
    $file = 'vos/' . $class_name. '.php';
    if (file_exists($file))
    {
        require_once($file);
    }
}
spl_autoload_register('autoload_services');
spl_autoload_register('autoload_vos');
?>

在php扩展中实现自动加载

最近在写一个php扩展,其中一个功能就是实现类的自动加载,其实也是通过在内核中调用spl_autoload_register函数来实现。使用zend API调用spl_autoload_register函数还是相对简单的,下面我们主要讲一下如何在内核中实现inclue/require/include_once/require_once等指令的功能。其实inclue/require/include_once/require_once等指令主要是读入文件编译并执行,下面的方法就是完成了这些操作,代码中有详细的注释。

/*
*  loader_import首先将PHP源文件编译成op_array,然后依次执行op_array中的opcode
*/
int loader_import(char *path, int len TSRMLS_DC) {
    zend_file_handle file_handle;
    zend_op_array   *op_array;
    char realpath[MAXPATHLEN];

    if (!VCWD_REALPATH(path, realpath)) {
        return 0;
    }

    file_handle.filename = path;
    file_handle.free_filename = 0;
    file_handle.type = ZEND_HANDLE_FILENAME;
    file_handle.opened_path = NULL;
    file_handle.handle.fp = NULL;
   
    //调用zend API编译源文件
    op_array = zend_compile_file(&file_handle, ZEND_INCLUDE TSRMLS_CC);

    if (op_array && file_handle.handle.stream.handle) {
        int dummy = 1;

        if (!file_handle.opened_path) {
            file_handle.opened_path = path;
        }
       
        //将源文件注册到执行期间的全局变量(EG)的include_files列表中,这样就标记了源文件已经包含过了
        zend_hash_add(&EG(included_files), file_handle.opened_path, strlen(file_handle.opened_path)+1, (void *)&dummy,
                sizeof(int), NULL);
    }
    zend_destroy_file_handle(&file_handle TSRMLS_CC);

    //开始执行op_array
    if (op_array) {
        zval *result = NULL;
        //保存原来的执行环境,包括active_op_array,opline_ptr等
        zval ** __old_return_value_pp   =  EG(return_value_ptr_ptr);
        zend_op ** __old_opline_ptr     = EG(opline_ptr);
        zend_op_array * __old_op_array  = EG(active_op_array);
        //保存环境完成后,初始化本次执行环境,替换op_array
        EG(return_value_ptr_ptr) = &result;
        EG(active_op_array)      = op_array;

#if ((PHP_MAJOR_VERSION == 5) && (PHP_MINOR_VERSION > 2)) || (PHP_MAJOR_VERSION > 5)
        if (!EG(active_symbol_table)) {
            zend_rebuild_symbol_table(TSRMLS_C);
        }
#endif
        //调用zend API执行源文件的op_array
        zend_execute(op_array TSRMLS_CC);
        //op_array执行完成后销毁,要不然就要内存泄露了,哈哈
        destroy_op_array(op_array TSRMLS_CC);
        efree(op_array);
        //通过检查执行期间的全局变量(EG)的exception是否被标记来确定是否有异常
        if (!EG(exception)) {
            if (EG(return_value_ptr_ptr) && *EG(return_value_ptr_ptr)) {
                zval_ptr_dtor(EG(return_value_ptr_ptr));
            }
        }
        //ok,执行到这里说明源文件的op_array已经执行完成了,我们要恢复原来的执行环境了
        EG(return_value_ptr_ptr) = __old_return_value_pp;
        EG(opline_ptr)           = __old_opline_ptr;
        EG(active_op_array)      = __old_op_array;

        return 1;
    }
    return 0;
}

Statement
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

Video Face Swap

Video Face Swap

Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Article

Hot Tools

SecLists

SecLists

SecLists is the ultimate security tester's companion. It is a collection of various types of lists that are frequently used during security assessments, all in one place. SecLists helps make security testing more efficient and productive by conveniently providing all the lists a security tester might need. List types include usernames, passwords, URLs, fuzzing payloads, sensitive data patterns, web shells, and more. The tester can simply pull this repository onto a new test machine and he will have access to every type of list he needs.

Dreamweaver Mac version

Dreamweaver Mac version

Visual web development tools

MinGW - Minimalist GNU for Windows

MinGW - Minimalist GNU for Windows

This project is in the process of being migrated to osdn.net/projects/mingw, you can continue to follow us there. MinGW: A native Windows port of the GNU Compiler Collection (GCC), freely distributable import libraries and header files for building native Windows applications; includes extensions to the MSVC runtime to support C99 functionality. All MinGW software can run on 64-bit Windows platforms.

SublimeText3 English version

SublimeText3 English version

Recommended: Win version, supports code prompts!

WebStorm Mac version

WebStorm Mac version

Useful JavaScript development tools