搜尋
首頁後端開發php教程雙引號是否過多,這就是問題所在!

最近我又聽說 PHP 人們仍然在談論單引號與雙引號,並且使用單引號只是一種微觀優化,但如果你習慣一直使用單引號,你會節省大量的 CPU循環!

「一切都已經說過了,但還沒有被所有人說出」 – Karl Valentin

正是本著這種精神,我正在寫一篇關於 Nikita Popov 12 年前已經做過的同一主題的文章(如果您正在閱讀他的文章,您可以在這裡停止閱讀)。

毛茸茸的到底是什麼?

PHP 執行字串插值,在字串中搜尋變數的使用情況,並將其替換為所使用變數的值:

$juice = "apple";
echo "They drank some $juice juice.";
// will output: They drank some apple juice.

此功能僅限於雙引號和定界符中的字串。使用單引號(或 nowdoc)將產生不同的結果:

$juice = "apple";
echo 'They drank some $juice juice.';
// will output: They drank some $juice juice.

請注意:PHP 不會搜尋該單引號字串中的變數。所以我們可以開始在任何地方使用單引號。所以人們開始建議這樣的改變..

- $juice = "apple";
+ $juice = 'apple';

.. 因為它會更快,並且每次執行該程式碼都會節省大量CPU 週期,因為PHP 不會在單引號字串中查找變數(無論如何,該範例中不存在這些變數)並且皆大歡喜,案件結案。

案件結案了嗎?

顯然,使用單引號和雙引號是有區別的,但為了理解發生了什麼,我們需要更深入地挖掘。

儘管 PHP 是一種解釋性語言,但它使用編譯步驟,其中某些部分一起運行以獲得虛擬機器實際可以執行的內容,即操作碼。那我們要如何從 PHP 原始碼取得操作碼呢?

詞法分析器

詞法分析器掃描原始程式碼檔案並將其分解為標記。可以在 token_get_all() 函數文件中找到該意義的簡單範例。一個 PHP 原始碼只是

T_OPEN_TAG (<?php )
T_ECHO (echo)
T_WHITESPACE ( )
T_CONSTANT_ENCAPSED_STRING ("")

我們可以在這個 3v4l.org 程式碼片段中看到它的實際效果並使用它。

解析器

解析器取得這些標記並從中產生抽象語法樹。當以 JSON 表示時,上述範例的 AST 表示如下所示:

{
  "data": [
    {
      "nodeType": "Stmt_Echo",
      "attributes": {
        "startLine": 1,
        "startTokenPos": 1,
        "startFilePos": 6,
        "endLine": 1,
        "endTokenPos": 4,
        "endFilePos": 13
      },
      "exprs": [
        {
          "nodeType": "Scalar_String",
          "attributes": {
            "startLine": 1,
            "startTokenPos": 3,
            "startFilePos": 11,
            "endLine": 1,
            "endTokenPos": 3,
            "endFilePos": 12,
            "kind": 2,
            "rawValue": "\"\""
          },
          "value": ""
        }
      ]
    }
  ]
}

如果你也想玩這個,看看其他程式碼的AST 是什麼樣子,我找到了Ryan Chandler 的https://phpast.com/ 和https://php-ast-viewer.com/ ,其中兩者都顯示給定PHP 程式碼片段的AST。

編譯器

編譯器採用 AST 並建立操作碼。操作碼是虛擬機器執行的內容,如果您進行了設定並啟用了它,它也會儲存在 OPcache 中(我強烈推薦)。

要查看操作碼,我們有多個選項(也許更多,但我確實知道這三個):

  1. 使用 vulcan 邏輯轉儲器擴充。它也被納入 3v4l.org
  2. 使用 phpdbg -p script.php 轉儲操作碼
  3. 或使用 OPcache 的 opcache.opt_debug_level INI 設定使其列印出操作碼
    • 最佳化前輸出操作碼為 0x10000
    • 0x20000 的值輸出最佳化後的操作碼
$ echo '<?php echo "";' > foo.php
$ php -dopcache.opt_debug_level=0x10000 foo.php
$_main:
...
0000 ECHO string("")
0001 RETURN int(1)

假設

回到使用單引號與雙引號時節省 CPU 週期的最初想法,我想我們都同意,只有當 PHP 在運行時為每個請求評估這些字串時,這才是正確的。

運行時會發生什麼?

那麼讓我們看看 PHP 為兩個不同版本建立了哪些操作碼。

雙引號:

<?php echo "apple";
0000 ECHO string("apple")
0001 RETURN int(1)

對比單引號:

<?php echo 'apple';
0000 ECHO string("apple")
0001 RETURN int(1)

嘿等等,發生了一些奇怪的事情。這看起來一模一樣!我的微優化去哪了?

好吧,也許 ECHO 操作碼處理程序的實現會解析給定的字串,儘管沒有標記或其他東西告訴它這樣做......嗯?

讓我們試試不同的方法,看看詞法分析器對這兩種情況做了什麼:

雙引號:

T_OPEN_TAG (<?php )
T_ECHO (echo)
T_WHITESPACE ( )
T_CONSTANT_ENCAPSED_STRING ("")

對比單引號:

Line 1: T_OPEN_TAG (<?php )
Line 1: T_ECHO (echo)
Line 1: T_WHITESPACE ( )
Line 1: T_CONSTANT_ENCAPSED_STRING ('')

標記仍然區分雙引號和單引號,但是檢查AST 將為我們提供兩種情況相同的結果- 唯一的區別是Scalar_String 節點屬性中的rawValue,它仍然具有單/雙引號,但是在這兩種情況下,該值都使用雙引號。

新假設

難道字串插值其實是在編譯時完成的嗎?

讓我們來看一個稍微「複雜」的例子:

<?php $juice="apple";
echo "juice: $juice";

此文件的令牌是:

T_OPEN_TAG (<?php )
T_VARIABLE ($juice)
T_CONSTANT_ENCAPSED_STRING ("apple")
T_WHITESPACE ()
T_ECHO (echo)
T_WHITESPACE ( )
T_ENCAPSED_AND_WHITESPACE (juice: )
T_VARIABLE ($juice)

Look at the last two tokens! String interpolation is handled in the lexer and as such is a compile time thing and has nothing to do with runtime.

Too double quote or not, that

For completeness, let's have a look at the opcodes generated by this (after optimisation, using 0x20000):

0000 ASSIGN CV0($juice) string("apple")
0001 T2 = FAST_CONCAT string("juice: ") CV0($juice)
0002 ECHO T2
0003 RETURN int(1)

This is different opcode than we had in our simple

Get to the point: should I concat or interpolate?

Let's have a look at these three different versions:

<?php $juice = "apple";
echo "juice: $juice $juice";
echo "juice: ", $juice, " ", $juice;
echo "juice: ".$juice." ".$juice;
  • the first version is using string interpolation
  • the second is using a comma separation (which AFAIK only works with echo and not with assigning variables or anything else)
  • and the third option uses string concatenation

The first opcode assigns the string "apple" to the variable $juice:

0000 ASSIGN CV0($juice) string("apple")

The first version (string interpolation) is using a rope as the underlying data structure, which is optimised to do as little string copies as possible.

0001 T2 = ROPE_INIT 4 string("juice: ")
0002 T2 = ROPE_ADD 1 T2 CV0($juice)
0003 T2 = ROPE_ADD 2 T2 string(" ")
0004 T1 = ROPE_END 3 T2 CV0($juice)
0005 ECHO T1

The second version is the most memory effective as it does not create an intermediate string representation. Instead it does multiple calls to ECHO which is a blocking call from an I/O perspective so depending on your use case this might be a downside.

0006 ECHO string("juice: ")
0007 ECHO CV0($juice)
0008 ECHO string(" ")
0009 ECHO CV0($juice)

The third version uses CONCAT/FAST_CONCAT to create an intermediate string representation and as such might use more memory than the rope version.

0010 T1 = CONCAT string("juice: ") CV0($juice)
0011 T2 = FAST_CONCAT T1 string(" ")
0012 T1 = CONCAT T2 CV0($juice)
0013 ECHO T1

So ... what is the right thing to do here and why is it string interpolation?

String interpolation uses either a FAST_CONCAT in the case of echo "juice: $juice"; or highly optimised ROPE_* opcodes in the case of echo "juice: $juice $juice";, but most important it communicates the intent clearly and none of this has been bottle neck in any of the PHP applications I have worked with so far, so none of this actually matters.

TLDR

String interpolation is a compile time thing. Granted, without OPcache the lexer will have to check for variables used in double quoted strings on every request, even if there aren't any, waisting CPU cycles, but honestly: The problem is not the double quoted strings, but not using OPcache!

However, there is one caveat: PHP up to 4 (and I believe even including 5.0 and maybe even 5.1, I don't know) did string interpolation at runtime, so using these versions ... hmm, I guess if anyone really still uses PHP 5, the same as above applies: The problem is not the double quoted strings, but the use of an outdated PHP version.

Final advice

Update to the latest PHP version, enable OPcache and live happily ever after!

以上是雙引號是否過多,這就是問題所在!的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
PHP類型提示如何起作用,包括標量類型,返回類型,聯合類型和無效類型?PHP類型提示如何起作用,包括標量類型,返回類型,聯合類型和無效類型?Apr 17, 2025 am 12:25 AM

PHP類型提示提升代碼質量和可讀性。 1)標量類型提示:自PHP7.0起,允許在函數參數中指定基本數據類型,如int、float等。 2)返回類型提示:確保函數返回值類型的一致性。 3)聯合類型提示:自PHP8.0起,允許在函數參數或返回值中指定多個類型。 4)可空類型提示:允許包含null值,處理可能返回空值的函數。

PHP如何處理對象克隆(克隆關鍵字)和__clone魔法方法?PHP如何處理對象克隆(克隆關鍵字)和__clone魔法方法?Apr 17, 2025 am 12:24 AM

PHP中使用clone關鍵字創建對象副本,並通過\_\_clone魔法方法定制克隆行為。 1.使用clone關鍵字進行淺拷貝,克隆對象的屬性但不克隆對象屬性內的對象。 2.通過\_\_clone方法可以深拷貝嵌套對象,避免淺拷貝問題。 3.注意避免克隆中的循環引用和性能問題,優化克隆操作以提高效率。

PHP與Python:用例和應用程序PHP與Python:用例和應用程序Apr 17, 2025 am 12:23 AM

PHP適用於Web開發和內容管理系統,Python適合數據科學、機器學習和自動化腳本。 1.PHP在構建快速、可擴展的網站和應用程序方面表現出色,常用於WordPress等CMS。 2.Python在數據科學和機器學習領域表現卓越,擁有豐富的庫如NumPy和TensorFlow。

描述不同的HTTP緩存標頭(例如,Cache-Control,ETAG,最後修飾)。描述不同的HTTP緩存標頭(例如,Cache-Control,ETAG,最後修飾)。Apr 17, 2025 am 12:22 AM

HTTP緩存頭的關鍵玩家包括Cache-Control、ETag和Last-Modified。 1.Cache-Control用於控制緩存策略,示例:Cache-Control:max-age=3600,public。 2.ETag通過唯一標識符驗證資源變化,示例:ETag:"686897696a7c876b7e"。 3.Last-Modified指示資源最後修改時間,示例:Last-Modified:Wed,21Oct201507:28:00GMT。

說明PHP中的安全密碼散列(例如,password_hash,password_verify)。為什麼不使用MD5或SHA1?說明PHP中的安全密碼散列(例如,password_hash,password_verify)。為什麼不使用MD5或SHA1?Apr 17, 2025 am 12:06 AM

在PHP中,應使用password_hash和password_verify函數實現安全的密碼哈希處理,不應使用MD5或SHA1。1)password_hash生成包含鹽值的哈希,增強安全性。 2)password_verify驗證密碼,通過比較哈希值確保安全。 3)MD5和SHA1易受攻擊且缺乏鹽值,不適合現代密碼安全。

PHP:服務器端腳本語言的簡介PHP:服務器端腳本語言的簡介Apr 16, 2025 am 12:18 AM

PHP是一種服務器端腳本語言,用於動態網頁開發和服務器端應用程序。 1.PHP是一種解釋型語言,無需編譯,適合快速開發。 2.PHP代碼嵌入HTML中,易於網頁開發。 3.PHP處理服務器端邏輯,生成HTML輸出,支持用戶交互和數據處理。 4.PHP可與數據庫交互,處理表單提交,執行服務器端任務。

PHP和網絡:探索其長期影響PHP和網絡:探索其長期影響Apr 16, 2025 am 12:17 AM

PHP在過去幾十年中塑造了網絡,並將繼續在Web開發中扮演重要角色。 1)PHP起源於1994年,因其易用性和與MySQL的無縫集成成為開發者首選。 2)其核心功能包括生成動態內容和與數據庫的集成,使得網站能夠實時更新和個性化展示。 3)PHP的廣泛應用和生態系統推動了其長期影響,但也面臨版本更新和安全性挑戰。 4)近年來的性能改進,如PHP7的發布,使其能與現代語言競爭。 5)未來,PHP需應對容器化、微服務等新挑戰,但其靈活性和活躍社區使其具備適應能力。

為什麼要使用PHP?解釋的優點和好處為什麼要使用PHP?解釋的優點和好處Apr 16, 2025 am 12:16 AM

PHP的核心優勢包括易於學習、強大的web開發支持、豐富的庫和框架、高性能和可擴展性、跨平台兼容性以及成本效益高。 1)易於學習和使用,適合初學者;2)與web服務器集成好,支持多種數據庫;3)擁有如Laravel等強大框架;4)通過優化可實現高性能;5)支持多種操作系統;6)開源,降低開發成本。

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
1 個月前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳圖形設置
1 個月前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您聽不到任何人,如何修復音頻
1 個月前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.聊天命令以及如何使用它們
1 個月前By尊渡假赌尊渡假赌尊渡假赌

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

Atom編輯器mac版下載

Atom編輯器mac版下載

最受歡迎的的開源編輯器

SAP NetWeaver Server Adapter for Eclipse

SAP NetWeaver Server Adapter for Eclipse

將Eclipse與SAP NetWeaver應用伺服器整合。

SecLists

SecLists

SecLists是最終安全測試人員的伙伴。它是一個包含各種類型清單的集合,這些清單在安全評估過程中經常使用,而且都在一個地方。 SecLists透過方便地提供安全測試人員可能需要的所有列表,幫助提高安全測試的效率和生產力。清單類型包括使用者名稱、密碼、URL、模糊測試有效載荷、敏感資料模式、Web shell等等。測試人員只需將此儲存庫拉到新的測試機上,他就可以存取所需的每種類型的清單。

VSCode Windows 64位元 下載

VSCode Windows 64位元 下載

微軟推出的免費、功能強大的一款IDE編輯器