搜尋
首頁後端開發php教程王帥:深入PHP核心(一)-弱型變項原理探究

PHP是一門簡單而強大的語言,提供了許多Web適用的語言特性,其中就包含了變數弱型,在弱型別機制下,你能夠給一個變數賦任意型別的值。 
PHP的執行是透過Zend Engine(以下簡稱ZE),ZE是使用C編寫,在底層實現了一套弱型機制。 ZE的記憶體管理使用寫入時拷貝、引用計數等最佳化策略,減少再變量賦值時候的記憶體拷貝。

下面不光帶你探索PHP弱類型的原理,也會在寫PHP擴展角度,介紹如何操作PHP的變數。

1. PHP的變數型別

PHP的變數型別有8種:

  • 標準型別:布林boolen,整數型integer,浮點float,字元string
  • 複雜型別:陣列array,特殊類型:資源resource  
  • PHP不會嚴格檢驗變數類型,變數可以不顯示的宣告其類型,而在運作期間直接賦值。也可以將變數自由的轉換類型。如下例,沒有實作宣告的情況下,$i可以賦任意型別的值。

[php] view plaincopy

  1.  php  $i = 1;     // float $i = array(1 , 2, 3);  // array $i = new Exception('test', 123); // object $i = fopen('/tmp/aaa.txt', object $i = fopen('/tmp/aaa. 如果你對弱類型原理理解不深刻,在變數比較時候,會出現「超出預期」的驚喜。
[php] view plaincopy

 PHP 
    $str1
  1.  = null;  $str2 $str1==$str2 ? '相等' : '不相等';  $str3 = '' echo $str3== $str4 ? '相等' : '不相等';   = '0';   echo $str5==$str6 ? '相等'🎠 以上三個結果全部是相等,因為變數比較的時候,PHP內部做了變數轉換。如果希望值和類型同時判斷,請使用三個=(如,$a===0)來判斷。也許你會覺得司空見慣,也許你會覺得很神奇,那請跟我一起深入PHP內核,探索PHP變數原理。 2. 變量的存儲及標準類型介紹PHP的所有變量,都是以結構體zval來實現,在Zend/zend.h中我們能看到zval的定義:[php] view plaincopy
    1. typedef union _zvalue_value {     long lval;             double dval;               /* double v         char *val;         int len;             be set for strings */     } str;                     /* string (always has length) */     HashTable *ht;             /* an array */     zend_object_value obj;     /* stores an object store handle, and handlers */  } zvalue_value;   refcount__gc
    表示引用計數
    1valuetype
    is_ref__gc 表示是否為引用 0
    儲存變數的值  
     

    其中refcount__gc和is_ref__gc表示變數是否為一個引用。 type欄位標識變數的類型,type的值可以是:IS_NULL,IS_BOOL,IS_LONG,IS_FLOAT,IS_STRING,IS_ARRAY,IS_OBJECT,IS_RESOURCE。 PHP根據type的類型,來選擇如何儲存到zvalue_value。 
    zvalue_value能夠實現變數弱型態的核心,定義如下:

    [php] view plaincopy

    1. typedef union _zvalue_value {     long lval;             double dval;               /* doub le value                char *val;         int len;          will always be set for strings */     } str;                     /* string (always has length) */     HashTable *ht;             /* an array */     zend_object_value obj;     /* stores an object store handle, and handlers */  } zvalue_value;   布林型,zval.type
    2. 布爾型,zval.type如果是字串,zval.type=IS_STRING,會讀取zval.value.str,這是一個結構體,儲存了字串指標和長度。
    C語言中,用" plaincopy

    typedefstruct_zend_rsrc_list_entry {     void *ptr;     int 

    其中,ptr是一個指向資源的最終實現的指針,例如一個文件句柄,或者一個資料庫連接結構。 type是一個類型標記,用來區分不同的資源類型。 refcount用於資源的參考計數。

    核心中,資源類型是透過函數ZEND_FETCH_RESOURCE取得的。

    [php] view plaincopy

    1. ZEND_FETCH_RESOURCE(con, type, zval *, default, resource_name, resource_type); 按照現在我們對PHP語言的了解,變數的類型依賴zval.type欄位指示,變數的內容依照zval.type儲存到zval.value。當PHP中需要變數的時候,只需要兩個步驟:把zval.value的值或指標改變,再改變zval.type的類型。不過對於PHP的一些高階變數Array/Object/Resource,變數轉換要進行更多操作。
    變數轉換原理分為3種:

    5.1 標準型別相互轉換

    比較簡單,依照上述的步驟轉換即可。

    5.2 標準型別與資源型別轉換

    資源型別可以理解為是int,較方便轉換標準型別。轉換後資源會被close或回收。

    [php] view plaincopy

     php 

    $var
    1.  = fopen()caaa/ // 資源 # 1 $var = (int) $var; var_dump($var);  // 輸出1 ?>  5.3 305.3 類型標準與複合型態轉換型/電腦型態轉換型/電腦型標準差35.3 305.300002 型式轉換類型/電腦類型。傳回元素個數;轉換bool回傳Array中是否有元素;轉換成string回傳'Array',並拋出warning。 詳情取決於經驗,請閱讀PHP手冊: http://php.net/manual/en/language.types.type-juggling.php 5.4 複雜型別相互轉換array和object可以互轉。如果其它任何類型的值被轉換成對象,將會建立一個內建類別stdClass的實例。
    2. 在我們寫PHP擴充的時候,PHP核心提供了一組函數用於型別轉換:  


    void convert_to_long(zval* p void convert_to_long_base(zval* pzval, int base)

    void convert_to_null(zval* pzval)

    void convert_to_leanf(Fvalzpvalp(Fpvalzp

    void convert_to_object( zval* pzval)void convert_object_to_type(zval* pzval, convert_func_t converter)PHP核提供的一組蛋白質來更容易的存取valval, 內核存取zval容器的API宏存取變數Z_DVAL(zval)
    (zval).value.dval
    Z_STRVAL(zval)

    (zval).value.str.val
    ). lenZ_ARRVAL(zval)Z_TYPE(zval) LVAL_P(zval)( *zval).value.lvalZ_DVAL_P(zval)(*zval).value.dvalZ_STRLEN_P(zval_p)毫(*zval).value.obj.handlers(**zval).value.lval_pp)(**zval).value.lval_pp)Z_STRVAL_PP(zval_pp)
    (zval). value.ht
    .
    (*zval).value.str.len
    Z_OBJ_HT_P(zval_p)
    Z_LVAL_PP(zval_pp)
    (**zval ).value.dval
    (**zval).value.str.val len
    Z_ARRVAL_PP(zval_pp) (**zval). value.ht

    6. 變數的符號表與作用域

    PHP的變數符號表與zval值的映射,是透過HashTable(哈希表,又叫做散列表,下面簡稱HT),HashTable在ZE中廣泛使用,包括常數、變數、函數等語言特性都是HT來組織,在PHP的陣列類型也是透過HashTable來實現。 
    舉例:

    [php] view plaincopy

    1.  php $var = 'Hello World';符號表中,代表$var的類型和值的zval結構儲存在哈希表中。核心透過變數符號表與zval位址的哈希映射,來實現PHP變數的存取。 為什麼要提作用域呢?因為函數內部變數保護。依照作用域PHP的變數分為全域變數和局部變量,每個作用域PHP都會維護一個符號表的HashTable。當在PHP中建立一個函數或類別的時候,ZE會建立一個新的符號表,表示函數或類別中的變數是局部變量,這樣就實現了局部變數的保護--外部無法存取函數內部的變數。當建立一個PHP變數的時候,ZE會分配一個zval,並設定對應type和初始值,把這個變數加入目前作用域的符號表,這樣使用者才能使用這個變數。 
    2. 核心中使用ZEND_SET_SYMBOL來設定變數:

    [php] view plaincopy


    ZEND_SET_SYMBOL( EG(active_symbol_table), 

    "foo"
    1. , foo); [php] view plaincopy
    2. Zend/zend_globals.h  

     struct _zend_   HashTable symbol_table;//全域變項的符號表        HashTable *active_symbol_table;//局部變項的符號表        ///略為@);        //略為略);

      

    1. 在寫PHP擴充時候,可以透過EG宏來存取PHP的變數符號表。 EG(symbol_table)存取全域作用域的變數符號表,EG(active_symbol_table)存取目前作用域的變數符號表,局部變數儲存的是指針,在對HashTable進行操作的時候傳遞給對應函數。 為了更好的理解變數的雜湊表與作用域,舉個簡單的例子:
    2. [php] view plaincopy
    3.  php 
    $temp

     = 

    'global'

    ;

    $temp

     = 
    1. 'active'; } test (); var_dump($temp); ?>   建立函數外的變數$temp,就會將這個它加入全域符號表,同時在全域符號表的HashTable中建立函數外的變數$temp,會把這個它加入全域符號表,同時在全域符號表的HashTable中類型的zval,值為'global'。建立函數test內部變數$temp,會把它加入屬於函數test的符號表,分配字元型zval,值為’active' 。 7. PHP擴充中變數操作建立PHP變數我們可以在擴充中呼叫函數MAKE_STD_ZVAL(pzv)來建立一個PHP可呼叫的變量,MAKE_STD_ZVAL應用到的宏有:] view plaincopy
      1. #define     MAKE_STD_ZVAL(zv)                               ZEND_FAST_ALLOC(z, zval, ZVAL_CACHE_LIST)   ZEND) (type * ) emalloc(sizeof(type))   #define     INIT_PZVAL(z)               0;   

      MAKE_STD_ZVAL(foo)展開後得到:

      [php] view plaincopy

      1. (foo) = (zval *) emalloc(sizeof(zval));   (foo)->refcount__gc =__1;
      可以看出, MAKE_STD_ZVAL做了三件事:分配記憶體、初始化zval結構中的refcount、is_ref。 

      核心中提供一些巨集來簡化我們的操作,可以只用一步便設定好zval的類型和值。

      API Macros for Accessing zval 宏 Z_TYPE_P(pzv) = IS_BOOL; Z_BVAL_P(pzv) = b ? 1 : 0;ZVAL_TRUE(pvz) ZVAL_BOOL(pzv, 0);ZVAL_LONG(pvz, l)(l 是值)Z_TYPE_P(pzv) = IS_LONGZ_LLet z, d )ZVAL_STRINGL(pvz, stret, len,d,nid; pzv) = len; if (dup) { ZVAL_STRINGL(pzv, str,strlen(str), dup);ZVAL_RESOURCE(pvz, res)
      實作方法
      ZVAL_BOOL(pvz)
      FALSE(pvz)
      Z_TYPE_P(pzv) = IS_DOUBLE;Z_LVAL_P(pzv) = d;
          {Z_STRVAL_P(pzv) =estrndup(str, len + 1);}  }else {    pvz, str, len)
      ZVAL_RESOURCE(pvz,res)


      ZVAL_STRINGL(pzv,str,len,dup)中的dup參數

      先闡述一下ZVAL_STRINGL(pzv,str,len,dup); str和len兩個參數很好理解,因為我們知道內核中保存了字串的位址和它的長度,後面的dup的意思其實很簡單,它指明了該字串是否需要被複製。值為 1 將先申請一塊新記憶體並賦值該字串,然後把新記憶體的位址複製給pzv,為 0 時則是直接把str的位址賦值給zval。

      ZVAL_STRINGL與ZVAL_STRING的區別

      如果你想在某一位置截取該字串或已經知道了這個字串的長度,那麼可以使用宏ZVAL_STRINGL(zval, string, length, duplicate) ,它顯式的指定字串長度,而不是使用strlen()。這個宏該字串長度作為參數。但它是二進位安全的,而且速度也比ZVAL_STRING快,因為少了個strlen。 
      ZVAL_RESOURCE約等於ZVAL_LONG

      在章節4中我們說過,PHP中的資源類型的值是一個整數,所以ZVAL_RESOURCE和ZVAL_LONG的工作差不多,只不過它會把zval的類型設為 IS_RESOURCE。

      8. 總結

      PHP的弱類型是透過ZE的zval容器轉換完成,透過哈希表來儲存變數名稱和zval數據,在運作效率方面有一定犧牲。另外因為變數類型的隱性轉換,在開發過程中對變數類型檢測力度不夠,可能會導致問題出現。 

      不過PHP的弱型別、陣列、記憶體託管、擴充等語言特性,非常適合Web開發場景,開發效率很高,能夠加快產品迭代週期。在海量服務中,通常瓶頸存在於資料存取層,而不是語言本身。在實際使用PHP不僅擔任邏輯層和展現層的任務,我們甚至用PHP開發的UDPServer/TCPServer作為資料和cache的中間層。

      以上就介紹了王帥:深入PHP核心(一)-弱型變項原理探究,包含了面向的內容,希望對PHP教學有興趣的朋友有幫助。

陳述
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
解决方法:您的组织要求您更改 PIN 码解决方法:您的组织要求您更改 PIN 码Oct 04, 2023 pm 05:45 PM

“你的组织要求你更改PIN消息”将显示在登录屏幕上。当在使用基于组织的帐户设置的电脑上达到PIN过期限制时,就会发生这种情况,在该电脑上,他们可以控制个人设备。但是,如果您使用个人帐户设置了Windows,则理想情况下不应显示错误消息。虽然情况并非总是如此。大多数遇到错误的用户使用个人帐户报告。为什么我的组织要求我在Windows11上更改我的PIN?可能是您的帐户与组织相关联,您的主要方法应该是验证这一点。联系域管理员会有所帮助!此外,配置错误的本地策略设置或不正确的注册表项也可能导致错误。即

Windows 11 上调整窗口边框设置的方法:更改颜色和大小Windows 11 上调整窗口边框设置的方法:更改颜色和大小Sep 22, 2023 am 11:37 AM

Windows11将清新优雅的设计带到了最前沿;现代界面允许您个性化和更改最精细的细节,例如窗口边框。在本指南中,我们将讨论分步说明,以帮助您在Windows操作系统中创建反映您的风格的环境。如何更改窗口边框设置?按+打开“设置”应用。WindowsI转到个性化,然后单击颜色设置。颜色更改窗口边框设置窗口11“宽度=”643“高度=”500“>找到在标题栏和窗口边框上显示强调色选项,然后切换它旁边的开关。若要在“开始”菜单和任务栏上显示主题色,请打开“在开始”菜单和任务栏上显示主题

如何在 Windows 11 上更改标题栏颜色?如何在 Windows 11 上更改标题栏颜色?Sep 14, 2023 pm 03:33 PM

默认情况下,Windows11上的标题栏颜色取决于您选择的深色/浅色主题。但是,您可以将其更改为所需的任何颜色。在本指南中,我们将讨论三种方法的分步说明,以更改它并个性化您的桌面体验,使其具有视觉吸引力。是否可以更改活动和非活动窗口的标题栏颜色?是的,您可以使用“设置”应用更改活动窗口的标题栏颜色,也可以使用注册表编辑器更改非活动窗口的标题栏颜色。若要了解这些步骤,请转到下一部分。如何在Windows11中更改标题栏的颜色?1.使用“设置”应用按+打开设置窗口。WindowsI前往“个性化”,然

OOBELANGUAGE错误Windows 11 / 10修复中出现问题的问题OOBELANGUAGE错误Windows 11 / 10修复中出现问题的问题Jul 16, 2023 pm 03:29 PM

您是否在Windows安装程序页面上看到“出现问题”以及“OOBELANGUAGE”语句?Windows的安装有时会因此类错误而停止。OOBE表示开箱即用的体验。正如错误提示所表示的那样,这是与OOBE语言选择相关的问题。没有什么可担心的,你可以通过OOBE屏幕本身的漂亮注册表编辑来解决这个问题。快速修复–1.单击OOBE应用底部的“重试”按钮。这将继续进行该过程,而不会再打嗝。2.使用电源按钮强制关闭系统。系统重新启动后,OOBE应继续。3.断开系统与互联网的连接。在脱机模式下完成OOBE的所

Windows 11 上启用或禁用任务栏缩略图预览的方法Windows 11 上启用或禁用任务栏缩略图预览的方法Sep 15, 2023 pm 03:57 PM

任务栏缩略图可能很有趣,但它们也可能分散注意力或烦人。考虑到您将鼠标悬停在该区域的频率,您可能无意中关闭了重要窗口几次。另一个缺点是它使用更多的系统资源,因此,如果您一直在寻找一种提高资源效率的方法,我们将向您展示如何禁用它。不过,如果您的硬件规格可以处理它并且您喜欢预览版,则可以启用它。如何在Windows11中启用任务栏缩略图预览?1.使用“设置”应用点击键并单击设置。Windows单击系统,然后选择关于。点击高级系统设置。导航到“高级”选项卡,然后选择“性能”下的“设置”。在“视觉效果”选

Windows 11 上的显示缩放比例调整指南Windows 11 上的显示缩放比例调整指南Sep 19, 2023 pm 06:45 PM

在Windows11上的显示缩放方面,我们都有不同的偏好。有些人喜欢大图标,有些人喜欢小图标。但是,我们都同意拥有正确的缩放比例很重要。字体缩放不良或图像过度缩放可能是工作时真正的生产力杀手,因此您需要知道如何对其进行自定义以充分利用系统功能。自定义缩放的优点:对于难以阅读屏幕上的文本的人来说,这是一个有用的功能。它可以帮助您一次在屏幕上查看更多内容。您可以创建仅适用于某些监视器和应用程序的自定义扩展配置文件。可以帮助提高低端硬件的性能。它使您可以更好地控制屏幕上的内容。如何在Windows11

10种在 Windows 11 上调整亮度的方法10种在 Windows 11 上调整亮度的方法Dec 18, 2023 pm 02:21 PM

屏幕亮度是使用现代计算设备不可或缺的一部分,尤其是当您长时间注视屏幕时。它可以帮助您减轻眼睛疲劳,提高易读性,并轻松有效地查看内容。但是,根据您的设置,有时很难管理亮度,尤其是在具有新UI更改的Windows11上。如果您在调整亮度时遇到问题,以下是在Windows11上管理亮度的所有方法。如何在Windows11上更改亮度[10种方式解释]单显示器用户可以使用以下方法在Windows11上调整亮度。这包括使用单个显示器的台式机系统以及笔记本电脑。让我们开始吧。方法1:使用操作中心操作中心是访问

如何在Safari中关闭iPhone的隐私浏览身份验证?如何在Safari中关闭iPhone的隐私浏览身份验证?Nov 29, 2023 pm 11:21 PM

在iOS17中,Apple为其移动操作系统引入了几项新的隐私和安全功能,其中之一是能够要求对Safari中的隐私浏览选项卡进行二次身份验证。以下是它的工作原理以及如何将其关闭。在运行iOS17或iPadOS17的iPhone或iPad上,如果您在Safari浏览器中打开了任何“无痕浏览”标签页,然后退出会话或App,Apple的浏览器现在需要面容ID/触控ID认证或密码才能再次访问它们。换句话说,如果有人在解锁您的iPhone或iPad时拿到了它,他们仍然无法在不知道您的密码的情况下查看您的隐私

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.能量晶體解釋及其做什麼(黃色晶體)
2 週前By尊渡假赌尊渡假赌尊渡假赌
倉庫:如何復興隊友
4 週前By尊渡假赌尊渡假赌尊渡假赌
Hello Kitty Island冒險:如何獲得巨型種子
3 週前By尊渡假赌尊渡假赌尊渡假赌

熱工具

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

SublimeText3 Linux新版

SublimeText3 Linux新版

SublimeText3 Linux最新版

記事本++7.3.1

記事本++7.3.1

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

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具