php中autoload的實現例子介紹

來源:互聯網
上載者:User

我們在寫web應用程式時通常對每個類都建立一個 PHP 源檔案。為了使用這些源檔案,我們就需要在每個指令碼開頭寫大量的的包含語句(include,require)。在 PHP 5 中,不再需要這樣了。我們可__autoload()函數和spl_autoload_register函數實現實現自己的載入源檔案的機制,它們會在試圖使用尚未被定義的類時自動調用。通過調用這些函數,指令碼引擎在 PHP 出錯失敗前有了最後一個機會載入所需的類。本文的主要目標是講述如何在擴充中用C語言實現自動載入源檔案的機制,但是在這之前我們先熟悉一下在PHP指令碼中實現自動載入的方法。

在指令碼中實現自動載入

在 PHP 5 中我們可以定義一個 __autoload() 函數,它會在試圖使用尚未被定義的類時自動調用,這樣我們就可以定義一些自己的載入規則了。

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

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

使用spl_autoload_register我們可以一次註冊多個載入函數,PHP會在試圖使用尚未被定義的類時按註冊順序調用。

<?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;
}

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.