php是如何找到要執行個體的對象的

來源:互聯網
上載者:User
比如我有個test對象,首先先執行個體對象,然後對象在執行個體化的後面,這個時候為什麼還會找的到對象?

$test = new Test();echo $test->run();class Test{    public function run(){        return 'run---';    }}

上面代碼是怎麼啟動並執行,php怎麼找的到test對象的?

回複內容:

比如我有個test對象,首先先執行個體對象,然後對象在執行個體化的後面,這個時候為什麼還會找的到對象?

$test = new Test();echo $test->run();class Test{    public function run(){        return 'run---';    }}

上面代碼是怎麼啟動並執行,php怎麼找的到test對象的?

你應該明白任何解譯器都不是直接解釋原始碼的(雖然你可以這麼做),而是經過"預先處理",之後,在執行這個預先處理的結果.雖然說是解譯器
比如你寫

echo "Hello world";exit;!#$%^&*()error

按照你理解的邏輯,可能php的解譯器是現在才開始掃描這個源碼,它會列印出Hello world的,但卻給你一個PHP Parse error: syntax error, 的異常.
奇怪,可見,原始碼在執行前經過了一次檢查,這些檢查包括但不限於文法檢測,php的源碼是經過處理的,你所定義的Test已經存在了.也就是說,所謂的解譯器,基本上都存在"偽編譯"的過程,所謂動態是指,你每一次請求都需要經過這樣的處理,對Java而言,這些工作需要你手動指定,編譯OK的class,繼續交給虛擬機器執行.

下面是在鳥哥的部落格裡面找到的執行流程簡化,解譯器其實是在解釋Opcode(這也是APC存在的基礎):

  1. 詞法分析, 去掉注釋, 空白, 得到TOKEN

  2. 文法分析, 在這個過程中產生Opcode array (op_array)

  3. 解釋執行, 執行op_array, 一條一條的解釋執行Opline(SWITCH, CALL, GOTO)

PHP 解譯器是個 C 程式。
它是解釋型語言,所以無需編譯,但這個編譯指的是『編譯成二進位檔案』。
但是從指令碼到結果,中間還是有一系列過程的。

語言本身只是為了更符合人的習慣,PHP 解譯器最終執行的是 opcode。

從從 php 指令碼到 opcodes 的的過程在 PHP5 中是:

Lexing:詞法掃描分析,將源檔案轉換成 token 流;
Parsing:文法分析,在此階段產生 op arrays。

PHP7 中在文法分析階段不再直接產生 op arrays,而是先產生 AST,所以過程多了一步:

Lexing:詞法掃描分析,將源檔案轉換成 token 流;
Parsing:文法分析,從 token 流產生抽象文法樹;
Compilation:從抽象文法樹產生 op arrays。

上面的 lexing,也就是詞法分析,PHP 用的是 re2c,parsing 也就是文法分析,PHP 用的是bison。
lexing 做一些符號替換,狀態記錄的東西。
parsing 會去掃描文法,然後調用相應的處理函數,比如 zend_do_begin_class_declaration 之類的函數。當然這是 PHP5,PHP7 它會先去調 zend_ast_create 之類的。

接下來 PHP5 中 parsing 調的相應的處理函數就會將語句轉換成 opcode,將變數存在記憶體中,函數名、類名存在符號表中。
PHP7 中會有 compile 相關的函數去分析抽象文法樹,然後得到和上面相同的結果。

這樣你的變數、類、函數都在記憶體中準備就緒了,你的指派陳述式、函數調用語句都已經變成了順序排列的一條一條的 opcode array了。

然後就是執行了。會有一個 excute 相關的函數來一條一條的執行 opcode,得到的就是你要的結果。

所以你的類雖然寫在下面,但是完全可以被找到的。

上面說的這些過程,對應的 PHP 解譯器中的檔案分別是:

zend_language_scanner.l
zend_language_parser.y
zend_ast.c (PHP7)
zend_compile.c
zend_excute.c

如果有 C 語言的底子,嘗試從另外一個層面去瞭解會更簡單。

php是解釋型語言, 不用像編譯型語言(c)那樣提前聲明函數定義。

運行之前電腦會把整個php代碼載入到記憶體中吧。然後再去尋找調用。。
我是才學一個月的小白。。不知道對不對

代碼會放在記憶體中的代碼區,程式啟動並執行時候調用,所以在你代碼中的順序沒有關係,但建議便於閱讀,執行個體放在前面。

別高興得太早,如果它繼承另一個類(include),就要放在下面了,php是個奇葩

我覺得大家解釋的都僅僅是原理,沒有解釋道這題的根本,這道問題的意思是問為什麼把類定義到調用類的後面也可以,按照常理來說是類定義在要調用的前面才能尋找得到。
我來解釋一下這個問題吧,首先,定義了類,不調用,是沒有意義的,要調用,就必須要執行個體化,上面提到的opcode執行機制,這個是對的,那麼我說的原因基於這個,也就是說php在執行的時候進行先行編譯,那麼編譯的時候把執行的資料放到記憶體,其存放方式和我們寫代碼的時候是不一樣的,php把每種類型的資料放到不同的位置,比如把類放到堆,也就是說,你這個類,不管定義在前面和後面,執行程式的時候,相當於是忽略你的定義的(因為在先行編譯階段被移動到了堆),那麼只有在執行到執行個體化具體的類的時候,才會去堆裡尋找有沒有定義這個類,定義了按照堆裡定義的類資料進行執行個體化,然後執行。

  • 相關文章

    聯繫我們

    該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.