PHP 快速指南



PHP 簡介

PHP 最初是一個小型開源專案,隨著越來越多的人發現它的實用性,它逐漸發展壯大。Rasmus Lerdorf 於 1994 年釋出了第一個 PHP 版本。最初,PHP 的縮寫是“Personal Home Page”,但現在代表遞迴縮寫“PHP: Hypertext Preprocessor”。

Lerdorf 從 1993 年開始開發 PHP,他編寫了幾個用 C 語言編寫的通用閘道器介面 (CGI) 程式,用於維護他的個人主頁。後來,他擴充套件了這些程式以與 Web 表單配合使用並與資料庫通訊。這個 PHP 實現被稱為“Personal Home Page/Forms Interpreter”或 PHP/FI。

如今,PHP 是世界上最流行的用於構建 Web 應用程式的伺服器端程式語言。多年來,它經歷了多次修訂和版本更新。

PHP 版本

PHP 由 Rasmus Lerdorf 於 1994 年開發,最初是一組用 C 語言編寫的簡單的 CGI 二進位制檔案。他將這套指令碼稱為“Personal Home Page Tools”。可以將其視為 PHP 1.0 版本。

  • 1996 年 4 月,Rasmus 推出了 PHP/FI。其中包括對 DBM、mSQL 和 Postgres95 資料庫、Cookie、使用者定義函式支援的內建支援。PHP/FI 被賦予了2.0 版本狀態。

  • PHP: Hypertext Preprocessor – PHP 3.0 版本是在 Zeev Suraski 和 Andi Gutmans 重寫 PHP 解析器並採用當前首字母縮寫詞時出現的。它為多個數據庫、協議和 API 提供了成熟的介面,以及面向物件程式設計支援和一致的語言語法。

  • PHP 4.0 於 2000 年 5 月釋出,由 Zend Engine 提供支援。它支援許多 Web 伺服器、HTTP 會話、輸出緩衝、安全的使用者輸入處理方法以及一些新的語言結構。

  • PHP 5.0 於 2004 年 7 月釋出。它主要由其核心 Zend Engine 2.0 驅動,具有新的物件模型和數十個其他新功能。PHP 的開發團隊包括數十名開發人員以及從事 PEAR、PECL 和文件等 PHP 相關和支援專案的人員。

  • PHP 7.0 於 2015 年 12 月釋出。最初被稱為 PHP 新一代 (phpng)。開發人員重新設計了 Zend Engine,稱為 Zend Engine 3。PHP 7 的一些重要功能包括其改進的效能、減少的記憶體使用量、返回和標量型別宣告以及匿名類。

  • PHP 8.0 於 2020 年 11 月 26 日釋出。這是一個主要版本,與之前的版本相比,有很多顯著改進。一個突出的功能是即時編譯 (JIT),它可以提供顯著的效能改進。最新版本的 PHP 是 8.2.8,於 2023 年 7 月 4 日釋出。

PHP 應用領域

PHP 是 Web 上最廣泛使用的語言之一。以下是 PHP 的一些應用領域:

  • PHP 是一種伺服器端指令碼語言,嵌入在 HTML 中。它用於管理動態內容、資料庫、會話跟蹤,甚至構建整個電子商務網站。雖然它特別適合 Web 開發,但您也可以構建桌面獨立應用程式,因為 PHP 也具有命令列介面。您可以使用 PHP-GTK 擴充套件在 PHP 中構建 GUI 應用程式。

  • PHP 廣泛用於構建 Web 應用程式,但您並不侷限於僅輸出 HTML。PHP 的輸出能力包括豐富的檔案型別,例如影像或 PDF 檔案,資料加密和傳送電子郵件。您還可以輕鬆輸出任何文字,例如 JSON 或 XML。

  • PHP 是一種跨平臺語言,能夠在所有主要的作業系統平臺上執行,並與大多數 Web 伺服器程式(如 Apache、IIS、lighttpd 和 nginx)一起執行。PHP 還支援使用 LDAP、IMAP、SNMP、NNTP、POP3、HTTP、COM 等協議的其他服務。

以下是 PHP 的一些更重要的特性:

  • PHP 執行系統函式。它可以建立、開啟、讀取、寫入和關閉檔案。

  • PHP 可以處理表單。它可以從檔案收集資料,將資料儲存到檔案,透過電子郵件傳送資料,將資料返回給使用者。

  • 您可以透過 PHP 新增、刪除、修改資料庫中的元素。

  • 訪問 Cookie 變數並設定 Cookie。

  • 使用 PHP,您可以限制使用者訪問網站的某些頁面。

  • 它可以加密資料。

PHP 提供大量可重用的類和庫,可在“PEAR”和“Composer”上獲得。“PEAR”(PHP 擴充套件和應用程式儲存庫)是可重用 PHP 庫或類的分發系統。“Composer”是 PHP 中的依賴管理工具。

PHP 安裝

您可以藉助網際網路上免費提供的任何線上 PHP 編譯器來學習 PHP 的程式設計基礎知識。這將有助於在不將其安裝到您的計算機上的情況下熟悉 PHP 的功能。之後,在您的本地機器上安裝完整的 PHP 環境。

Tutorialpoint 提供的一個線上 PHP 編譯器是“開發者程式碼練習場”。訪問 https://tutorialspoint.tw/codingground.htm,輸入 PHP 程式碼並執行。

PHP Installation

然而,要學習 PHP 的高階特性,特別是與 Web 概念相關的特性,例如伺服器變數、使用後端資料庫等,您需要在本地機器上安裝 PHP 環境。

為了開發和執行 PHP 網頁,您需要在計算機系統上安裝三個重要元件。

  • Web 伺服器 − PHP 幾乎可以與所有 Web 伺服器軟體一起工作,包括 Microsoft 的 Internet Information Server (IIS)、NGINX 或 Lighttpd 等。最常用的 Web 伺服器軟體是免費的 Apache 伺服器。在此免費下載 Apache − https://httpd.apache.org/download.cgi

  • 資料庫 − PHP 幾乎可以與所有資料庫軟體一起工作,包括 Oracle 和 Sybase,但最常用的是免費的 MySQL 資料庫。在此免費下載 MySQL − https://www.mysql.com/downloads/

  • PHP 解析器 − 為了處理 PHP 指令碼指令,必須安裝一個解析器來生成可以傳送到 Web 瀏覽器的 HTML 輸出。

雖然可以分別安裝這三個元件並正確配置安裝,但這對於初學者來說是一個稍微複雜的過程。相反,使用包含預編譯的 Apache、MySQL 和 PHP 二進位制檔案的任何一體化打包發行版比較方便。

XAMPP 安裝

有許多預編譯的軟體包,既有開源的也有專有的發行版。來自 Apache Friends 的 XAMPP (https://www.apachefriends.org/) 是最流行的 PHP 啟用 Web 伺服器軟體包之一。本教程將使用 XAMPP。

XAMPP 是一個易於安裝的 Apache 發行版,包含 Apache、MariaDB、PHP 和 Perl。首字母縮寫中的字母 X 表示它是一個跨平臺軟體,可在 Windows、Linux 和 OS X 上使用。請注意,XAMPP 包含 MariaDB,它是 MySQL 的一個分支,其功能沒有任何區別。

要下載適合您作業系統的相應安裝程式,請訪問 https://www.apachefriends.org/download.html,然後下載以下其中一個 −

在 Windows 上使用安裝程式是一個完全基於嚮導的安裝。您只需要提供管理員許可權和安裝目錄的位置(預設為“c:\xampp”)。

要在 Linux 上安裝 XAMPP,請執行以下步驟 −

步驟 1 − 更改安裝程式的許可權 −

chmod 755 xampp-linux-*-installer.run

執行安裝程式 −

sudo ./xampp-linux-*-installer.run

XAMPP 現在安裝在“/opt/lamp”目錄下。

步驟 2 − 要啟動 XAMPP,只需呼叫此命令 −

sudo /opt/lampp/lampp start

您現在應該在螢幕上看到類似以下內容 −

Starting XAMPP ...
LAMPP: Starting Apache...
LAMPP: Starting MySQL...
LAMPP started.
Ready. Apache and MySQL are running.

您還可以使用圖形工具輕鬆管理伺服器。您可以使用以下命令啟動此工具 −

cd /opt/lampp
sudo ./manager-linux.run (or manager-linux-x64.run)

步驟 3 − 要停止 XAMPP,只需呼叫此命令 −

sudo /opt/lampp/lampp stop

您現在應該在螢幕上看到類似以下內容 −

Stopping XAMPP ...
LAMPP: Stopping Apache...
LAMPP: Stopping MySQL...
LAMPP stopped.

此外,請注意,有一個圖形工具可以輕鬆啟動/停止伺服器。您可以使用以下命令啟動此工具 −

cd /opt/lampp
sudo ./manager-linux.run (or manager-linux-x64.run)

如果您使用的是 OS X,請按照以下步驟操作 −

  • 要開始安裝,請開啟 DMG 映象,然後雙擊該映象以啟動安裝過程。

  • 要啟動 XAMPP,只需開啟 XAMPP 控制面板並啟動 Apache、MySQL 和 ProFTPD。XAMPP 控制面板的名稱是“manager-osx”。

  • 要停止 XAMPP,只需開啟 XAMPP 控制面板並停止伺服器。XAMPP 控制面板的名稱是“manager-osx”。

  • XAMPP 控制面板是一個 GUI 工具,可以輕鬆啟動和停止 Apache 伺服器和 MySQL。

PHP Installation 2

啟動 Apache 模組後,按“Admin”按鈕。XAMPP 主頁顯示如下所示 −

PHP Installation 3

PHP 解析器安裝

在繼續之前,務必確保您的機器上已正確設定環境,以便使用 PHP 開發 Web 程式。

在瀏覽器的位址列中輸入以下地址。

http://127.0.0.1/info.php

如果顯示的頁面顯示與 PHP 安裝相關的資訊,則表示您已正確安裝 PHP 和 Web 伺服器。否則,您必須按照給定的步驟在計算機上安裝 PHP。

本節將指導您在以下四個平臺上安裝和配置 PHP −

Apache 配置

如果您使用 Apache 作為 Web 伺服器,則本節將指導您編輯 Apache 配置檔案。

請在此處檢視 − Apache 伺服器中的 PHP 配置

PHP.INI 檔案配置

PHP 配置檔案 php.ini 是影響 PHP 功能的最終也是最直接的方法。

請在此處檢視 − PHP.INI 檔案配置

Windows IIS 配置

要配置 Windows 計算機上的 IIS,您可以參考 IIS 參考手冊(隨 IIS 提供)。

現在,您已經在本地機器上擁有了一個完整的 PHP 開發環境。

PHP 歷史

PHP 最初是一個小型開源專案,隨著越來越多的人發現它的實用性,它逐漸發展壯大。Rasmus Lerdorf 在 1994 年釋出了第一個版本的 PHP。當時,PHP 代表 Personal Home Page(個人主頁),因為他用它來維護自己的個人主頁。後來,他添加了資料庫支援,並將其稱為“Personal Home Page/Forms Interpreter”(個人主頁/表單直譯器)或 PHP/FI,可用於構建簡單的動態 Web 應用程式。

  • Zeev Suraski 和 Andi Gutmans 在 1997 年重寫了解析器,並構成了PHP 3的基礎。該語言的名稱也更改為遞迴首字母縮寫 PHP:Hypertext Preprocessor(超文字預處理器)。他們也是 Zend Engine 的作者,Zend Engine 是 PHP 的編譯器和執行時環境。Zend Engine 驅動的PHP 4於 2000 年 5 月釋出。

  • PHP 5於 2004 年釋出,其中包含許多新特性,例如 OOP 支援、PHP 資料物件 (PDO) 和許多效能增強。

  • PHP 7是 2015 年開發的一個新的主要 PHP 版本。它包含新的語言特性,最值得注意的是,引入了函式的返回型別宣告,補充了現有的引數型別宣告,並支援引數和返回型別宣告中的標量型別(整數、浮點數、字串和布林值)。

PHP 8 的新特性

PHP 8 是最新的主要版本,於 2020 年 11 月釋出。一些新的特性和顯著變化包括

即時 (JIT) 編譯

PHP 8 的 JIT 編譯器比常見的 Web 開發用例對數學型別操作提供了顯著的效能改進。JIT 編譯器為將來將某些程式碼從 C 移動到 PHP 提供了潛力。

“match”表示式

新引入的“match”表示式比 switch 語句更簡潔。因為 match 是一個表示式,所以它的結果可以賦值給變數或從函式返回。

PHP 8 – 型別更改和新增

PHP 8 引入了聯合型別、新的靜態返回型別和新的混合型別。PHP 8 還提供了屬性(類似於其他程式語言中的“註釋”),有助於向 PHP 類新增元資料。

此外,PHP 標準庫也進行了許多更改和新增。PHP 8.2.9 是最新可用的穩定版本。

PHP 釋出歷史中的重要里程碑總結在下表中 −

版本 描述

版本 1.0
(1995 年 6 月 8 日)

正式稱為“Personal Home Page Tools (PHP Tools)”。這是第一次使用“PHP”這個名稱。

版本 2.0
(1997 年 11 月 1 日)

正式稱為“PHP/FI 2.0”。這是第一個實際上可以稱為 PHP 的版本,它是一種獨立的語言,具有許多延續至今的特性。

版本 3.0
(1998 年 6 月 6 日)

開發從一個人轉向多人。

Zeev Suraski 和 Andi Gutmans 重寫了這個版本的底層。

版本 4.0
(2000 年 5 月 22 日)

添加了更高階的兩階段解析/執行標籤解析系統,稱為 Zend 引擎。

版本 5.0
(2004 年 7 月 13 日)

Zend Engine II,具有新的物件模型。

版本 5.1
(2005 年 11 月 24 日)

在重新設計的 PHP 引擎中引入編譯器變數,從而提高了效能。

添加了 PHP 資料物件 (PDO) 作為訪問資料庫的一致介面。

版本 6.x
未釋出

已放棄的 PHP 版本,該版本計劃包含原生 Unicode 支援。

版本 7.0
(2015 年 12 月 3 日)

  • Zend Engine 3,

  • 統一變數語法,

  • 新增 Closure:call(),

  • ?? (空合併)運算子,

  • 返回型別宣告,

  • 標量型別宣告,

  • <=> “飛船” 三向比較運算子,

  • 匿名類

版本 7.3
(2018 年 12 月 6 日)

靈活的 Heredoc 和 Nowdoc 語法

版本 8.0
(2020 年 11 月 26 日)

  • 即時 (JIT) 編譯,

  • 以負索引開頭的陣列,

  • 無效的算術/按位運算子上的 TypeError,

  • 變數語法調整,

  • 屬性,

  • 命名引數,

  • Match 表示式,

  • 聯合型別、混合型別,

  • 靜態返回型別

PHP 特性

PHP(超文字預處理器)是一種開源伺服器端指令碼語言,主要用於 Web 開發。PHP 可以嵌入到 HTML 程式碼中。

PHP 主要用於伺服器端指令碼,它在 Web 伺服器上執行指令碼,然後將它們處理的 HTML 轉發到客戶端的 Web 瀏覽器。這使得程式設計師可以設計動態網頁,這些網頁可以管理會話、處理表單、與資料庫通訊以及執行線上應用程式所需的各種其他任務。

PHP 的特性

多年來,PHP 集成了許多特性。它不斷升級,增加了新特性和程式碼修訂。本章將重點介紹 PHP 的一些關鍵特性。

PHP Features

PHP 簡單易學

與 C、Java 和 Perl 相比,PHP 的語法相對簡單,開發人員很容易理解,特別是那些已經熟悉其他程式語言的開發人員。由於其豐富的預定義函式,可以快速開發 Web 應用程式。

PHP 是開源的

PHP 是一種免費且開源的語言,這意味著我們可以免費下載它,任何人都可以使用、修改和分發它。這促進了龐大而活躍的開發者社群的形成,他們透過論壇、教程和文件來支援和貢獻其發展。

PHP 具有跨平臺相容性

包括 Windows、Linux、macOS 和 UNIX 在內的眾多作業系統;以及 MongoDB、PostgreSQL、MySQL 等不同的資料庫都與 PHP 相容。

由於這種跨平臺互操作性,基於 PHP 的應用程式可以在多個環境中執行,無需任何修改。

PHP 中的伺服器端指令碼

PHP 主要用於伺服器端指令碼編寫,它在 Web 伺服器上執行指令碼,然後將其處理的 HTML 轉發到客戶端的 Web 瀏覽器。它幫助開發者處理表單提交和跨多個請求的使用者會話管理。

PHP 支援與資料庫輕鬆整合

PHP 為各種 DBMS 提供強大的資料庫互動支援。它提供了許多內建函式來實現資料庫連線。

PHP 還包含資料庫抽象層,它整合應用程式和資料庫之間的通訊。這使得開發者可以輕鬆設計資料庫驅動的 Web 應用程式。

PHP 提供廣泛的庫支援

PHP 為各種功能提供了廣泛的庫,例如影像處理、加密、PDF 生成、解析 XML 和 JSON、處理會話和 Cookie 等等。

PHP 中的安全功能

PHP 提供了大量用於資料加密的內建函式。開發者還可以利用第三方應用程式來增強安全性。

PHP 使用Sha1MD5等安全演算法來加密字串。此外,諸如filter_varstrip_tags之類的函式也有助於為使用者維護安全的環境。PHP 還支援 HTTPS 等安全通訊協議。

PHP 中高效的記憶體和會話管理

PHP 由於其高效的記憶體管理和會話管理而成為一種可靠的語言。它避免了不必要的記憶體分配。

PHP 程式碼在其自身的記憶體空間中執行,這使得它比其他指令碼語言更快,效率更高。在 PHP 中,資料庫連線也非常快速。

PHP 擁有活躍的社群和支援

由於 PHP 是一個開源平臺,它擁有一個充滿活力的開發者社群,他們積極參與其開發、分享知識、提供支援並建立第三方工具和框架。

由於這個活躍的社群支援,PHP 保持最新狀態,開發者可以輕鬆地從其他社群成員那裡尋求幫助,以防他們在編寫 PHP 程式碼時遇到任何錯誤或異常。

PHP 語法

PHP 的語法規則與 C 語言非常相似。PHP 是一種伺服器端指令碼語言。PHP 程式碼儲存為副檔名為“.php”的文字檔案。“.php”檔案本質上是一個網頁,其中包含一個或多個嵌入在 HTML 指令碼中的 PHP 程式碼塊。但是,它必須使用 HTTP 協議 URL 在瀏覽器中開啟。換句話說,如果雙擊 PHP 檔案圖示,它將在本地使用檔案協議開啟。例如,如果在 Apache 伺服器的文件根資料夾中開啟“index.php”檔案,它可能只會顯示 PHP 程式碼的文字。但是,如果啟動 Apache 伺服器並開啟 URLhttps:///index.php,它將顯示 Apache 主頁。

“.php”檔案可能包含 HTML、CSS 和 JavaScript 程式碼塊以及 PHP 程式碼。因此,PHP 解析器必須區分 PHP 程式碼和其他元素。當“.php”檔案在 Web 瀏覽器中開啟時,HTML 引擎呈現 HTML/CSS/JavaScript 部分,並在遇到 PHP 標記中包含的語句後立即退出 HTML 塊。PHP 解析器直譯器處理此塊並將響應返回到瀏覽器。

PHP Syntax

PHP 定義了兩種使用標記將 PHP 程式碼從 HTML 中分離出來的方法:標準 PHP 標記和簡短開啟(SGML 風格)標記。

標準 PHP 標記

最普遍有效的 PHP 標記樣式是:

<?php
   One or more PHP statements
?>

如果您使用此樣式,您可以確信您的標記將始終被正確解釋。

簡短開啟(SGML 風格)標記

簡短或簡短開啟標記如下所示:

<?php
	One or more PHP statements
?>

簡短標記正如預期的那樣是簡短的選擇。您必須執行以下兩件事之一才能使 PHP 識別這些標記:

  • 在構建 PHP 時選擇“--enable-short-tags”配置選項。

  • 將 php.ini 檔案中的“short_open_tag”設定設定為 on。

short_open_tag=on

必須停用此選項才能使用 PHP 解析 XML,因為 XML 標記使用相同的語法。

ASP 風格的標記的使用:

<%...%> 

HTML 指令碼標記

<script language = "PHP">...</script>

已被棄用。

從 HTML 中轉義

PHP 解析器忽略一對開閉標記之外的所有內容。因此,PHP 檔案可以包含混合內容。這允許 PHP 嵌入到 HTML 文件中:

<p>This is a HTML statement</p>
<?php echo This is a PHP statement.'; ?>
<p>This is another HTML statement.</p>

下面顯示了一個使用條件的稍微高階的轉義示例:

<?php if ($expression == true): ?>
   This HTML statement will be rendered.
<?php else: ?>
   Otherwise this HTML statement will be rendered.
<?php endif; ?>

即使這些塊在 PHP 開/閉標記之外,PHP 也會跳過條件不滿足的塊。

對於輸出大量文字,退出 PHP 解析模式通常比透過 echo 或 print 傳送所有文字更高效。

PHP 的基本語法

PHP 的基本語法與 C 和 C++ 的語法非常相似。

語句是用分號結尾的表示式

PHP 中的語句是任何後跟分號 (;) 的表示式。任何用 PHP 標記括起來的有效 PHP 語句序列都是一個有效的 PHP 程式。

這是一個典型的 PHP 語句,在本例中,它將一個字元字串賦值給名為“$greeting”的變數:

$greeting = "Welcome to PHP!";

文字編輯器中的物理行在 PHP 程式碼中沒有任何意義。一行中可能有多個以分號結尾的語句。另一方面,如果需要,PHP 語句可能會超過一行。

表示式是標記的組合

PHP 最小的構建塊是不可分割的標記,例如數字 (3.14159)、字串 ("two")、變數 ($two)、常量 (TRUE) 以及構成 PHP 本身語法的特殊單詞,例如 "if"、"else"、"while"、"for" 等等。

大括號構成程式碼塊

儘管語句不能像表示式那樣組合,但是您可以始終將語句序列放在任何語句可以出現的地方,方法是用一對大括號將它們括起來。

這裡,以下兩個語句是等效的:

if (3 == 2 + 1)
   print("Good - I haven't totally lost my mind.
"); if (3 == 2 + 1) { print("Good - I haven't totally"); print("lost my mind.
"); }

PHP 區分大小寫

PHP 是一種區分大小寫的語言。各種 PHP 識別符號(如變數、函式、類等)都區分大小寫。因此,變數“$age”與“$Age”不同。類似地,名為“myfunction()”的函式與名為“MyFunction()”的另一個函式不同。

PHP - Hello World

按照慣例,學習者在學習新語言或框架時,會將“Hello World”程式作為他們的第一個程式。目的是驗證要使用的軟體是否已正確安裝並按預期工作。要在 PHP 中執行“Hello World”程式,您應該在使用的作業系統上安裝了 Apache 伺服器以及 PHP 模組。

PHP 是一種伺服器端程式語言。PHP 程式碼必須位於 Web 伺服器的文件根目錄中。Web 伺服器文件根目錄是系統上執行的 Web 伺服器的根目錄。此根目錄下的文件可供連線到 Web 伺服器的任何系統訪問(前提是使用者具有許可權)。如果檔案不在此根目錄下,則無法透過 Web 伺服器訪問它。

在本教程中,我們使用 XAMPP 伺服器軟體來編寫 PHP 程式碼。預設的文件根目錄在 Windows 上通常是“C:\xampp\htdocs\”,在 Linux 上是“/opt/lamp/htdocs/”。但是,您可以透過修改 Apache 伺服器的配置檔案“httpd.conf”中的 DocumentRoot 設定來更改預設文件根目錄。

在 Windows 作業系統上,從 XAMPP 控制面板啟動 Apache 伺服器。

PHP Hello World

瀏覽到“htdocs”目錄。將以下指令碼儲存為其中的“hello.php”。

<?php
   echo "Hello World!";
?>

在瀏覽器中開啟一個新標籤頁,並將https:///hello.php作為 URL 輸入。您應該在瀏覽器視窗中看到“Hello World”訊息。

PHP 指令碼可能包含 HTML 和 PHP 程式碼的混合。

<!DOCTYPE html>
<html>
<body>
   <h1>My PHP Website</h1>
   <?php
      echo "Hello World!";
   ?>
</body>
</html>

“Hello World”訊息將呈現為純文字。但是,您可以將 HTML 標記放在“Hello World”字串中。瀏覽器將相應地解釋這些標記。

在下面的程式碼中,“echo”語句呈現“Hello World”,使其成為<h1>標題,文字位於頁面中心。

<?php
   echo "<h1 align='center'>Hello World!</h1>";
?>

從命令提示符執行 PHP 指令碼

您可以從命令提示符執行 PHP 指令碼。假設您的“hello.php”檔案包含以下內容。

<?php
   echo "Hello PHP!!!!!";
?>

將 PHP 可執行檔案的路徑新增到作業系統的路徑環境變數中。例如,在典型的 Windows XAMPP 安裝中,PHP 可執行檔案“php.exe”位於“c:\xampp\php”目錄中。將此目錄新增到 PATH 環境變數字串中。

現在在命令提示符下執行此指令碼:

C:\xampp\htdocs>php hello.php

您將獲得以下輸出:

Hello PHP!!!!!

PHP 註釋

任何計算機程式(例如 PHP 程式)中的註釋都是某種解釋性文字,語言編譯器/直譯器會忽略它。其目的是幫助使用者理解程式演算法中使用的邏輯。

雖然在程式碼中放置註釋不是必需的,但它是一種強烈推薦的做法。註釋也用作程式文件。當需要除錯和修改程式碼時,註釋也很有用。

PHP 中有兩種註釋格式:

  • 單行註釋

  • 多行註釋

單行註釋

它們通常用於與區域性程式碼相關的簡短解釋或說明。PHP 使用兩種表示法在程式中插入單行註釋。

使用“#”的單行註釋

PHP 程式碼中以“#”符號開頭的行被視為單行註釋。

<?php
   # Single line comment starting with # symbol
   echo 'Hello World';
?>

使用“//”的單行註釋

PHP 也支援 C 語言風格的單行註釋,使用“//”符號。以雙斜槓開頭的行被視為註釋。

<?php
   // Single line comment starting with // symbol
   echo 'Hello World';
?>

以“#”或“//”符號開頭的註釋不需要關閉。這些符號的有效性持續到物理行結束。

換句話說,即使沒有註釋結束標記,PHP 解析器也會將下一行視為 PHP 語句,而不是註釋。

多行註釋

多行註釋通常用於提供虛擬碼演算法和必要的更詳細的解釋。

多行註釋的風格與 C 語言相同。“/*”和“*/”符號之間嵌入的一行或多行被視為註釋。

PHP 中多行註釋的示例

這是一個多行註釋的示例。

<?php

   /* This is a multiline comment example
   program to add two numbers
   Variables used - $x for first number, 
   $y for second number */
   
   $x=10;
   $y=20;
   print "Total = ". $x+$y;
?>

請注意,您甚至可以將單行放在“/* .. */”符號內。但是,如果程式中存在“/*”符號,則必須具有相應的註釋結束標記“*/”。否則,將顯示如下錯誤:

PHP Parse error:  Unterminated comment starting line 3 in /home/cg/root/65ded9eeb52fc/main.php on line 3

PHP 變數

PHP 中的變數是命名的記憶體位置,用於儲存屬於某種資料型別的資料。

  • PHP 使用在變數名前新增美元符號 ($) 的約定。

  • PHP 中的變數名稱區分大小寫。

  • PHP 中的變數名遵循與其他標籤相同的規則。有效的變數名以字母或下劃線開頭,後跟任意數量的字母、數字或下劃線。

  • 根據命名約定,“$name”、“$rate_of_int”、“$Age”、“$mark1”是 PHP 中有效變數名的示例。

  • 無效變數名:“name”(沒有 $ 字首)、“$rate of int”(不允許使用空格)、“$Age#1”(無效字元 #)、“$11”(名稱不以字母開頭)。

變數使用“=”運算子賦值,變數位於左側,要計算的表示式位於右側。

無需指定變數的型別

PHP 是一種動態型別語言。無需指定變數的型別。相反,變數的型別由賦給它的值決定。變數的值是其最近一次賦值的值。

請看以下示例

<?php
   $x = 10;
   echo "Data type of x: " . gettype($x) . "\n";

   $x = 10.55;
   echo "Data type of x now: " . gettype($x) . "";
?>

它將產生以下輸出

Data type of x: integer
Data type of x now: double

變數的自動型別轉換

PHP 在必要時可以很好地自動將型別從一種轉換為另一種。在以下程式碼中,PHP 將字串變數“y”轉換為“int”以與另一個整數變數進行加法運算,並列印 30 作為結果。

請看以下示例

<?php
   $x = 10;
   $y = "20";

   echo "x + y is: ", $x+$y;
?>

它將產生以下輸出

x + y is: 30

按值賦值變數

在 PHP 中,變數總是按值賦值。如果將表示式賦給變數,則原始表示式的值將被複制到其中。如果表示式中任何變數的值在賦值後發生更改,則不會對賦值值產生任何影響。

<?php
   $x = 10;
   $y = 20;
   $z = $x+$y;
   echo "(before) z = ". $z . "\n";

   $y=5;
   echo "(after) z = ". $z . "";
?>

它將產生以下輸出

(before) z = 30
(after) z = 30

按引用方式給 PHP 變數賦值

您也可以使用按引用方式給 PHP 變數賦值。在這種情況下,新變數只是引用或成為原始變數的別名或指向原始變數。對新變數的更改會影響原始變數,反之亦然。

要按引用賦值,只需在被賦值變數(源變數)的開頭新增一個與號 (&)。

請看以下示例

<?php
   $x = 10;
   $y = &$x;
   $z = $x+$y;
   echo "x=". $x . " y=" . $y . " z = ". $z . "\n";

   $y=20;
   $z = $x+$y;
   echo "x=". $x . " y=" . $y . " z = ". $z . "";
?>

它將產生以下輸出

x=10 y=10 z = 20
x=20 y=20 z = 40

變數作用域

作用域可以定義為變數在其宣告的程式中具有的可用範圍。PHP 變數可以是四種作用域型別之一:

變數命名

變數命名的規則是:

  • 變數名必須以字母或下劃線字元開頭。

  • 變數名可以包含數字、字母、下劃線,但不能使用+、-、%、(、) 、& 等字元。

變數沒有大小限制。

PHP echo/print

在 PHP 中,echoprint 語句都用於在瀏覽器或 PHP 控制檯上呈現輸出。兩者都不是函式,而是語言結構。因此,兩者都不應使用括號。

PHP 中的“echo”語句

echo 語句使用以下語法

echo(string ...$expressions): void

echo 語句輸出一個或多個表示式,不新增額外的換行符或空格。

示例

這是一個關於 echo 語句如何在 PHP 中工作的示例:

<?php
   $name = "Rajesh";
   echo "Hello " . $name . " How are you?"
?>

它將產生以下輸出

Hello Rajesh How are you?

由於雙引號字串與 PHP 中的單引號字串類似,因此以下語句產生相同的輸出。

echo 'Hello ' . $name . ' How are you?';

示例

雙引號字串輸出變數的值。因此,以下語句在列印輸出之前插入“$name”變數的值。

<?php
   $name = "Rajesh";
   echo "Hello $name How are you?";
?>

它將產生以下輸出

Hello Rajesh How are you?

示例

但是,單引號字串將按原樣輸出“$name”。

<?php
   $name = "Rajesh";
   echo 'Hello $name How are you?';
?>

它將產生以下輸出

Hello $name How are you?

傳遞給 echo 語句的字串可以作為多個引數單獨傳遞,也可以連線在一起作為單個引數傳遞。因此,以下兩個語句都是有效的:

echo 'Hello ', 'how ', 'are ', 'you?', "\n";
echo 'Hello ' . 'how ' . 'are ' . 'you?' . "\n";

示例

請注意,如果未使用換行符,則兩個連續的 echo 語句的輸出將呈現於同一行。請看以下示例:

<?php
   echo "hello";
   echo "world";
?>

它將產生以下輸出

helloworld

PHP 中的“print”語句

print 語句類似於 echo,但它輸出一個表示式。

print(string $expression): int

與 echo 一樣,print 也是一種語言結構。其引數是一個表示式,但不放在括號中。

主要區別在於 PHP 中的 print 語句只接受一個引數,並且總是返回 1。

示例

請看以下示例

<?php
   $name = "Rajesh";

   print "Hello " . $name . " How are you?\n";
   print "Hello $name How are you?";
?>

它將產生以下輸出

Hello Rajesh How are you?
Hello Rajesh How are you?

使用 Print/Echo 輸出多行字串

echo 和 print 語句都可以輸出跨越多行的多行字串。請看以下示例:

<?php
   print "
   Multi-line
   string can be output  
   by echo as well as 
   print statement in PHP
   ";  
?>

它將產生以下輸出

Multi-line
string can be output
by echo as well as
print statement in PHP

如果我們將print替換為echo,輸出將保持不變。

PHP var_dump() 函式

PHP 中的內建函式之一是 var_dump() 函式。此函式顯示結構化資訊,例如作為此函式引數給出的一個或多個表示式的型別和值。

var_dump(mixed $value, mixed ...$values): void

此函式在輸出中返回物件的全部公共、私有和受保護屬性。關於陣列和物件的轉儲資訊正確縮排以顯示遞迴結構。

對於內建的整數、浮點數和布林變數,var_dump() 函式顯示引數變數的型別和值。

示例 1

例如,這是一個整數變數:

<?php
   $x = 10;  
   var_dump ($x);
?>

轉儲資訊如下:

int(10)

示例 2

讓我們看看它對浮點變數的行為:

<?php
   $x = 10.25;  
   var_dump ($x);
?>

var_dump() 函式返回以下輸出

float(10.25)

示例 3

如果表示式是布林值:

<?php
   $x = true;  
   var_dump ($x);
?>

它將產生以下輸出

bool(true)

示例 4

對於字串變數,var_dump() 函式還會返回字串的長度。

<?php
   $x = "Hello World"; 
   var_dump ($x);  
?>

它將產生以下輸出

string(11) "Hello World"

這裡我們可以使用`

` HTML 標籤來顯示預格式化的文字。`
`元素中的文字以等寬字型顯示,並且文字保留空格和換行符。

<?php
   echo "<pre>";
   $x = "Hello World"; 
   var_dump ($x);  
   echo "</pre>"
?>

它將產生以下輸出

string(11) "Hello World"

示例 5 - 使用 var_dump() 研究陣列結構

var_dump() 函式可用於研究陣列結構。在以下示例中,我們有一個數組,其中陣列的一個元素是另一個數組。換句話說,我們有巢狀陣列的情況。

<?php
   $x = array("Hello", false, 99.99, array(10, 20,30));
   var_dump ($x);
?>

它將產生以下輸出

array(4) {
  [0]=>
  string(5) "Hello"
  [1]=>
  bool(false)
  [2]=>
  float(99.99)
  [3]=>
  array(3) {
    [0]=>
    int(10)
    [1]=>
    int(20)
    [2]=>
    int(30)
  }
}

示例 6

由於"$x"在上一個示例中是索引陣列,因此會轉儲從“0”開始的索引及其值。如果陣列是關聯陣列,則會轉儲鍵值對資訊。

<?php
   $x = array(
      "Hello", false, 99.99, 
      array(1=>10, 2=>20,3=>30)
   );
   var_dump($x);
?>

在這裡,您將獲得以下輸出

array(4) {
  [0]=>
  string(5) "Hello"
  [1]=>
  bool(false)
  [2]=>
  float(99.99)
  [3]=>
  array(3) {
    [1]=>
    int(10)
    [2]=>
    int(20)
    [3]=>
    int(30)
  }
}

當使用 var_dump() 顯示陣列值時,無需使用結束標籤“`

`”。

示例 7

var_dump() 函式還可以顯示錶示類的物件的屬性。在以下示例中,我們聲明瞭一個具有兩個私有屬性“x”和“y”的 Point 類。類建構函式使用傳遞給它的引數初始化物件“p”。

var_dump() 函式提供有關物件屬性及其對應值的資訊。

<?php  
   class Point {
      private int $x;
      private int $y;

      public function __construct(int $x, int $y = 0) {
         $this->x = $x;
         $this->y = $y;
      }
   }

   $p = new Point(4, 5);
   var_dump($p) 
?>

它將產生以下輸出

object(Point)#1 (2) {
  ["x":"Point":private]=>
  int(4)
  ["y":"Point":private]=>
  int(5)
}

PHP 中還有一個類似的內建函式用於生成轉儲,名為get_defined_vars()

var_dump(get_defined_vars());

它會將所有已定義的變數轉儲到瀏覽器。

PHP $ 和 $$ 變數

我們知道 PHP 使用在變數名前新增“$”符號的約定。PHP 還允許透過在名稱前新增兩個美元符號($$)來宣告動態變數。變數變數(或動態變數)可以動態設定和使用。

普通變數的宣告如下:

$a = 'good';

動態變數取普通變數的值,並將其視為變數的名稱。在上面的示例中,“good”可以透過使用兩個美元符號“$$”作為變數名:

$$a = 'morning';

現在我們有兩個變數:“$a”的內容為“good”,“$$a”的內容為“morning”。因此,以下 echo 語句將產生相同的輸出:

echo "$a {$$a}";
echo "$a $good";

兩者產生相同的輸出:

good morning

示例 1

請看以下示例

<?php  
   $a = 'good';
   $$a = 'morning';

   echo "$a {$$a}\n";
   echo "$a $good";
?>

它將產生以下輸出

good morning
good morning

示例 2

讓我們看另一個例子:

<?php  
   $x = "foo";  
   $$x = "bar";  
   echo "Value of x = " .$x . "\n";  
   echo 'Value of $$x = ' . $$x . "\n";  
   echo 'Value of foo = ' . $foo;  
?>

在這裡,您將獲得以下輸出

Value of x = foo
Value of $$x = bar
Value of foo = bar

使用多個“$”符號

請注意,“$”符號的使用不限於兩個。可以新增任意數量的美元符號。

假設有一個變數“$x”,其值為“a”。接下來,我們定義 $$x='as',那麼“$$x”和“$a”將具有相同的值。同樣,語句 $$$x='and' 有效地聲明瞭一個“$as”變數,其值為'and'。

示例

這是一個完整的示例,它顯示了多個“$”符號的使用。

<?php  
   $php = "a";
   $lang = "php";
   $World = "lang";
   $Hello = "World";
   $a = "Hello";
   echo '$a= ' . $a;
   echo "\n";
   echo '$$a= ' . $$a;
   echo "\n";
   echo '$$$a= ' . $$$a;
   echo "\n";
   echo '$$$$a= ' . $$$$a;
   echo "\n";
   echo '$$$$$a= ' . $$$$$a;
?>

執行此程式碼時,將產生以下輸出

$a= Hello
$$a= World
$$$a= lang
$$$$a= php
$$$$$a= a

將動態變數與陣列一起使用

將動態變數與陣列一起使用可能會導致某些模稜兩可的情況。對於陣列“a”,如果您編寫 $$a[1],則解析器需要知道您是指“$a[1]”作為變數,還是想要“$$a”作為變數,然後從該變數獲取[1]索引。

為了解決這種歧義,對於第一種情況,使用${$a[1]};對於第二種情況,使用${$a}[1]。

示例

請看以下示例:

<?php  
   $vars = array("hw", "os", "lang");
   $var_hw="Intel";
   $var_lang="PHP";
   $var_os="Linux";

   foreach ($vars as $var)
      echo ${"var_$var"} . "\n";

   print "$var_hw\n$var_os\n$var_lang";
?>

它將產生以下輸出

Intel
Linux
PHP
Intel
Linux
PHP

需要注意的是,此技術不能與 PHP 的超全域性陣列(PHP 中的幾個預定義變數是“超全域性”變數,這意味著它們在整個指令碼的所有作用域中都可用)一起在函式或類方法中使用。“$this”是 PHP 中的一個特殊變數,不能動態引用。

PHP 常量

PHP 中的常量是簡單值的名稱或識別符號。常量的值在 PHP 指令碼執行期間不能更改。

  • 預設情況下,PHP 常量區分大小寫。

  • 按照約定,常量識別符號始終為大寫。

  • 常量名以字母或下劃線開頭,後跟任意數量的字母、數字或下劃線。

  • 無需在常量前寫美元符號 ($) ,但是必須在變數前使用美元符號。

PHP 中有效和無效常量名的示例

以下是一些 PHP 中有效和無效常量名的示例:

// Valid constant names
define("ONE",     "first thing");
define("TWO2",    "second thing");
define("THREE_3", "third thing");
define("__THREE__", "third value");

// Invalid constant names
define("2TWO",    "second thing");

PHP 中常量和變數的區別

  • 常量不能透過簡單的賦值來定義;它們只能使用 define() 函式來定義。

  • 常量可以在任何地方定義和訪問,而無需考慮變數作用域規則。

  • 一旦設定了常量,就不能重新定義或取消定義它們。

定義命名常量

PHP 庫中的 define() 函式用於在執行時定義命名常量。

define(string $const_name, mixed $value, bool $case = false): bool

引數

  • const_name - 常量的名稱。

  • value - 常量的值。它可以是標量值(int、float、string、bool 或 null),也可以接受陣列值。

  • case - 如果設定為 true,則常量將被定義為不區分大小寫。預設行為區分大小寫,即 CONSTANT 和 Constant 代表不同的值。

define() 函式在成功時返回“true”,失敗時返回“false”。

示例 1

以下示例演示了 define() 函式的工作方式:

<?php  
   define("CONSTANT", "Hello world.");

   echo CONSTANT; 
   // echo Constant; 
?>

第一個 echo 語句輸出 CONSTANT 的值。你將得到以下輸出

Hello world.

但是,當你取消第二個 echo 語句的註釋時,它將顯示以下錯誤:

Fatal error: Uncaught Error: Undefined constant "Constant" in hello.php: on line 5

如果將 case 引數設定為 False,PHP 不會區分大小寫常量。

示例 2

你也可以使用陣列作為常量的值。來看下面的例子:

<?php  
   define(
      $name="LANGS", 
      $value=array('PHP', 'Java', 'Python')
   );
   var_dump(LANGS);
?>

它將產生以下輸出

array(3) {
  [0]=>
  string(3) "PHP"
  [1]=>
  string(4) "Java"
  [2]=>
  string(6) "Python"
}

使用 constant() 函式

echo 語句輸出已定義常量的值。你也可以使用 constant() 函式。它返回按名稱指示的常量的值。

constant(string $name): mixed

如果你需要檢索常量的值,但不知道它的名稱,則 constant() 函式很有用。例如,它儲存在變數中或由函式返回。

<?php
   define("MINSIZE", 50);

   echo MINSIZE;
   echo PHP_EOL;
   echo constant("MINSIZE");	// same thing as the previous line
?>

它將產生以下輸出

50
50

使用 defined() 函式

PHP 庫提供了一個 defined() 函式,用於檢查是否存在給定的命名常量。來看下面的例子:

<?php
   define('MAX', 100);

   if (defined('MAX')) {
      echo MAX;
   }
?>

它將產生以下輸出

100

PHP 還具有一個名為“get_defined_constants()”的函式,它返回所有已定義常量及其值的關聯陣列。

PHP 魔術常量

PHP 中的魔術常量是預定義的常量。它們可用於執行它們的任何指令碼,並且它們的值取決於使用它們的位置。所有這些“魔術”常量都在編譯時解析,這與在執行時解析的常規常量不同。

PHP 中有九個魔術常量。這些特殊常量不區分大小寫。

__LINE__

它返回檔案的當前行號。以下示例顯示瞭如何使用此魔術常量。

<?php
   $x="Hello World";
   echo "$x. The current Line number is " . __LINE__ . ".";
?>

它將產生以下輸出

Hello World. The current Line number is 5.

__FILE__

此魔術常量返回檔案的完整路徑和檔名。如果在 include 內部使用,則返回包含檔案的名稱。來看下面的示例

<?php
   $x="Hello World";
   echo "$x. Current PHP script name is " . __FILE__ . ".";
?>

它將產生以下輸出

Hello World. Current PHP script name is C:\xampp\htdocs\hello.php.

__DIR__

此魔術常量返回檔案的目錄。如果在 include 內部使用,則返回包含檔案的目錄。這等效於“dirname(__FILE__)”。此目錄名稱不包含尾部斜槓,除非它是根目錄。請參見以下示例

<?php
   $x="Hello World";
   echo "$x. Directory of the Current PHP script name is " . __DIR__ . ".";
?>

它將在瀏覽器上顯示以下輸出

Hello World. Directory of the Current PHP script name is C:\xampp\htdocs.

__FUNCTION__

此魔術常量返回使用該常量的函式名,或者對於匿名函式返回 {closure}。以下示例顯示了它的工作原理:

<?php
   function hello(){    
      $x="Hello World";  
      echo "$x. The function name is ". __FUNCTION__ . "";   
   } 
   hello();   
?>

它將產生以下輸出

Hello World. The function name is hello

如果此魔術常量在函式外部使用,則將輸出為空。

__CLASS__

此常量返回類的名稱。類名包含其宣告的名稱空間。請參見以下示例

<?php
   class myclass {    
      public function __construct() {    
         echo "Inside the constructor of ". __CLASS__ . PHP_EOL;    
      }    
      function getClassName(){                      
         echo "from an instance method of " . __CLASS__ . "";   
      }    
   }    
   $obj = new myclass;    
   $obj->getClassName();    
?>

它將產生以下輸出

Inside the constructor of myclass
from an instance method of myclass

__METHOD__

__METHOD__ 常量返回類方法名。以下示例顯示了它的工作原理:

<?php
   class myclass {    
      public function __construct() {    
         echo "Calling " . __METHOD__ . " of " . __CLASS__ ."<br>";
      }    
      function mymethod(){                      
         echo "Calling " . __METHOD__ . " of " . __CLASS__ ."";
      }    
   }    
   $obj = new myclass;    
   $obj->mymethod();
?>

它將產生以下輸出

Calling myclass::__construct of myclass
Calling myclass::mymethod of myclass

__TRAIT__

它返回 trait 名稱。trait 名稱包含其宣告的名稱空間。在 PHP 中,trait 是程式碼重用的機制。trait 類似於類,但僅用於以細粒度和一致的方式分組功能。無法單獨例項化 trait。

來看下面的示例

<?php
   trait mytrait {
      public function hello() {
         echo "Hello World from " . __TRAIT__ ."";
      }
   }
   class myclass {
      use mytrait;
   }
   $obj = new myclass();
   $obj->hello();
?>

它將產生以下輸出

Hello World from mytrait

__NAMESPACE__

此常量返回當前名稱空間的名稱。在 PHP 中,名稱空間允許我們在不同的上下文中使用相同名稱的類/函式/常量,而不會產生任何衝突,從而封裝這些項。名稱空間是根據類/函式的相關性對它們進行邏輯分組。

以下示例顯示瞭如何使用此魔術常量:

<?php
   namespace myspace;
   class myclass {    
      public function __construct() {    
         echo "Name of the class: " . __CLASS__ . " in " . __NAMESPACE__ . ""; 
      }     
   }    
   $class_name = __NAMESPACE__ . '\myclass';    
   $a = new $class_name;   
?>

它將產生以下輸出

Name of the class: myspace\myclass in myspace

ClassName::class

與其他魔術常量不同,此魔術常量不以雙下劃線(__)開頭和結尾。它返回完全限定的類名。

以下示例顯示瞭如何使用此魔術常量:

<?php
   namespace myspace;
   class myclass {    
      public function __construct() {    
         echo "Name of the class: " . myclass::class ;
      }     
   }
   use myspace;   
   $a = new myclass; 
?>

它將產生以下輸出

Name of the class: myspace\myclass

PHP – 資料型別

術語“資料型別”指的是將資料分類到不同的類別中。PHP 總共有八種資料型別,我們用它們來構建我們的變數:

  • 整數 - 沒有小數點的整數,例如 4195。

  • 雙精度浮點數 - 浮點數,例如 3.14159 或 49.1。

  • 布林值 - 只有兩個可能的值,真或假。

  • NULL - 只具有一個值的特殊型別:NULL。

  • 字串 - 字元序列,例如 'PHP supports string operations.'。

  • 陣列 - 其他值的命名和索引集合。

  • 物件 - 程式設計師定義類的例項,可以打包其他型別的變數和特定於類的函式。

  • 資源 - 保持對 PHP 外部資源(例如資料庫連線)的引用的特殊變數。

前五個是簡單型別,接下來的兩個(陣列和物件)是複合型別。複合型別可以打包任意型別和任意數量的其他值,而簡單型別則不能。

在本章中,讓我們詳細討論這些 PHP 的內建資料型別。

PHP 中的整數資料型別

沒有小數點的整數(例如 4195)在 PHP 中屬於int 型別。整數資料型別是最簡單的型別。它們對應於簡單的整數,包括正數和負數。

  • int 是集合 Z = {..., -2, -1, 0, 1, 2, ...} 中的一個數。

  • int 可以用十進位制(基數 10)、十六進位制(基數 16)、八進位制(基數 8)或二進位制(基數 2)表示法表示。

要使用八進位制表示法,數字前面要加上“0o”或“0O”。要使用十六進位制表示法,數字前面要加上“0x”。要使用二進位制表示法,數字前面要加上“0b”。

下面是一些示例

  • 十進位制整數 - 201, 4195, -15

  • 八進位制整數 - 0010, 0O12, -0O21

  • 十六進位制整數 - 0x10, -0x100

  • 二進位制整數 - 0b10101, -0b100

整數可以賦值給變數,也可以用於表示式,如下所示:

$int_var = 12345;
$another_int = -12345 + 12345;

PHP 中的雙精度浮點數資料型別

雙精度浮點數變量表示浮點數(也稱為“浮點數”、“雙精度浮點數”或“實數”),它們是帶有小數部分的數。小數部分位於整數部分之後,由小數點符號 (.) 分隔。

注意 - 雙精度浮點數變數可以是正數、負數或零。

$var1 = 1.55
$var2 =-123.0

科學浮點記數法

PHP 還允許使用科學記數法來表示小數點後有更多位數的浮點數。“E”或“e”符號用於分隔整數和小數部分。

− 1.2e3, 2.33e-4, 7E-10, 1.0E5 

預設情況下,雙精度浮點數以所需的最小小數位數列印。來看下面的示例

<?php
   $many = 2.2888800;
   $many_2 = 2.2111200;
   $few = $many + $many_2;

   print("$many + $many_2 = $few");
?>

它產生以下輸出

2.28888 + 2.21112 = 4.5

PHP 中的布林資料型別

bool 型別只有兩個值;它可以是真或假。bool 型別用於表達真值。

$bool1 = true;
$bool2 = false;

你也可以使用整數“1”和“0”來表示真和假布林值:

$bool3 = 1; 
$bool4 = 0;

通常,返回 bool 值的運算子的結果將傳遞給控制結構,例如if、whiledo-while。例如,

if (TRUE)
   print("This will always print.");

else
   print("This will never print.");

將其他資料型別解釋為布林值

以下是一組規則,你可以使用它們將其他資料型別解釋為布林值:

  • 如果該值為數字,則僅當該值等於零時才為假,否則該值為真。

  • 如果該值為字串,則如果字串為空(沒有字元)或為字串“0”,則為假,否則為真。

  • NULL 型別的值始終為假。

  • 如果該值為陣列,則如果它不包含其他值,則為假;否則為真。對於物件,包含值意味著具有已賦值的成員變數。

  • 有效的資源為真(儘管某些在成功時返回資源的函式在不成功時將返回 FALSE)。

注意 - 不要使用雙精度浮點數作為布林值。

以下每個變數在其用作布林上下文時都具有嵌入在其名稱中的真值。

$true_num = 3 + 0.14159;
$true_str = "Tried and true"
$true_array[49] = "An array element";
$false_array = array();
$false_null = NULL;
$false_num = 999 - 999;
$false_str = "";

PHP 中的字串資料型別

字串是字元序列,例如 'PHP supports string operations.'。

在 PHP 中,字元與位元組相同。這意味著 PHP 只支援 256 個字元集,因此不提供原生 Unicode 支援。

PHP 支援單引號和雙引號字串的形成。以下兩種表示在 PHP 中都是有效的:

$string_1 = "This is a string in double quotes";
$string_2 = 'This is a somewhat longer, singly quoted string';

以下是一些更多字串型別的示例:

$string_39 = "This string has thirty-nine characters";
$string_0 = "";		// a string with zero characters

單引號字串幾乎按字面意思處理,而雙引號字串則用其值替換變數,並對某些字元序列進行特殊解釋。

<?php
   $variable = "name";
   $literally = 'My $variable will not print!';

   print($literally);
   print "\n";

   $literally = "My $variable will print!";
   print($literally);
?>

執行此程式碼時,將產生以下輸出

My $variable will not print!
My name will print

字串長度沒有人工限制。在可用記憶體的範圍內,你應該能夠建立任意長的字串。

由雙引號分隔的字串(如“this”)將透過 PHP 以以下兩種方式預處理:

  • 以反斜槓 (\) 開頭的某些字元序列將被替換為特殊字元。

  • 變數名(以$開頭)將被其值的字串表示形式替換。

轉義序列替換為:

  • \n 將被換行符替換

  • \r 將被回車符替換

  • \t 將被製表符替換

  • \$ 將被美元符號本身 ($) 替換

  • \" 將被單個雙引號 (") 替換

  • \\ 將被單個反斜槓 (\) 替換

PHP 還具有HeredocNowdoc 字串資料型別的表示形式。

字串資料型別的 Heredoc 表示形式

你可以使用 heredoc 將多行賦給單個字串變數:

<?php
   $channel =<<<_XML_

   <channel>
      <title>What's For Dinner</title>
      <link>http://menu.example.com/ </link>
      <description>Choose what to eat tonight.</description>
   </channel>
   _XML_;

   echo <<< END
      This uses the "here document" syntax to output multiple lines with 
	  variable interpolation. Note that the here document terminator must
	  appear on a line with just a semicolon. no extra whitespace!
   END;

   print $channel;
?>

執行此程式碼時,它將產生以下輸出:

This uses the "here document" syntax to output
multiple lines with variable interpolation. Note
that the here document terminator must appear on a
line with just a semicolon. no extra whitespace!

<channel>
   <title>What's For Dinner</title>
   <link>http://menu.example.com/ </link>
   <description>Choose what to eat tonight.</description>
</channel>

字串資料型別的 Nowdoc 表示形式

Heredoc 識別符號的所有規則也適用於 nowdoc 識別符號。nowdoc 的指定方式與heredoc 相同,但在 nowdoc 內沒有解析。你可以使用 nowdoc 結構嵌入大型文字塊,而無需使用任何跳脫字元。

nowdoc 使用與 heredoc 相同的 <<< 序列標識,但識別符號用單引號括起來,例如 <<<'EOT'。Nowdoc 應用於單引號字串的方式與 heredoc 應用於雙引號字串的方式相同。

請看以下示例:

<?php
   echo <<<'IDENTIFIER'
   As the cat cleared its throat with a refined "Meow",
   the squirrel chirped excitedly about its latest
   discovery of a hidden stash of peanut treasure!
   IDENTIFIER;
?>

執行程式碼並檢查其輸出:

As the cat cleared its throat with a refined "Meow",
the squirrel chirped excitedly about its latest
discovery of a hidden stash of peanut treasure!

PHP 中的 Null 資料型別

在 PHP 中,null 表示只具有一個值:NULL 的特殊型別。未定義和 unset() 變數將解析為值“null”。

程式設計師通常使用PHP中的Null資料型別來初始化變數或指示值缺失。

要為變數賦予NULL值,只需這樣賦值:

$my_var = NULL;

特殊常量NULL按照慣例大寫,但實際上它**不區分大小寫**;你也可以這樣寫:

$my_var = null;

已賦值為NULL的變數具有以下屬性:

  • 在布林上下文中計算結果為FALSE。

  • 使用IsSet()函式測試時返回FALSE。

**注意** - PHP中變數的資料型別是在執行時根據賦值給它們的值確定的。

PHP中的陣列資料型別

PHP中的陣列是有序對映,一個鍵與一個或多個值關聯。PHP陣列使用array()函式定義,或者使用簡寫法,其中資料放在方括號中。

讓我們看看以下**關聯陣列**的示例:

使用array()函式

$arr = array(
   "foo" => "bar",
   "bar" => "foo",
);

使用簡寫法

$arr = [
   "foo" => "bar",
   "bar" => "foo",
];

PHP中的陣列也可以使用“鍵值對”語法定義。這被稱為**索引陣列**。

$arr = array("foo", "bar", "hello", "world");

在**多維陣列**中,主陣列中的每個元素也可以是一個數組。並且,子陣列中的每個元素可以是一個數組,以此類推。多維陣列中的值使用多個索引訪問。

**注意** - 在PHP中,複合資料型別用於儲存資料集合,包括陣列和物件。

PHP中的物件資料型別

物件型別是程式設計師定義類的例項,它可以打包其他型別的值和特定於類的函式。

要建立一個新物件,請使用**new語句**來例項化一個類:

class foo {
   function bar() {
      echo "Hello World."; 
   }
}
$obj = new foo;
$obj->bar();

PHP中的資源資料型別

資源是持有對PHP外部資源(例如檔案流或資料庫連線)的引用的特殊變數。

這是一個**檔案資源**的示例:

$fp = fopen("foo.txt", "w");

屬於上述任何型別的資料都儲存在變數中。但是,由於PHP是一種動態型別語言,因此無需指定變數的型別,因為這將在執行時確定。

示例:gettype()函式

gettype()函式有助於找出儲存在變數中的資料型別:

<?php
   $x = 10;
   echo gettype($x) . "\n";

   $y = 10.55;
   echo gettype($y) . "\n";

   $z = [1,2,3,4,5];
   echo gettype($z);
?>

執行此程式碼時,將產生以下輸出

integer
double
array

PHP 型別轉換

術語“型別轉換”指的是將一種型別的資料轉換為另一種型別。由於PHP是一種弱型別語言,因此解析器在執行某些操作時會將某些資料型別強制轉換為其他型別。例如,如果字串包含數字,則如果它是加法運算中涉及的運算元之一,則將其轉換為整數。

隱式型別轉換

這是一個強制或隱式型別轉換的示例:

<?php
   $a = 10;
   $b = '20';
   $c = $a+$b;
   echo "c = " . $c;
?>

在這種情況下,$b是一個字串變數,轉換為整數以啟用加法。它將產生以下**輸出**:

c = 30

讓我們再舉一個例子。在這裡,整數變數$a被轉換為字串,以便與字串變數連線。

<?php
   $a = 10;
   $b = '20';
   $c = $a.$b;
   echo "c = " . $c;
?>

它將產生以下輸出

c = 1020

除了這種強制型別轉換之外,還有其他方法可以顯式地將一種型別的資料轉換為另一種型別。您可以為此目的使用PHP的型別轉換運算子或型別轉換函式。

型別轉換運算子

要將一種型別的表示式轉換為另一種型別,需要在表示式之前將後者的資料型別放在括號中。

$var = (type)expr;

PHP中的一些型別轉換運算子是:

  • (int) 或 (integer) 轉換為整數

  • (bool) 或 (boolean) 轉換為布林值

  • (float) 或 (double) 或 (real) 轉換為浮點數

  • (string) 轉換為字串

  • (array) 轉換為陣列

  • (object) 轉換為物件

轉換為整數

您可以輕鬆地將浮點值轉換為整數。讓我們看看下面的**示例**:

<?php
   $a = 9.99;
   $b = (int)$a;
   var_dump($b);
?>

它將產生以下輸出

int(9)

請注意,浮點值不會四捨五入到最接近的整數;而是隻返回整數部分。

字串到整數轉換

(int)運算子也把字串轉換為整數。如果字串只包含數字,則轉換很簡單。

<?php
   $a = "99";
   $b = (int)$a;
   var_dump($b);
?>

在這裡,您將獲得以下輸出

int(99)

即使字串包含浮點數,(int)運算子也只返回整數部分。

現在讓我們來看另一個例子來理解一個特殊情況。**如果字串是字母數字的,則使用(int)進行轉換的方式不同**。

  • 如果字串以數字開頭,後跟非數字字元,則只考慮初始數字。

  • 如果字串以非數字字元開頭,而數字在中間,則轉換運算子返回“0”。

來看下面的示例

<?php
   $a = "10 Rs.";
   $b = (int)$a;
   var_dump($b);

   $a = "$100";
   $b = (int)$a;
   var_dump($b);
?>

它將產生以下輸出

int(10)
int(0)

轉換為浮點型別

您可以使用(float)或(double)轉換運算子將變數或表示式顯式轉換為浮點數。

<?php
   $a = 100;
   $b = (double)$a;
   var_dump($b);
?>

它將產生以下輸出

float(100)

包含任何有效數字表示的字串都可以使用轉換運算子轉換為浮點型別。

<?php
   $a = "100";
   $b = (double)$a;
   var_dump($b);

   $a = "9.99";
   $b = (float)$a;
   var_dump($b);
?>

在這裡,您將獲得以下輸出

float(100)
float(9.99)

即使字串包含浮點數的科學計數法,它也會轉換為浮點數。讓我們看看下面的例子:

<?php
   $a = "1.23E01";
   $b = (double)$a;
   var_dump($b);
   $a = "5.5E-5";
   $b = (float)$a;
   var_dump($b);
?>

它將產生以下輸出

float(12.3)
float(5.5E-5)

浮點數後面的所有非數字字元都將被忽略。類似地,如果字串以任何非數字字元開頭,則字串將轉換為“0”。請參見以下**示例**:

<?php
   $a = "295.95 only";
   $b = (double)$a;
   var_dump($b);

   $a = "$2.50";
   $b = (float)$a;
   var_dump($b);
?>

它將產生以下輸出

float(295.95)
float(0)

轉換為字串型別

透過使用轉換運算子,任何計算結果為浮點數或整數的表示式都可以轉換為字串型別。下面給出一些例子:

<?php
   $a = 100;
   $b = (string)$a;
   var_dump($b);

   $x = 55.50;
   $y = (string)$x;
   var_dump($y);
?>

您將獲得以下**輸出**:

string(3) "100"
string(4) "55.5"

轉換為布林型別

任何非零數字(整數或浮點數)都將使用(bool)運算子轉換為true。計算結果為“0”的表示式返回false。字串總是轉換為true。

來看下面的示例

<?php
   $a = 100;
   $b = (bool)$a;

   $x = 0;
   $y = (bool)$x;

   $m = "Hello";
   $n = (bool)$m;

   var_dump($b);
   var_dump($y);
   var_dump($n);
?>

它將產生以下輸出

bool(true)
bool(false)
bool(true)

型別轉換函式

PHP包含以下用於執行型別轉換的內建函式:

  • intval()

  • floatval()

  • strval()

讓我們詳細討論這些內建函式。

intval()函式

此函式獲取變數的整數值。

intval(mixed $value, int $base = 10): int

**$base**引數預設為10,這意味著該值將轉換為十進位制數。

  • 如果值是浮點數,則intval()函式返回一個整數,丟棄小數部分。

  • 數字的字串表示返回相應的整數,如果存在小數部分,則丟棄小數部分。

  • 如果該值是帶有有效八進位制數的字串,並且基數為8,則intval()函式返回相應的八進位制數。

**當基數為“0”時**,值的轉換將基於字元字首進行。

  • 如果值以0X或0x開頭,則返回十六進位制數。

  • 如果值以0B或0b開頭,則返回二進位制數。

  • 如果值以0開頭,則函式返回八進位制數。

對於true布林值,intval()函式返回1;對於false布林值,返回0。

示例

以下示例顯示了intval()函式的工作方式:

<?php
   echo intval(42). PHP_EOL;                     
   echo intval(4.2). PHP_EOL;                    
   echo intval('42') . PHP_EOL;                   

   echo intval(042) . PHP_EOL;         # 0ctal number 
   echo intval('042', 0) . PHP_EOL;    # 0ctal number
   echo intval('42', 8) . PHP_EOL;     # octal  

   echo intval(0x1A) . PHP_EOL;        # Hexadecimal              
   echo intval('0x1A', 16) . PHP_EOL;  # Hexadecimal           
   echo intval('0x1A', 0) . PHP_EOL;   # Hexadecimal         

   echo intval(false) . PHP_EOL;                  
   echo intval(true) . PHP_EOL; 
?>

它將產生以下輸出

42
4
42
34
34
34
26
26
26
0
1

floatval()函式

floatval()函式獲取表示式的浮點值。

floatval(mixed $value): float

該值可以是任何標量變數。包含非數字字元的字串返回“0”。包含數字表示或以數字表示開頭的子字串的字串返回相應的數字。以下**示例**顯示了floatval()函式的工作方式:

<?php
   echo floatval(42). PHP_EOL;                     
   echo floatval(4.2). PHP_EOL;                    
   echo floatval('42') . PHP_EOL;                   

   echo floatval('99.90 Rs') . PHP_EOL;      
   echo floatval('$100.50') . PHP_EOL;      
   echo floatval('ABC123!@#') . PHP_EOL; 

   echo (true) . PHP_EOL; ;
   echo (false) . PHP_EOL; 
?>

它將產生以下輸出

42
4.2
42
99.9
0
0
1

**doubleval()**函式是floatval()函式的別名,因此返回類似的結果。

strval()函式

strval()函式獲取變數的字串值。此函式不對返回的值進行任何格式化。

strval(mixed $value): string

要轉換為字串的值可以是任何標量型別、null或實現__toString()方法的物件。讓我們看看下面的**示例**:

<?php
   echo strval(42). PHP_EOL;                     
   echo strval(4.2). PHP_EOL;                    
   echo strval(4.2E5) . PHP_EOL;                   

   echo strval(NULL) . PHP_EOL;      

   echo (true) . PHP_EOL; 
   echo (false) . PHP_EOL; 
?>

它將產生以下輸出

42
4.2
420000

1

以下**示例**定義了一個實現**__toString()方法**的類。

<?php
   class myclass {
      public function __toString() {
         return __CLASS__;
      }
   }
   echo strval(new myclass);
?>

在這裡,您將獲得以下輸出

myclass

PHP 型別強制轉換

PHP被稱為動態型別語言。PHP中變數的型別會動態變化。此功能在PHP中稱為“型別轉換”。

在C、C++和Java中,您需要在後續程式碼中使用變數之前宣告變數及其型別。變數只能取與宣告型別匹配的值。

PHP既不需要也不支援變數的顯式型別宣告。因此,PHP變數的型別由賦給它的值決定,而不是相反。此外,當變數被賦予不同型別的值時,它的型別也會改變。

示例 1

看看PHP中以下變數賦值。

<?php
   $var = "Hello";
   echo "The variable \$var is of " . gettype($var) . " type" .PHP_EOL;

   $var = 10;
   echo "The variable \$var is of " . gettype($var) . " type" .PHP_EOL;

   $var = true;
   echo "The variable \$var is of " . gettype($var) . " type" .PHP_EOL;

   $var = [1,2,3,4];
   echo "The variable \$var is of " . gettype($var) . " type" .PHP_EOL;
?>

它將產生以下輸出

The variable $var is of string type
The variable $var is of integer type
The variable $var is of boolean type
The variable $var is of array type

您可以看到“$var”的型別根據賦給它的值動態變化。PHP的這個特性叫做“型別轉換”。

示例 2

型別轉換也發生在表示式計算過程中。在這個例子中,包含數字的字串變數會自動轉換為整數,以計算加法表示式。

<?php
   $var1=100;
   $var2="100";
   $var3=$var1+$var2;
   var_dump($var3);
?>

這是它的**輸出**:

int(200)

示例 3

如果字串以數字開頭,則在執行計算時,將忽略任何尾隨的非數字字元。但是,PHP解析器會發出如下所示的通知:

<?php
   $var1=100;
   $var2="100 days";
   $var3=$var1+$var2;
   var_dump($var3);
?>

您將獲得以下**輸出**:

int(200)

PHP Warning:  A non-numeric value encountered in /home/cg/root/53040/main.php on line 4

型別轉換與型別轉換

請注意,PHP中的“型別轉換”與“型別轉換”略有不同。

  • 在型別轉換中,PHP會在必要時自動將型別從一種轉換為另一種。例如,如果將整數值賦給變數,則它將成為整數。

  • 另一方面,當用戶顯式定義他們想要轉換到的資料型別時,就會發生型別轉換。

示例

型別轉換強制變數用作某種型別。以下指令碼顯示了不同型別轉換運算子的示例:

<?php
   $var1=100;
   $var2=(boolean)$var1;
   $var3=(string)$var1;
   $var4=(array)$var1;
   $var5=(object)$var1;
   var_dump($var2, $var3, $var4, $var5);
?>

它將產生以下輸出

bool(true)
string(3) "100"
array(1) {
  [0]=>
  int(100)
}
object(stdClass)#1 (1) {
  ["scalar"]=>
  int(100)
}

示例

也可以透過將變數包含在雙引號字串中來將其轉換為字串:

<?php
   $var1=100.50;
   $var2=(string)$var1;
   $var3="$var1";
   var_dump($var2, $var3);
?>

在這裡,您將獲得以下輸出

string(5) "100.5"
string(5) "100.5"

PHP 字串

字串是一系列字元,例如“PHP支援字串操作”。PHP中的字串是位元組陣列和表示緩衝區長度的整數。在PHP中,字元與位元組相同。這意味著PHP只支援256個字元集,因此不提供原生Unicode支援。

PHP支援單引號和雙引號字串的形成。'這是一個簡單的字串'和"這是一個簡單的字串"這兩種表示方式都是有效的。PHP還具有字串資料型別的Here文件和Nowdoc表示。

單引號字串

用單引號(字元')括起來的一系列字元是字串。

$str = 'this is a simple string';

示例

如果要包含文字單引號,請用反斜槓(\)轉義它。

<?php
   $str = 'This is a \'simple\' string';
   echo $str;
?>

它將為您提供以下**輸出**:

This is a 'simple' string  

示例

要指定文字反斜槓,請將其加倍(\\)。

<?php
   $str = 'The command C:\\*.* will delete all files.';
   echo $str;
?>

這是它的**輸出**:

The command C:\*.* will delete all files.

示例

諸如“\r”或“\n”之類的轉義序列將被逐字對待,並且不會解釋它們的特殊含義。如果變量出現在單引號字串中,它們也不會被展開。

<?php
   $str = 'This will not expand: \n a newline';
   echo $str . PHP_EOL;
   $x=100;
   $str = 'Value of x = $x';
   echo $str;
?>

它將產生以下輸出

This will not expand: \n a newline
Value of x = $x

雙引號字串

用雙引號(" ")括起來的一系列字元是另一種字串表示。

$str = "this is a simple string";

單引號字串和雙引號字串是等效的,只是它們對轉義序列的處理方式不同。PHP將解釋某些用於特殊字元的轉義序列。例如,“\r”和“\n”。

序列 含義
\n 換行符(LF或ASCII中的0x0A(10))
\r 回車符(CR或ASCII中的0x0D(13))
\t 水平製表符(HT或ASCII中的0x09(9))
\v 垂直製表符(VT或ASCII中的0x0B(11))
\e 轉義符(ESC或ASCII中的0x1B(27))
\f 換頁符(FF或ASCII中的0x0C(12))
\\ 反斜槓
\$ 美元符號
\" 雙引號

如何在PHP中轉義八進位制和十六進位制字元?

PHP支援將八進位制數和十六進位制數轉義為其ASCII字元。例如,P的ASCII字元在十進位制中為80。十進位制80轉換為八進位制為120。類似地,十進位制80轉換為十六進位制為50。

要轉義八進位制字元,在其前面加上“\”;要轉義十六進位制字元,在其前面加上“\x”。

<?php
   $str = "\120\110\120";
   echo "PHP with Octal: ". $str;
   echo PHP_EOL;

   $str = "\x50\x48\x50";
   echo "PHP with Hexadecimal: ". $str;
?>

檢查輸出 -

PHP with Octal: PHP
PHP with Hexadecimal: PHP

與單引號字串一樣,轉義任何其他字元都將導致反斜槓也被打印出來。雙引號字串最重要的特性是變數名將被展開。

示例

PHP 中的雙引號字串會展開變數名(PHP 變數以 $ 符號開頭)。要在 PHP 字串中實際表示“$”符號,請使用反斜槓“\”對其進行轉義。

<?php
   $price = 200;
   echo "Price = \$ $price";
?>

您將獲得以下**輸出**:

Price = $ 200

字串連線運算子

要將兩個字串變數連線在一起,PHP 使用點 (.) 運算子 -

<?php
   $string1="Hello World";
   $string2="1234";

   echo $string1 . " " . $string2;
?>

在這裡,您將獲得以下輸出

Hello World 1234

在上面的例子中,我們使用了兩次連線運算子。這是因為我們必須插入第三個字串。在兩個字串變數之間,我們添加了一個包含單個字元(一個空格)的字串,以分隔這兩個變數。

PHP 的標準庫包含許多用於字串處理的函式。你可以在 PHP 的官方文件中找到它們(https://php.net.tw/manual/en/ref.strings.php)。

strlen() 函式

strlen() 函式用於查詢字串的長度。

示例

讓我們找到字串“Hello world!”的長度 -

<?php
   echo strlen("Hello world!");
?>

它將產生以下輸出

12

字串的長度經常用於迴圈或其他函式中,當知道字串何時結束很重要時(例如,在迴圈中,我們希望在字串的最後一個字元之後停止迴圈)。

strpos() 函式

strpos() 函式用於在一個字串中搜索字串或字元。

  • 如果在字串中找到匹配項,此函式將返回第一個匹配項的位置。

  • 如果找不到匹配項,它將返回 FALSE。

示例

讓我們看看是否可以在我們的字串中找到字串“world” -

<?php
   echo strpos("Hello world!","world");
?>

它將產生以下輸出

6

如你所見,字串“world”在我們字串中的位置是“6”。之所以是“6”而不是“7”,是因為字串中的第一個位置是“0”而不是“1”。

PHP 布林值

在 PHP 中,“bool”是內建標量資料型別之一。它用於表示真值,可以是 True 或 False。布林文字使用 PHP 常量 True 或 False。這些常量不區分大小寫,例如 true、TRUE 或 True 是同義詞。

你可以按如下方式宣告 bool 型別的變數 -

$a = true;

示例

邏輯運算子(<、>、==、!= 等)返回布林值。

<?php
   $gender="Male";
   var_dump ($gender=="Male");
?>

它將產生以下輸出

bool(true)

控制語句中的布林值

布林值用於構建控制語句,例如if、while、forforeach。這些語句的行為取決於布林運算子返回的真/假值。

以下條件語句使用if關鍵字前面括號中表達式的布林值 -

$mark=60;

if ($mark>50)
   echo "pass";
else
   echo "fail";

將值轉換為布林值

使用 (bool) 型別轉換運算子將值轉換為 bool。當值在邏輯上下文中使用時,它將自動解釋為 bool 型別的值。

非零數字被認為是 true,只有 0(+0.0 或 -0.0)是 false。非空字串表示 true,空字串 "" 等效於 false。類似地,空陣列返回 false。

示例

看一下下面的例子 -

<?php
   $a = 10;
   echo "$a: ";
   var_dump((bool)$a);

   $a = 0;
   echo "$a: ";
   var_dump((bool)$a);

   $a = "Hello";
   echo "$a: ";
   var_dump((bool)$a);

   $a = "";
   echo "$a: ";
   var_dump((bool)$a);

   $a = array();
   echo "$a: ";
   var_dump((bool)$a);
?>

它將產生以下輸出

10: bool(true)
0: bool(false)
Hello: bool(true)
: bool(false)
Array: bool(false)

整數是 PHP 中的內建標量型別之一。字面值中沒有小數點的整數在 PHP 中屬於“int”型別。整數可以用十進位制(基數 10)、十六進位制(基數 16)、八進位制(基數 8)或二進位制(基數 2)表示法表示。

要使用八進位制表示法,數字前要加“0o”或“0O”(PHP 8.1.0 及更早版本)。從 PHP 8.1.0 開始,以“0”為字首且沒有小數點的數字是八進位制數。

要使用十六進位制表示法,請在數字前加“0x”。要使用二進位制表示法,請在數字前加“0b”。

示例

請看以下示例:

<?php
   $a = 1234; 
   echo "1234 is an Integer in decimal notation: $a\n";

   $b = 0123; 
   echo "0o123 is an integer in Octal notation: $b\n";

   $c = 0x1A; 
   echo "0xaA is an integer in Hexadecimal notation: $c\n";

   $d = 0b1111;
   echo "0b1111 is an integer in binary notation: $d\n";
?>

它將產生以下輸出

1234 is an Integer in decimal notation: 1234
0o123 is an integer in Octal notation: 83
0xaA is an integer in Hexadecimal notation: 26
0b1111 is an integer in binary notation: 15

從 PHP 7.4.0 開始,整數字面值可以使用下劃線 (_) 作為數字之間的分隔符,以提高字面值的易讀性。這些下劃線將被 PHP 的掃描器刪除。

示例

請看以下示例:

<?php
   $a = 1_234_567; 
   echo "1_234_567 is an Integer with _ as separator: $a\n";
?>

它將產生以下輸出

1_234_567 is an Integer with _ as separator: 1234567

PHP 不支援無符號 intint 的大小取決於平臺。在 32 位系統上,最大值約為 20 億。64 位平臺的最大值通常約為 9E18。

可以使用常量 PHP_INT_SIZE確定int的大小,使用常量 PHP_INT_MAX確定最大值,使用常量 PHP_INT_MIN確定最小值。

如果整數恰好超過int型別的範圍,或者任何運算結果都超過int型別的範圍,它將被解釋為浮點數。

示例

請看以下示例:

<?php
   $x = 1000000;
   $y =  50000000000000 * $x;
   var_dump($y); 
?>

它將產生以下輸出

float(5.0E+19)

PHP 沒有整數除法的運算子。因此,整數和浮點數之間的除法運算始終產生浮點數。要獲得整數除法,可以使用內建函式intval()

示例

請看以下示例:

<?php
   $x = 10;
   $y = 3.5;
   $z = $x/$y;
   var_dump ($z);
   $z = intdiv($x, $y);
   var_dump ($z);
?>

它將產生以下輸出

float(2.857142857142857)
int(3)

PHP 整數

整數是 PHP 中的內建標量型別之一。字面值中沒有小數點的整數在 PHP 中屬於“int”型別。整數可以用十進位制(基數 10)、十六進位制(基數 16)、八進位制(基數 8)或二進位制(基數 2)表示法表示。

要使用八進位制表示法,數字前要加“0o”或“0O”(PHP 8.1.0 及更早版本)。從 PHP 8.1.0 開始,以“0”為字首且沒有小數點的數字是八進位制數。

要使用十六進位制表示法,請在數字前加“0x”。要使用二進位制表示法,請在數字前加“0b”。

示例

看一下下面的例子 -

<?php
   $a = 1234; 
   echo "1234 is an Integer in decimal notation: $a\n";

   $b = 0123; 
   echo "0o123 is an integer in Octal notation: $b\n";

   $c = 0x1A; 
   echo "0xaA is an integer in Hexadecimal notation: $c\n";

   $d = 0b1111;
   echo "0b1111 is an integer in binary notation: $d";
?>

它將產生以下輸出

1234 is an Integer in decimal notation: 1234
0o123 is an integer in Octal notation: 83
0xaA is an integer in Hexadecimal notation: 26
0b1111 is an integer in binary notation: 15

從 PHP 7.4.0 開始,整數字面值可以使用下劃線 (_) 作為數字之間的分隔符,以提高字面值的易讀性。這些下劃線將被 PHP 的掃描器刪除。

示例

看一下下面的例子 -

<?php
   $a = 1_234_567; 
   echo "1_234_567 is an Integer with _ as separator: $a";
?>

它將產生以下輸出

1_234_567 is an Integer with _ as separator: 1234567

PHP 不支援無符號 intint 的大小取決於平臺。在 32 位系統上,最大值約為 20 億。64 位平臺的最大值通常約為 9E18。

可以使用常量 PHP_INT_SIZE確定int的大小,使用常量 PHP_INT_MAX確定最大值,使用常量 PHP_INT_MIN確定最小值。

如果整數恰好超過int型別的範圍,或者任何運算結果都超過int型別的範圍,它將被解釋為浮點數。

示例

看一下下面的例子 -

<?php
   $x = 1000000;
   $y =  50000000000000 * $x;
   var_dump($y); 
?>

它將產生以下輸出

float(5.0E+19)

PHP 沒有整數除法的運算子。因此,整數和浮點數之間的除法運算始終產生浮點數。要獲得整數除法,可以使用內建函式intval()

示例

看一下下面的例子 -

<?php
   $x = 10;
   $y = 3.5;
   $z = $x/$y;
   var_dump ($z);
   $z = intdiv($x, $y);
   var_dump ($z);
?>

它將產生以下輸出

float(2.857142857142857)
int(3)

PHP 檔案與I/O

本章將解釋以下與檔案相關的函式 -

  • 開啟檔案
  • 讀取檔案
  • 寫入檔案
  • 關閉檔案

開啟和關閉檔案

PHP 的fopen()函式用於開啟檔案。它需要兩個引數,首先是檔名,然後是操作模式。

檔案模式可以指定為表中的六個選項之一。

序號 模式和用途
1

r

只讀方式開啟檔案。

將檔案指標置於檔案開頭。

2

r+

以讀寫方式開啟檔案。

將檔案指標置於檔案開頭。

3

w

只寫方式開啟檔案。

將檔案指標置於檔案開頭。

並將檔案截斷為零長度。如果檔案不存在,

則嘗試建立檔案。

4

w+

只讀寫方式開啟檔案。

將檔案指標置於檔案開頭。

並將檔案截斷為零長度。如果檔案不存在,

則嘗試建立檔案。

5

a

只寫方式開啟檔案。

將檔案指標置於檔案末尾。

如果檔案不存在,則嘗試建立檔案。

6

a+

只讀寫方式開啟檔案。

將檔案指標置於檔案末尾。

如果檔案不存在,則嘗試建立檔案。

如果嘗試開啟檔案失敗,則fopen返回false值,否則返回檔案指標,該指標用於進一步讀取或寫入該檔案。

對開啟的檔案進行更改後,務必使用fclose()函式關閉它。fclose()函式需要一個檔案指標作為引數,然後在關閉成功時返回true,失敗時返回false

讀取檔案

使用fopen()函式開啟檔案後,可以使用名為fread()的函式讀取它。此函式需要兩個引數。這些引數必須是檔案指標和以位元組表示的檔案長度。

可以使用filesize()函式查詢檔案長度,該函式以檔名作為引數,並返回以位元組表示的檔案大小。

因此,以下是使用 PHP 讀取檔案所需的步驟。

  • 使用fopen()函式開啟檔案。

  • 使用filesize()函式獲取檔案長度。

  • 使用fread()函式讀取檔案內容。

  • 使用fclose()函式關閉檔案。

示例

以下示例將文字檔案的內容分配給一個變數,然後在網頁上顯示這些內容。

<html>
<head>
   <title>Reading a file using PHP</title>
</head>
<body>
   <?php
      $filename = "tmp.txt";
      $file = fopen( $filename, "r" );

      if( $file == false ) {
         echo ( "Error in opening file" );
         exit();
      }

      $filesize = filesize( $filename );
      $filetext = fread( $file, $filesize );
      fclose( $file );

      echo ( "File size : $filesize bytes" );
      echo ( "<pre>$filetext</pre>" );
   ?>
</body>
</html>

它將產生以下結果 -

Reading File

寫入檔案

可以使用 PHP 的fwrite()函式寫入新檔案或將文字追加到現有檔案。此函式需要兩個引數,指定一個檔案指標和要寫入的資料字串。可以選擇包含第三個整數引數來指定要寫入資料的長度。如果包含第三個引數,則寫入將在達到指定的長度後停止。

示例

以下示例建立一個新的文字檔案,然後在其中寫入一個簡短的文字標題。關閉此檔案後,使用file_exist()函式確認其存在,該函式以檔名作為引數

<?php
   $filename = "/home/user/guest/newfile.txt";
   $file = fopen( $filename, "w" );
   
   if( $file == false ) {
      echo ( "Error in opening new file" );
      exit();
   }
   fwrite( $file, "This is  a simple test\n" );
   fclose( $file );
?>
<html>
<head>
   <title>Writing a file using PHP</title>
</head>
<body>
   <?php
      $filename = "newfile.txt";
      $file = fopen( $filename, "r" );

      if( $file == false ) {
         echo ( "Error in opening file" );
         exit();
      }

      $filesize = filesize( $filename );
      $filetext = fread( $file, $filesize );

      fclose( $file );

      echo ( "File size : $filesize bytes" );
      echo ( "$filetext" );
      echo("file name: $filename");
   ?>
</body>
</html>

它將產生以下結果 -

Writing File

我們在PHP 檔案系統函式章節中介紹了所有與檔案輸入輸出相關的函式。

PHP 數學函式

為了啟用數學運算,PHP 具有數學(算術)運算子和許多數學函式。本章將透過示例解釋以下數學函式。

PHP abs() 函式

abs() 函式是 PHP 直譯器中的內建函式。此函式接受任何數字作為引數,並返回一個正值,忽略其符號。任何數字的絕對值始終為正。

abs( mixed $num)

PHP abs() 函式返回num的絕對值。如果 num 的資料型別是浮點數,則其返回型別也將是浮點數。對於整數引數,返回型別為整數。

示例

看一下下面的例子 -

<?php
   $num=-9.99;
   echo "negative float number: " . $num . "\n";
   echo "absolute value : " . abs($num) . "\n"; 

   $num=25.55;
   echo "positive float number: " . $num . "\n";
   echo "absolute value : " . abs($num). "\n";

   $num=-45;
   echo "negative integer number: " . $num . "\n";
   echo "absolute value : " . abs($num) . "\n"; 

   $num=25;
   echo "positive integer number: " . $num . "\n";
   echo "absolute value : " . abs($num);
?>

它將產生以下輸出

negative float number: -9.99
absolute value : 9.99
positive float number: 25.55
absolute value : 25.55
negative integer number: -45
absolute value : 45
positive integer number: 25
absolute value : 25

PHP ceil() 函式

ceil() 函式是 PHP 直譯器中的內建函式。此函式接受任何浮點數作為引數,並將其向上舍入到下一個最高的整數。此函式始終返回一個浮點數,因為浮點數的範圍大於整數的範圍。

ceil ( float $num ) : float

PHP ceil() 函式返回大於或等於給定引數的最小整數。

示例 1

以下程式碼將 5.78 舍入到其下一個最高的整數 6

<?php
   $arg=5.78; 
   $val=ceil($arg);
   echo "ceil(" . $arg .  ") = " . $val;
?>

它將產生以下輸出

ceil(5.78) = 6

示例 2

以下示例顯示如何找到 15.05 的下一個最高整數。

<?php
   $arg=15.05; 
   $val=ceil($arg);
   echo "ceil(" . $arg .  ") = " . $val;
?>

它將產生以下輸出

ceil(15.05) = 16

示例 3

對於負數,它將舍入到 0。

<?php
   $arg=-3.95; 
   $val=ceil($arg);
   echo "ceil(" . $arg .  ") = " . $val;
?>

它將產生以下輸出

ceil(-3.95) = -3

PHP exp() 函式

exp()函式計算 e 的指數,即尤拉數。PHP 有一個預定義的常量 M_E,它表示尤拉數,等於 2.7182818284590452354。因此,exp(x) 返回 2.7182818284590452354x

此函式始終返回浮點數。

exp ( float $arg ) : float

PHP exp() 函式返回尤拉數 e 提升到給定的arg。請注意,e是自然對數的底數。exp() 函式是自然對數的逆函式。

示例 1

PHP 中的預定義常量之一是M_LN2,它代表 loge2,等於 0.69314718055994530942。因此,此值的 exp() 將返回 2。

<?php
   echo "exp(" . M_LN2 . ") = " . exp(M_LN2);
?>

它將產生以下輸出

exp(0.69314718055995) = 2

示例 2

M_LN10 是另一個預定義常量,代表 loge10。此程式計算 exp(M_LN10) 並返回 10。

<?php
   echo "exp(" . M_LN10 . ") = " . exp(M_LN10);
?>

它將產生以下輸出

exp(2.302585092994) = 10

PHP floor() 函式

floor() 函式是 PHP 直譯器中的另一個內建函式。此函式接受任何浮點數作為引數,並將其向下舍入到下一個最低的整數。此函式始終返回一個浮點數,因為浮點數的範圍大於整數的範圍。

floor ( float $num ) : float

PHP floor() 函式返回小於或等於給定引數的最大整數。

示例 1

以下示例顯示如何將 15.05 舍入到其下一個最高的整數 15

<?php
   $arg=15.05; 
   $val=floor($arg);
   echo "floor(" . $arg .  ") = " . $val;
?>

它將產生以下輸出

floor(15.05) = 15

示例 2

以下示例顯示如何找到 5.78 的下一個最低整數。

<?php
   $arg=5.78; 
   $val=floor($arg);
   echo "floor(" . $arg .  ") = " . $val;
?>

它將產生以下輸出

floor(5.78) = 5

示例 3

負數將舍入遠離 0。

<?php
   $arg=-3.95; 
   $val=floor($arg);
   echo "floor(" . $arg .  ") = " . $val;
?>

它將產生以下輸出

floor(-3.95) = -4

PHP intdiv() 函式

intdiv() 函式返回兩個整數引數的整數商。如果 x/y 的結果是“i”作為除法和“r”作為餘數,則 -

x = y*i+r

在這種情況下,intdiv(x,y) 返回“i”

intdiv ( int $x , int $y ) : int

“x”引數構成除法表示式的分子部分,“y”引數構成除法表示式的分母部分。

PHP intdiv() 函式返回“x”除以“y”的整數商。如果兩個引數都是正數或兩個引數都是負數,則返回值為正。

示例 1

下面的例子顯示,如果分子小於分母,則 intdiv() 函式返回 0。

<?php
   $x=10;
   $y=3; 
   $r=intdiv($x, $y);
   echo "intdiv(" . $x . "," . $y . ") = " . $r . "\n";
   $r=intdiv($y, $x);
   echo "intdiv(" . $y . "," . $x . ") = " . $r;
?>

它將產生以下輸出

intdiv(10,3) = 3
intdiv(3,10) = 0

示例 2

在下面的例子中,intdiv() 函式返回一個負整數,因為分子或分母是負數。

<?php
   $x=10;
   $y=3; 
   $r=intdiv($x, $y);
   echo "intdiv(" . $x . "," . $y . ") = " . $r . "\n";

   $x=10;
   $y=-3; 
   $r=intdiv($x, $y);
   echo "intdiv(" . $x . "," . $y . ") = " . $r . "\n";

   $x=-10;
   $y=3; 
   $r=intdiv($x, $y);
   echo "intdiv(" . $x . "," . $y . ") = " . $r . "\n";

   $x=-10;
   $y=-3; 
   $r=intdiv($x, $y);
   echo "intdiv(" . $x . "," . $y . ") = " . $r ;
?>

它將產生以下輸出

intdiv(10,3) = 3
intdiv(10,-3) = -3
intdiv(-10,3) = -3
intdiv(-10,-3) = 3

示例 3

在下面的例子中,分母為 0。這將導致 DivisionByZeroError 異常。

<?php
   $x=10;
   $y=0; 
   $r=intdiv($x, $y);
   echo "intdiv(" . $x . "," . $y . ") = " . $r . "\n";
?>

它將產生以下輸出

PHP Fatal error:  Uncaught DivisionByZeroError: Division by zero

示例 4

兩個引數中的小數部分將被忽略。PHP intdiv() 函式只應用於整數部分。

<?php
   $x=2.90;
   $y=1.90; 
   $r=intdiv($x, $y);
   echo "intdiv(" . $x . "," . $y . ") = " . $r . "";
?>

它將產生以下輸出

intdiv(2.9,1.9) = 2

PHP log10() 函式

log10() 函式計算一個數的以 10 為底的對數。以 10 為底的對數也稱為常用對數常用演算法。log10(x) 函式計算 log10x。它與自然對數的關係如下所示:

log10x=logex/loge10 ; So that
log10100=loge100/loge10 = 2

在 PHP 中,log10log10() 函式表示

log10 ( float $arg ) : float

PHP log10() 函式返回arg 的以 10 為底的對數。

示例 1

以下程式碼計算 100 的以 10 為底的對數

<?php
   $arg=100;
   echo "log10(" . $arg. ")=" . log10($arg) . "";
?>

它將產生以下輸出

log10(100)=2

示例 2

以下程式碼計算尤拉數M_E 的以 10 為底的對數。結果等於預定義常量M_LOG10E

<?php
   $arg=M_E;
   echo "log10(" . $arg. ")=" . log10($arg) . "\n";
   echo "predefined constant M_LOG10E=" . M_LOG10E;
?>

它將產生以下輸出

log10(2.718281828459)=0.43429448190325
predefined constant M_LOG10E=0.43429448190325

示例 3

以下程式碼計算 log100 並返回 -∞。

<?php
   $arg=0;
   echo "log10(" . $arg. ")=" . log10($arg) . "";
?>

它將產生以下輸出

log10(0)=-INF

示例 4

類似地,sqrt(-1) 返回 NAN。因此,它的 log10() 也返回 NAN。

<?php
   $arg=sqrt(-1);
   echo "log10(" . $arg. ")=" . log10($arg) . "";
?>

它將產生以下輸出

log10(NAN)=NAN

PHP max() 函式

max() 函式返回陣列中的最大元素,或者兩個或多個逗號分隔的引數中的最大值。

max ( array $values ) : mixed

或者:

max ( mixed $value1 [, mixed $... ] ) : mixed
  • 如果只有一個引數,則它應該是一個值陣列,這些值可以是相同或不同型別的。

  • 如果給出兩個或多個引數,則它們應該是任何可比較的相同或不同型別的值。

PHP max() 函式返回陣列引數或值序列中的最大值。標準比較運算子適用。如果多個不同型別的數值評估結果相等(例如 0 和 'PHP'),則返回函式的第一個引數。

示例 1

以下程式碼返回數值陣列中的最大值。

<?php
   $arg=array(23, 5.55, 142, 56, 99);
   echo "array=";
   foreach ($arg as $i) echo $i . ",";
   echo "\n"; 
   echo "max = " . max($arg);
?>

它將產生以下輸出

array=23,5.55,142,56,99,
max = 142

示例 2

以下程式碼返回字串陣列中的最大值。

<?php
   $arg=array("Java", "Angular", "PHP", "C", "Kotlin");
   echo "array=";
   foreach ($arg as $i) echo $i . ",";
   echo "\n"; 
   echo "max = " . max($arg);
?>

它將產生以下輸出

array=Java,Angular,PHP,C,Kotlin,
max = PHP

示例 3

在下面的例子中,一系列字串值被提供給 max() 函式。讓我們看看它的行為:

<?php
   $val1="Java";
   $val2="Angular";
   $val3="PHP";
   $val4="C";
   $val5="Kotlin";
   echo "values=" . $val1 . "," . $val2 . "," . $val3 . "," . 	$val4 . "," . $val5 . "\n";
   echo "max = " . max($val1, $val2, $val3,$val4,$val5);
?>

它將產生以下輸出

values=Java,Angular,PHP,C,Kotlin
max = PHP

示例 4

在這個例子中,給定的陣列是混合資料型別的集合。

<?php
   $arg=array(23, "Java", 142, 1e2, 99);
   echo "array=";
   foreach ($arg as $i) echo $i . ",";
   echo "\n"; 
   echo "max = " . max($arg);
?>

它將產生以下輸出

array=23,Java,142,100,99,
max = 142

PHP min() 函式

min() 函式返回陣列中的最小元素,或者兩個或多個逗號分隔的引數中的最小值。

min ( array $values ) : mixed

或者:

min ( mixed $value1 [, mixed $... ] ) : mixed
  • 如果只有一個引數,則它應該是一個值陣列,這些值可以是相同或不同型別的

  • 如果給出兩個或多個引數,則它們應該是任何可比較的相同或不同型別的值

PHP min() 函式返回陣列引數或值序列中的最小值。標準比較運算子適用。如果多個不同型別的數值評估結果相等(例如 0 和 'PHP'),則返回函式的第一個引數

示例 1

以下程式碼返回數值陣列中的最小值。

<?php
   $arg=array(23, 5.55, 142, 56, 99);
   echo "array=";
   foreach ($arg as $i) echo $i . ",";
   echo "\n"; 
   echo "min = " . min($arg);
?>

它將產生以下輸出

array=23,5.55,142,56,99,
min = 5.55

示例 2

以下程式碼返回字串陣列中的最小值。

<?php
   $arg=array("Java", "Angular", "PHP", "C", "Kotlin");
   echo "array=";
   foreach ($arg as $i) echo $i . ",";
   echo "\n"; 
   echo "min = " . min($arg);
?>

它將產生以下輸出

array=Java,Angular,PHP,C,Kotlin,
min = Angular

示例 3

在這個例子中,一系列字串值被提供給 min() 函式。

<?php
   $val1="Java";
   $val2="Angular";
   $val3="PHP";
   $val4="C";
   $val5="Kotlin";
   echo "values=" . $val1 . "," . $val2 . "," . $val3 . "," . 	$val4 . "," . $val5 . "\n";
   echo "min = " . min($val1, $val2, $val3,$val4,$val5);
?>

它將產生以下輸出

values=Java,Angular,PHP,C,Kotlin
min = Angular

示例 4

在這個例子中,給定的陣列是混合資料型別的集合。

<?php
   $arg=array(23, "Java", 142, 1e2, 99);
   echo "array=";
   foreach ($arg as $i) echo $i . ",";
   echo "\n"; 
   echo "min = " . min($arg);
?>

它將產生以下輸出

array=23,Java,142,100,99,
min = 23

PHP pow() 函式

pow() 函式用於計算某個數的冪。它返回 xy 計算結果,也稱為 x 的 y 次冪。PHP 還提供 "**" 作為冪運算子。

因此,pow(x,y) 返回 xy,這與 x**y 相同。

pow ( number $base , number $exp ) : number

第一個引數是要提升的底數。第二個引數是底數需要提升的冪。

PHP pow() 函式返回底數的 exp 次冪。如果兩個引數都是非負整數,則結果將作為整數返回,否則將作為浮點數返回。

示例 1

下面的例子使用 pow() 函式計算 10 的 2 次冪:

<?php
   echo "pow(10,2) = " . pow(10,2);
   echo " using ** operator " . 10**2;
?>

它將產生以下輸出

pow(10,2) = 100 using ** operator 100

示例 2

任何數的 0 次冪都等於 1。這在下面的例子中得到了驗證:

<?php
   $x=10;
   $y=0;
   echo "pow(" . $x, "," . $y . ")=". pow($x,$y);
?>

它將產生以下輸出

pow(10,0)=1

示例 3

下面的例子展示瞭如何使用 pow() 函式計算 100 的平方根:

<?php
   $x=100;
   $y=0.5;
   echo "pow(" . $x, "," . $y . ")=". pow($x,$y) . "\n";
   echo "using sqrt() function : ". sqrt(100);
?>

它將產生以下輸出

pow(100,0.5)=10
using sqrt() function : 10

示例 4

此示例演示如何使用 pow() 函式計算圓的面積。

<?php
   $radius=5;
   echo "radius = " . $radius . " area = " . M_PI*pow(5,2);
?>

它將產生以下輸出

radius = 5 area = 78.539816339745

PHP round() 函式

round() 函式在將任何浮點數四捨五入到所需的精度級別時非常有用。正精度引數會導致數字在小數點後四捨五入;而負精度則在小數點前四捨五入。預設精度為“0”。

例如,round(10.6) 返回 11,round(10.2) 返回 10。該函式始終返回浮點數。

此函式還有一個可選引數,稱為mode,它接受後面描述的預定義常量之一。

round ( float $value , int $precision , int $mode ) : float

引數

  • - 要四捨五入的浮點數。

  • 精度 - 要四捨五入的小數位數。預設為 0。正精度在小數點後四捨五入給定數字。負精度在小數點前四捨五入給定數字。

  • 模式 - 以下預定義常量之一。

序號 常量 & 說明
1

PHP_ROUND_HALF_UP

當數字正好是中間值時,將其四捨五入到遠離 0 的方向。因此,1.5 變成 2,-1.5 變成 -2

2

PHP_ROUND_HALF_DOWN

當數字正好是中間值時,將其四捨五入到 0 的方向。因此 1.5 變成 1,-1.5 變成 -1

3

PHP_ROUND_HALF_EVEN

將數字四捨五入到最接近的偶數值

4

PHP_ROUND_HALF_ODD

將數字四捨五入到最接近的奇數值

PHP round() 函式返回一個浮點數,該浮點數透過將值四捨五入到所需的精度來獲得。

示例 1

以下程式碼將給定數字四捨五入到正精度值:

<?php
   $arg=1234.567;
   echo "round(" . $arg . ") = " . round($arg) . "\n";
   echo "round(" . $arg . ",1) = " . round($arg,1) . "\n";
   echo "round(" . $arg . ",2) = " . round($arg,2) . "";
?>

它將產生以下輸出

round(1234.567) = 1235
round(1234.567,1) = 1234.6
round(1234.567,2) = 1234.57

示例 2

以下程式碼將數字四捨五入到負精度值:

<?php
   $arg=1234.567;
   echo "round(" . $arg . ") = " . round($arg) . "\n";
   echo "round(" . $arg . ",-1) = " . round($arg,-1) . "\n";
   echo "round(" . $arg . ",-2) = " . round($arg,-2) . "";
?>

它將產生以下輸出

round(1234.567) = 1235
round(1234.567,-1) = 1230
round(1234.567,-2) = 1200

示例 3

以下程式碼使用 UP 和 DOWN 模式常量進行四捨五入:

<?php
   echo "round(3.45,HALF_UP) = " . round(3.45,0, PHP_ROUND_HALF_UP) . "\n";
   echo "round(3.75 HALF_UP) = " . round(3.75, 1, PHP_ROUND_HALF_DOWN) . "";
?>

它將產生以下輸出

round(3.45,HALF_UP) = 3
round(3.75 HALF_UP) = 3.7

示例 4

以下程式碼使用 ODD 和 EVEN 模式進行四捨五入:

<?php
   echo "round( 3.45,HALF_ODD) = " . round(3.45,0, PHP_ROUND_HALF_ODD) . "\n";
   echo "round(3.78 HALF_EVEN) = " . round(3.78, 0, PHP_ROUND_HALF_EVEN) . "";
?>

它將產生以下輸出

round(3.45,HALF_ODD) = 3
round(3.78, HALF_EVEN) = 4

PHP sqrt() 函式

sqrt() 函式返回正浮點數的平方根。由於負數的平方根未定義,因此它返回 NAN。這是最常用的函式之一。此函式始終返回浮點數。

sqrt (float $arg) : float

PHP sqrt() 函式返回給定 arg 數的平方根。對於負數,函式返回 NAN。

示例 1

以下程式碼計算 100 的平方根:

<?php
   $arg = 100;
   echo "Square root of " . $arg . "=" . sqrt($arg) . "";
?>

它將產生以下輸出

Square root of 100=10

示例 2

對於 sqrt(2)、1/sqrt(2) 和 sqrt(3),PHP 分別具有特殊的預定義常量 M_SQRT2、M_SQRT1_2 和 M_SQRT3。

<?php
   echo "sqrt(2) = " . sqrt(2) . "\n";
   echo "M_SQRT2 = " . M_SQRT2. "\n";
   echo "sqrt(3) = " . sqrt(3) . "\n";
   echo "M_SQRT3 = " . M_SQRT3 . "\n";
   echo "1/sqrt(2)) = " . 1/sqrt(2) . "\n";
   echo "M_SQRT1_2 = " . M_SQRT1_2 . "";
?>

它將產生以下輸出

sqrt(2) = 1.4142135623731
M_SQRT2 = 1.4142135623731
sqrt(3) = 1.7320508075689
M_SQRT3 = 1.7320508075689
1/sqrt(2)) = 0.70710678118655
M_SQRT1_2 = 0.70710678118655

示例 3

數學常量 M_SQRTPI 和 M_2_SQRTPI 分別表示 sqrt(Π) 和 2/sqrt(Π) 的值。

<?php
   echo "sqrt(pi) = " . sqrt(M_PI) . "\n";
   echo "M_SQRTPI = " . M_SQRTPI. "\n";
   echo "2/sqrt(pi) = " . 2/sqrt(M_PI) . "\n";
   echo "M_2_SQRTPI = " . M_2_SQRTPI . "";
?>

它將產生以下輸出

sqrt(pi) = 1.7724538509055
M_SQRTPI = 1.7724538509055
2/sqrt(pi) = 1.1283791670955
M_2_SQRTPI = 1.1283791670955

示例 4

sqrt(-1) 未定義,因此它返回 NAN。

<?php
   echo "sqrt(-1) = " . sqrt(-1) . "";
?>

它將產生以下輸出

sqrt(-1) = NAN

預定義數學常量

除了上述數學函式外,PHP 還具有以下預定義數學常量列表:

常量 描述
M_PI 3.14159265358979323846 π
M_E 2.7182818284590452354 尤拉數 e
M_LOG2E 1.4426950408889634074 log2 e
M_LOG10E 0.43429448190325182765 log10 e
M_LN2 0.69314718055994530942 loge 2
M_LN10 M_LN10 2.30258509299404568402 loge 10 loge 10
M_PI_2 1.57079632679489661923 pi/2
M_PI_4 0.78539816339744830962 pi/4
M_1_PI 0.31830988618379067154 1/pi
M_2_PI 0.63661977236758134308 2/pi
M_SQRTPI 1.77245385090551602729 sqrt(pi)
M_2_SQRTPI 1.12837916709551257390 2/sqrt(pi)
M_SQRT2 1.41421356237309504880 sqrt(2)
M_SQRT3 1.73205080756887729352 sqrt(3)
M_SQRT1_2 0.70710678118654752440 1/sqrt(2)
M_LNPI 1.14472988584940017414 loge(pi)
M_EULER 0.57721566490153286061 尤拉常數
PHP_ROUND_HALF_UP 1 四捨五入到上
PHP_ROUND_HALF_DOWN 2 四捨五入到下
PHP_ROUND_HALF_EVEN 3 四捨五入到偶數
PHP_ROUND_HALF_ODD 4 四捨五入到奇數
NAN NAN 非數字
INF INF 無窮大

PHP Heredoc 和 Nowdoc

PHP 提供了兩種替代方法來宣告單引號或雙引號字串,它們的形式為heredocnowdoc 語法。

  • 單引號字串不解釋跳脫字元,也不展開變數。

  • 另一方面,如果宣告的雙引號字串本身包含雙引號字元,則需要使用“\”符號對其進行轉義。heredoc 語法提供了一種方便的方法。

PHP 中的 Heredoc 字串

PHP 中的 heredoc 字串非常類似於雙引號字串,只是沒有雙引號。這意味著它們不需要轉義引號並展開變數。

Heredoc 語法

$str = <<<IDENTIFIER
place a string here
it can span multiple lines
and include single quote ' and double quotes "
IDENTIFIER;

首先,以“<<<”運算子開頭。在這個運算子之後,提供一個識別符號,然後是一個換行符。字串本身緊隨其後,然後是相同的識別符號來關閉引號。字串可以跨越多行,幷包含單引號(')或雙引號(")。

結束識別符號可以透過空格或製表符縮排,在這種情況下,縮排將從 doc 字串中的所有行中去除。

示例

識別符號只能包含字母數字字元和下劃線,並且必須以下劃線或非數字字元開頭。結束識別符號除了分號(;)之外,不應包含任何其他字元。此外,結束識別符號之前和之後必須只有換行符。

請看以下示例:

<?php  
   $str1 = <<<STRING
   Hello World
      PHP Tutorial
         by TutorialsPoint
   STRING;

   echo $str1;
?>

它將產生以下輸出

Hello World
    PHP Tutorial
        by TutorialsPoint

示例

結束識別符號可以在編輯器的第一列之後是否包含縮排。如果有縮排,則將被刪除。但是,結束識別符號的縮排不能超過正文的任何行。否則,將引發 ParseError。請檢視以下示例及其輸出:

<?php  
   $str1 = <<<STRING
   Hello World
      PHP Tutorial
   by TutorialsPoint
         STRING;
         
   echo $str1;
?>

它將產生以下輸出

PHP Parse error:  Invalid body indentation level 
(expecting an indentation level of at least 16) in hello.php on line 3

示例

heredoc 中的引號不需要轉義,但仍然可以使用 PHP 轉義序列。Heredoc 語法也展開變數。

<?php  
   $lang="PHP";
   echo <<<EOS
   Heredoc strings in $lang expand vriables.
   The escape sequences are also interpreted.
   Here, the hexdecimal ASCII characters produce \x50\x48\x50
   EOS;
?>

它將產生以下輸出

Heredoc strings in PHP expand vriables.
The escape sequences are also interpreted.
Here, the hexdecimal ASCII characters produce PHP

PHP 中的 Nowdoc 字串

PHP 中的 nowdoc 字串類似於 heredoc 字串,只是它不展開變數,也不解釋轉義序列。

<?php  
   $lang="PHP";

   $str = <<<'IDENTIFIER'
   This is an example of Nowdoc string.
   it can span multiple lines
   and include single quote ' and double quotes "
   IT doesn't expand the value of $lang variable
   IDENTIFIER;

   echo $str;
?>

它將產生以下輸出

This is an example of Nowdoc string.
it can span multiple lines
and include single quote ' and double quotes "
IT doesn't expand the value of $lang variable

nowdoc 的語法類似於 heredoc 的語法,只是跟隨“<<<”運算子的識別符號需要用單引號括起來。nowdoc 的識別符號也遵循 heredoc 識別符號的規則。

Heredoc 字串類似於不帶轉義的雙引號字串。Nowdoc 字串類似於不帶轉義的單引號字串。

PHP 複合型別

PHP 中的資料型別可以是“標量型別”或“複合型別”。整數、浮點數、布林值和字串型別是標量型別,而陣列和物件型別則歸類為複合型別。多個型別的值可以一起儲存在複合型別的單個變數中。

在 PHP 中,物件和陣列是兩種複合資料型別。

  • 陣列是其他資料型別的元素的有序集合,這些元素不一定是相同型別的。

  • 物件是內建類或使用者自定義類的例項,由屬性和方法組成。

PHP中的陣列

陣列是一種資料結構,它在一個變數中儲存一個或多個數據值。PHP中的陣列是有序對映,它將值與其鍵關聯。

  • PHP中有兩種宣告陣列的方法。一種是使用內建的`array()`函式,另一種是將陣列元素放在方括號內。

  • 僅包含值的陣列稱為**索引陣列**。每個值都由從0開始的索引標識。

  • 如果陣列是鍵值對的集合,則稱為**關聯陣列**。對的鍵部分可以是數字或字串,而值部分可以是任何型別。

PHP中的`array()`函式

內建的`array()`函式使用給定的引數並返回陣列型別的物件。一個或多個用逗號分隔的引數是陣列中的元素。

array(mixed ...$values): array

括號中的每個值可以是單個值(可以是數字、字串、任何物件甚至另一個數組),也可以是鍵值對。“=>”符號表示鍵與其值之間的關聯。

示例

看一下下面的例子 -

$arr1 = array(10, "asd", 1.55, true);

$arr2 = array("one"=>1, "two"=>2, "three"=>3);

$arr3 = array(
   array(10, 20, 30),
   array("Ten", "Twenty", "Thirty"),
   array("physics"=>70, "chemistry"=>80, "maths"=>90)
);

使用方括號 []

除了`array()`函式外,還可以將用逗號分隔的陣列元素放在方括號內來宣告陣列物件。在這種情況下,元素也可以是單個值、字串或另一個數組。

$arr1 = [10, "asd", 1.55, true];

$arr2 = ["one"=>1, "two"=>2, "three"=>3];

$arr3 = [
   [10, 20, 30],
   ["Ten", "Twenty", "Thirty"],
   ["physics"=>70, "chemistry"=>80, "maths"=>90]
];

訪問陣列元素

要訪問給定陣列中的任何元素,可以使用`array[key]`語法。對於索引陣列,將索引放在方括號內,因為索引本身就是鍵。

<?php
   $arr1 = [10, 20, 30];
   $arr2 = array("one"=>1, "two"=>2, "three"=>3);

   var_dump($arr1[1]);
   var_dump($arr2["two"]);
?>

它將產生以下輸出

int(20)
int(2)

PHP中的陣列遍歷

您還可以使用`foreach`迴圈來迭代索引陣列。

<?php
   $arr1 = [10, 20, 30, 40, 50];
   foreach ($arr1 as $val){
      echo "$val\n";
   } 
?>

它將產生以下輸出

10
20
30
40
50

請注意,PHP內部將索引陣列視為關聯陣列,其中索引被視為鍵。可以使用`var_dump()`輸出陣列來驗證此事實。

我們可以使用`foreach`語法將索引陣列的每個元素解包到鍵和值變數中。

<?php
   $arr1 = [10, 20, 30, 40, 50];
   foreach ($arr1 as $key => $val){
      echo "arr1[$key] = $val" . "\n";
   }
?>

它將產生以下輸出

arr1[0] = 10
arr1[1] = 20
arr1[2] = 30
arr1[3] = 40
arr1[4] = 50

`foreach`迴圈也用於遍歷關聯陣列,儘管任何其他型別的迴圈也可以透過一些操作來使用。

讓我們來看一下`foreach`迴圈的實現,其中每個鍵值對都解包到兩個變數中。

<?php
   $capitals = array(
      "Maharashtra"=>"Mumbai", 
      "Telangana"=>"Hyderabad", 
      "UP"=>"Lucknow", 
      "Tamilnadu"=>"Chennai"
   );

   foreach ($capitals as $k=>$v) {
      echo "Capital of $k is $v" . "\n";
   }
?>

它將產生以下輸出

Capital of Maharashtra is Mumbai
Capital of Telangana is Hyderabad
Capital of UP is Lucknow
Capital of Tamilnadu is Chennai

PHP中的物件

在PHP中,物件是一種複合資料型別。它是內建類或使用者自定義類的例項。下面是一個簡單的PHP類。

class SayHello {
   function hello() {
      echo "Hello World";
   }
}

要宣告一個類的物件,我們需要使用`new`運算子。

$obj=new SayHello;

我們現在可以呼叫它的方法了。

<?php
   class SayHello {
      function hello() {
         echo "Hello World". PHP_EOL;
      }
   }

   $obj=new SayHello;
   var_dump(gettype($obj));
   $obj->hello();
?>

它將產生以下輸出

string(6) "object"
Hello World

stdClass

PHP提供`stdClass`作為通用的空類,它對於動態新增屬性和強制轉換很有用。`stdClass`的物件最初為null。我們可以動態地向其中新增屬性。

<?php
   $obj=new stdClass;
   $obj->name="Deepak";
   $obj->age=21;
   $obj->marks=75;

   print_r($obj);
?>

它將產生以下輸出

stdClass Object (
   [name] => Deepak
   [age] => 21
   [marks] => 75
)

PHP中的陣列到物件的轉換

PHP中的陣列可以按如下方式強制轉換為物件:

<?php
   $arr=array("name"=>"Deepak", "age"=>21, "marks"=>75);
   $obj=(object)$arr;

   print_r($obj);
?>

它將產生以下輸出

stdClass Object (
   [name] => Deepak
   [age] => 21
   [marks] => 75
)

PHP中的物件到陣列的轉換

相反,物件可以轉換為陣列。請看下面的例子:

<?php
   $obj=new stdClass;
   $obj->name="Deepak";
   $obj->age=21;
   $obj->marks=75;

   $arr=(array)$obj;
   print_r($arr);
?>

它將產生以下輸出

Array
(
   [name] => Deepak
   [age] => 21
   [marks] => 75
)

PHP中標量型別到物件型別的轉換

任何標量型別的變數也可以透過型別轉換轉換為物件。標量變數的值將成為物件標量屬性的值。

<?php
   $name="Deepak";
   $age=21;
   $percent=75.50;

   $obj1=(object)$name;
   print_r($obj1);

   $obj2=(object)$age;
   print_r($obj2);

   $obj3=(object)$percent;
   print_r($obj3);
?>

它將產生以下輸出

stdClass Object
(
   [scalar] => Deepak
)
stdClass Object
(
   [scalar] => 21
)
stdClass Object
(
   [scalar] => 75.5
)

PHP 檔案包含

PHP中的`include`語句類似於Java或Python中的`import`語句以及C/C++中的`#include`指令。但是,PHP中`include`語句的工作方式略有不同。

Java/Python中的`import`或C/C++中的`#include`僅將一個或多個語言結構(例如在一個檔案中定義的函式或類)載入到當前檔案中。相反,PHP中的`include`語句將另一個檔案中的所有內容都引入到現有的PHP指令碼中。它可以是PHP程式碼、文字檔案、HTML標記等。

PHP中的“include”語句

這是一個關於PHP中`include`語句如何工作的典型示例:

myfile.php

<?php
   # some PHP code
?>

test.php

<?php
   include 'myfile.php';
   # PHP script in test.php
?>

`include`關鍵字在PHP中非常方便,尤其是在您需要在一個專案中跨多個PHP指令碼使用相同的PHP程式碼(函式或類)或HTML標記時。一個例子是建立應該出現在Web應用程式所有頁面上的選單。

假設您想為您的網站建立一個通用選單。然後,建立一個包含以下內容的檔案“menu.php”。

<a href="https://tutorialspoint.tw/index.htm">Home</a> - 
<a href="https://tutorialspoint.tw/ebxml">ebXML</a> - 
<a href="https://tutorialspoint.tw/ajax">AJAX</a> - 
<a href="https://tutorialspoint.tw/perl">PERL</a> <br />

現在建立任意數量的頁面幷包含此檔案以建立頁首。例如,現在您的“test.php”檔案可以包含以下內容:

<html>
   <body>
      <?php include("menu.php"); ?>
      <p>This is an example to show how to include PHP file!</p>
   </body>
</html>

假設這兩個檔案都位於XAMPP伺服器的文件根資料夾中。訪問**https:///test.php** URL。它將產生以下**輸出**:

PHP File Include

當PHP解析器遇到`include`關鍵字時,它會嘗試在執行當前指令碼的同一目錄中查詢指定的檔案。如果找不到,則搜尋“php.ini”的“include_path”設定中的目錄。

包含檔案時,它包含的程式碼將繼承包含該語句的行所在的變數作用域。呼叫檔案中該行中可用的任何變數都將從那時起在被呼叫檔案中可用。但是,包含檔案中定義的所有函式和類都具有全域性作用域。

示例

在下面的示例中,我們有一個“myname.php”指令碼,其中聲明瞭兩個變數。它包含在另一個指令碼test.php中。這些變數載入在全域性作用域中。

myname.php

<?php
   $color = 'green';
   $fruit = 'apple';
?>

test.php

<?php
   include "myname.php";
   echo "<h2>$fname $lname</h2>";
?>

當瀏覽器訪問**https:///test.php**時,它顯示:

Ravi Teja

但是,如果檔案包含在函式內,則變數僅是函式區域性作用域的一部分。

myname.php

<?php
   $color = 'green';
   $fruit = 'apple';
?>

test.php

<?php
   function showname() {
      include "myname.php";
   }
   echo "<h2>$fname $lname</h2>";
?>

現在,當瀏覽器訪問**https:///test.php**時,它會顯示未定義變數警告:

Warning: Undefined variable $fname in C:\xampp\htdocs\test.php on line 7
Warning: Undefined variable $lname in C:\xampp\htdocs\test.php on line 7

include_once語句

就像`include`一樣,PHP也具有`include_once`關鍵字。唯一的區別是,如果某個檔案中的程式碼已被包含,則不會再次包含它,並且`include_once`返回true。顧名思義,該檔案只會包含一次。

`include_once`可用於在指令碼的特定執行過程中可能會多次包含和評估同一檔案的情況,因此它可以幫助避免函式重新定義、變數值重新賦值等問題。

PHP – include與require

PHP中的`require`關鍵字與`include`關鍵字非常相似。兩者之間的區別在於,`require`失敗時會產生致命的E_COMPILE_ERROR級別錯誤。

換句話說,`require`將停止指令碼,而`include`僅發出警告(E_WARNING),允許指令碼繼續執行。

require_once關鍵字

`require_once`關鍵字類似於`require`,但略有不同。如果您使用`require_once`,則PHP將檢查檔案是否已被包含,如果已包含,則不會再次包含同一檔案。

PHP 日期與時間

PHP的內建庫具有廣泛的函式,有助於以程式設計方式處理和操作日期和時間資訊。PHP中的日期和時間物件可以透過傳入日期/時間資訊的字串表示或從當前系統的時鐘來建立。

PHP提供`DateTime`類,該類定義了許多方法。在本章中,我們將詳細瞭解PHP中可用的各種與日期和時間相關的方法。

PHP中的日期/時間功能實現ISO 8601日曆,該日曆實現了格里高利曆之前使用的當前閏日規則。日期和時間資訊在內部儲存為64位數字。

使用time()獲取時間戳

PHP的`time()`函式為您提供了關於當前日期和時間所需的所有資訊。它不需要引數,但返回一個整數。

time(): int

`time()`返回的整數表示自1970年1月1日格林尼治標準時間午夜以來經過的秒數。這個時刻被稱為UNIX紀元,自那時以來經過的秒數稱為時間戳。

<?php
   print time();
?>

它將產生以下輸出

1699421347

我們可以將時間戳轉換為人類更容易理解的形式。

使用getdate()轉換時間戳

`getdate()`函式可以選擇性地接受時間戳並返回一個包含日期資訊的關聯陣列。如果您省略時間戳,它將使用`time()`返回的當前時間戳。

下表列出了`getdate()`返回的陣列中包含的元素。

序號 鍵與描述 示例
1

seconds

分鐘後的秒數 (0-59)

20
2

minutes

小時後的分鐘數 (0-59)

29
3

hours

一天中的小時數 (0-23)

22
4

mday

月份中的天數 (1-31)

11
5

wday

星期幾 (0-6)

4
6

mon

一年中的月份 (1-12)

7
7

year

年份 (4位數字)

1997
8

yday

一年中的天數 (0-365)

19
9

weekday

星期幾

星期四
10

month

一年中的月份

一月
11

0

Timestamp

948370048

現在您可以完全控制日期和時間。您可以根據需要格式化此日期和時間。

示例

請看以下示例

<?php
   $date_array = getdate();

   foreach ( $date_array as $key => $val ){
      print "$key = $val\n";
   }
   $formated_date  = "Today's date: ";
   $formated_date .= $date_array['mday'] . "-";
   $formated_date .= $date_array['mon'] . "-";
   $formated_date .= $date_array['year'];

   print $formated_date;
?>

它將產生以下輸出

seconds = 0
minutes = 38
hours = 6
mday = 8
wday = 3
mon = 11
year = 2023
yday = 311
weekday = Wednesday
month = November
0 = 1699421880
Today's date: 8-11-2023

使用date()轉換時間戳

`date()`函式返回一個表示日期的格式化字串。您可以使用必須傳遞給它的字串引數來對`date()`返回的格式進行極大的控制。

date(string $format, ?int $timestamp = null): string

`date()`可以選擇性地接受時間戳,如果省略,則使用當前日期和時間。您在傳遞給`date()`的格式字串中包含的任何其他資料都將包含在返回值中。

下表列出了格式字串可以包含的程式碼:

序號 格式與描述 示例
1

a

'am' 或 'pm' 小寫

pm
2

A

'AM' 或 'PM' 大寫

PM
3

d

月份中的天數,帶前導零的數字

20
4

D

星期幾 (三個字母)

Thu
5

F

月份名稱

一月
6

h

小時 (12小時制 - 帶前導零)

12
7

H

小時 (24小時制 - 帶前導零)

22
8

g

小時 (12小時制 - 無前導零)

12
9

G

小時 (24小時制 - 無前導零)

22
10

i

分鐘 (0-59)

23
11

j

月份中的天數 (無前導零)

20
12

l (小寫 'L')

星期幾

星期四
13

L

閏年 ('1' 表示是,'0' 表示否)

1
14

m

一年中的月份 (數字 - 帶前導零)

1
15

M

一年中的月份 (三個字母)

Jan
16

r

RFC 2822 格式的日期

Thu, 21 Dec 2000 16:01:07 +0200
17

n

一年中的月份 (數字 - 無前導零)

2
18

s

小時的秒數

20
19

U

時間戳

948372444
20

y

年份 (兩位數字)

06
21

Y

年份 (四位數字)

2006
22

z

一年中的天數 (0-365)

206
23

Z

與格林尼治標準時間的偏移量(秒)

+5

示例

請看以下示例

<?php
   print date("m/d/y G.i:s \n", time()) . PHP_EOL;
   print "Today is ";
   print date("j of F Y, \a\\t g.i a", time());
?>

它將產生以下輸出

11/08/23 11.23:08

Today is 8 2023f November 2023, at 11.23 am

希望您已經很好地理解了如何根據您的要求格式化日期和時間。為了您的參考,所有日期和時間函式的完整列表在PHP 日期和時間函式中給出。

PHP 標量型別宣告

PHP 從 5 版本開始就提供了型別提示的功能。**型別提示**指的是在函式定義中提供引數資料型別的做法。在 PHP 7 之前,函式型別提示只能使用陣列、可呼叫物件和類。PHP 7 及以後版本,還可以為標量資料型別(例如 int、string、bool 等)的引數插入型別提示。

PHP 是一種動態(且弱)型別語言。因此,在定義函式時,不需要宣告引數的型別,而像 C 或 Java 這樣的靜態型別語言則需要。

PHP 函式的典型定義如下:

function addition($x, $y) {
   echo "First number: $x Second number: $y Addition: " . $x+$y;
}

這裡,我們假設引數 $x 和 $y 是數值型的。但是,即使傳遞給函式的值不是數值型的,PHP 解析器也會盡可能地將變數轉換為相容的型別。

如果傳遞的值之一是數字的字串表示,而另一個是數值型變數,PHP 會將字串變數轉換為數值型以執行加法運算。

示例

看一下下面的例子 -

<?php
   function addition($x, $y) {
      echo "First number: " . $x; 
      echo "\nSecond number: " . $y; 
      echo "\nAddition: " . $x+$y;
   }

   $x="10";
   $y=20;
   addition($x, $y);
?>

它將產生以下輸出

First number: 10
Second number: 20
Addition: 30

但是,如果上面的例子中 $x 是一個不包含有效數值表示的字串,則會遇到錯誤。

<?php
   function addition($x, $y) {
      echo "First number: " . $x; 
      echo "\nSecond number: " . $y; 
      echo "\nAddition: " . $x+$y;
   }

   $x="Hello";
   $y=20;
   addition($x, $y);
?>

執行這段程式碼,看看它如何顯示**錯誤**。

PHP 7 中的標量型別宣告

PHP 7 版本引入的一項新功能允許定義引數資料型別可以在括號內指定的函式。

PHP 7 引入了以下標量型別宣告:

  • Int

  • Float

  • Bool

  • String

  • 介面

  • 陣列

  • 可呼叫物件

舊版本的 PHP 只允許使用陣列、可呼叫物件和類型別作為型別提示。此外,在舊版本的 PHP(PHP 5)中,致命錯誤是可恢復的錯誤,而新版本(PHP 7)則返回一個可丟擲的錯誤。

標量型別宣告以兩種模式實現:

  • **強制模式** - 強制模式是預設模式,無需指定。

  • **嚴格模式** - 必須顯式提示嚴格模式。

強制模式

前面例子中定義的 addition() 函式現在可以透過合併型別宣告來改寫,如下所示:

function addition(int $x, int $y) {
   echo "First number: $x Second number: $y Addition: " . $x+$y;
}

請注意,如果字串包含整數,解析器仍然會轉換不相容的型別,即字串為整數,與之前一樣。

示例

看一下下面的例子 -

<?php
   function addition(int $x, int $y) {
      echo "First number: " . $x;
      echo "\nSecond number: " . $y;
      echo "\nAddition: " . $x+$y;
   }

   $x="10";
   $y=20;
   echo addition($x, $y);
?>

它將產生以下輸出

First number: 10
Second number: 20
Addition: 30

顯然,這是因為 PHP 是一種弱型別語言,PHP 會嘗試將字串型別的變數強制轉換為整數。PHP 7 引入了一種嚴格模式功能來解決這個問題。

嚴格模式

為了應對 PHP 的弱型別檢查,引入了嚴格模式。此模式透過**declare 語句**啟用:

declare (strict_types=1);

此語句應放在 PHP 指令碼的頂部(通常就在 PHP 標記下方)。這意味著標量的型別嚴格性是在每個檔案的基礎上配置的。

在弱模式下,strict_types 標誌為 0。將其設定為 1 會強制 PHP 解析器檢查傳遞的引數和值的相容性。在上面的程式碼中新增此語句並檢查結果。它將顯示以下錯誤訊息:

Fatal error: Uncaught TypeError: addition(): 
Argument #1 ($x) must be of type int, string given, 
called in add.php on line 12 and defined in add.php:4

Stack trace:
#0 add.php(12): addition('10', 20)
#1 {main}
   thrown in add.php on line 4

示例

這是函式定義中標量型別宣告的另一個示例。啟用嚴格模式後,如果將不相容的型別作為引數傳遞,則會引發致命錯誤。

<?php

   // Strict mode
   // declare(strict_types = 1);
   function sum(int ...$ints) {
      return array_sum($ints);
   }

   print(sum(2, '3', 4.1));
?>

取消此程式碼頂部**declare**語句的註釋並執行它。現在它將產生一個**錯誤**:

Fatal error: Uncaught TypeError: 
sum(): Argument #2 must be of type int, string given, 
called in add.php on line 9 and defined in add.php:4
Stack trace:
#0 add.php(9): sum(2, '3', 4.1)
#1 {main}
   thrown in add.php on line 4

型別提示功能主要由 IDE 用於提示使用者函式宣告中使用的引數的預期型別。以下螢幕截圖顯示了 VS Code 編輯器在您鍵入時彈出的函式原型。

PHP Scalar Type Declarations

PHP 返回型別宣告

PHP 7 版本將標量型別宣告功能擴充套件到函式的返回值。根據這項新規定,返回型別宣告指定函式應返回的值的型別。我們可以為返回型別宣告以下型別:

  • int

  • float

  • bool

  • string

  • 介面

  • 陣列

  • 可呼叫物件

要實現返回型別宣告,函式定義如下:

function myfunction(type $par1, type $param2): type {
   # function body
   return $val;
}

PHP 解析器預設情況下是強制型別轉換。您需要宣告 "strict_types=1" 以強制更嚴格地驗證要返回的變數型別與定義中使用的型別。

示例

在下面的例子中,division() 函式的返回型別定義為 int。

<?php
   function division(int $x, int $y): int {
      $z = $x/$y;
      return $z;
   }

   $x=20.5;
   $y=10;

   echo "First number: " . $x; 
   echo "\nSecond number: " . $y; 
   echo "\nDivision: " . division($x, $y);
?>

由於型別檢查未設定為 strict_types=1,即使其中一個引數是非整數,除法也會進行。

First number: 20.5
Second number: 10
Division: 2

但是,一旦在指令碼頂部新增 strict_types 的宣告,程式就會引發致命錯誤訊息。

Fatal error: Uncaught TypeError: division(): Argument #1 ($x) must be of type int, float given, called in div.php on line 12 and defined in div.php:3
Stack trace:
#0 div.php(12): division(20.5, 10)
#1 {main}
   thrown in div.php on line 3

VS Code 甚至在執行程式碼之前就會警告錯誤,在錯誤位置顯示錯誤行:

PHP Return Type Declarations

示例

要使 division() 函式返回 float 而不是 int,請將分子轉換為 float,然後檢視 PHP 如何引發致命錯誤:

<?php
   // declare(strict_types=1);
   function division(int $x, int $y): int {
      $z = (float)$x/$y;
      return $z;
   }

   $x=20;
   $y=10;

   echo "First number: " . $x; 
   echo "\nSecond number: " . $y; 
   echo "\nDivision: " . division($x, $y);
?>

取消此程式碼頂部**declare**語句的註釋並執行它以檢查其輸出。它將顯示錯誤:

First number: 20
Second number: 10PHP Fatal error:  Uncaught TypeError: division(): Return value must be of type int, float returned in /home/cg/root/14246/main.php:5
Stack trace:
#0 /home/cg/root/14246/main.php(13): division()
#1 {main}
  thrown in /home/cg/root/14246/main.php on line 5

PHP - 運算子型別

PHP 中的運算子是什麼?

與任何程式語言一樣,PHP 也具有運算子,它們是預定義的符號(有時是**關鍵字**),用於對一個或多個運算元執行某些常用的操作。

例如,表示式 "4 + 5" 等於 9。這裡 "4" 和 "5" 稱為**運算元**,"+" 稱為**運算子**。

PHP 中有以下幾種運算子:

  • 算術運算子

  • 比較運算子

  • 邏輯運算子

  • 賦值運算子

  • 字串運算子

  • 陣列運算子

  • 條件(或三元)運算子

本章將概述如何在 PHP 中使用這些運算子。在後續章節中,我們將更仔細地研究每個運算子及其工作方式。

PHP 中的算術運算子

我們使用算術運算子對給定的運算元執行加、減、乘、除等數學運算。算術運算子(不包括增量和減量運算子)始終作用於兩個運算元,但是這些運算元的型別應該相同。

下表突出顯示了 PHP 支援的算術運算子。假設變數 “$a” 包含 42,變數 “$b” 包含 20:

運算子 描述 示例
+ 將兩個運算元相加 $a + $b = 62
- 從第一個運算元中減去第二個運算元 $a - $b = 22
* 將兩個運算元相乘 $a * $b = 840
/ 將分子除以分母 $a / $b = 2.1
% 模運算子和整數除法後的餘數 $a % $b = 2
++ 增量運算子,將整數值增加一 $a ++ = 43
-- 減量運算子,將整數值減少一 $a -- = 42

PHP 中的比較運算子

您可以使用比較運算子比較兩個運算元並找到它們之間的關係。它們根據比較的結果返回布林值(true 或 false)。

下表突出顯示了 PHP 支援的比較運算子。假設變數 $a 包含 10,變數 $b 包含 20,則:

運算子 描述 示例
== 檢查兩個運算元的值是否相等,如果相等則條件為 true。 ($a == $b) 為 false
!= 檢查兩個運算元的值是否不相等,如果不相等則條件為 true。 ($a != $b) 為 true
> 檢查左運算元的值是否大於右運算元的值,如果是則條件為 true。 ($a > $b) 為 false
< 檢查左運算元的值是否小於右運算元的值,如果是則條件為 true。 ($a < $b) 為 true
>= 檢查左運算元的值是否大於或等於右運算元的值,如果是則條件為 true。 ($a >= $b) 為 false
<= 檢查左運算元的值是否小於或等於右運算元的值,如果是則條件為 true。 ($a <= $b) 為 true

PHP 中的邏輯運算子

您可以使用 PHP 中的邏輯運算子對多個表示式一起執行邏輯運算。邏輯運算子始終返回布林值,true 或 false。

邏輯運算子通常與條件語句和迴圈一起使用,根據布林條件返回決策。您還可以將它們組合起來,在處理複雜表示式時操作布林值。

下表突出顯示了 PHP 支援的邏輯運算子。

假設變數 $a 包含 10,變數 $b 包含 20,則:

運算子 描述 示例
and 稱為邏輯 AND 運算子。如果兩個運算元都為 true,則條件為 true。 (A and B) 為 true
or 稱為邏輯 OR 運算子。如果兩個運算元中的任何一個非零,則條件為 true。 (A or B) 為 true
&& 稱為邏輯 AND 運算子。如果兩個運算元都非零,則條件為 true。 (A && B) 為 true
|| 稱為邏輯 OR 運算子。如果兩個運算元中的任何一個非零,則條件為 true。 (A || B) 為 true
! 稱為邏輯 NOT 運算子。用於反轉其運算元的邏輯狀態。如果條件為 true,則邏輯 NOT 運算子將使其為 false。 !(A && B) 為 false

PHP 中的賦值運算子

您可以使用 PHP 中的賦值運算子為給定的變數分配或更新新值。賦值運算子的右側儲存值,賦值運算子的左側是將為其賦值的變數。

雙方的資料型別應該相同,否則會報錯。賦值運算子的結合性是從右到左。PHP 支援兩種型別的賦值運算子:

  • 簡單賦值運算子 − 這是最常用的運算子。它用於為變數或常量賦值。

  • 複合賦值運算子 − 賦值運算子 (=) 與其他運算子(如 +、*、/ 等)的組合。

下表重點介紹了 PHP 支援的賦值運算子:

運算子 描述 示例
= 簡單賦值運算子,將右側運算元的值賦給左側運算元 C = A + B 將 A + B 的值賦給 C
+= 加法與賦值運算子,它將右側運算元加到左側運算元上,並將結果賦給左側運算元 C += A 等效於 C = C + A
-= 減法與賦值運算子,它從左側運算元中減去右側運算元,並將結果賦給左側運算元 C -= A 等效於 C = C - A
*= 乘法與賦值運算子,它將右側運算元乘以左側運算元,並將結果賦給左側運算元 C *= A 等效於 C = C * A
/= 除法與賦值運算子,它將左側運算元除以右側運算元,並將結果賦給左側運算元 C /= A 等效於 C = C / A
%= 取模與賦值運算子,它使用兩個運算元取模,並將結果賦給左側運算元 C %= A 等效於 C = C % A

PHP 中的字串運算子

PHP 中有兩個運算子用於處理字串資料型別:

  • “.”(點)運算子是 PHP 的連線運算子。它連線兩個字串運算元(右側字串的字元附加到左側字串),並返回一個新的字串。

  • PHP 還具有“.=”運算子,可以稱為連線賦值運算子。它透過附加右側運算元的字元來更新其左側的字串。

$third = $first . $second;
$leftstring .= $rightstring;

PHP 中的陣列運算子

PHP 定義了以下一組符號,用作陣列資料型別的運算子:

符號 示例 名稱 結果
+ $a + $b 聯合 $a 和 $b 的聯合。
== $a == $b 相等 如果 $a 和 $b 具有相同的鍵/值對,則為 TRUE。
=== $a === $b 恆等 如果 $a 和 $b 具有相同的鍵/值對,順序相同且型別相同,則為 TRUE。
!= $a != $b 不相等 如果 $a 不等於 $b,則為 TRUE。
<> $a <> $b 不相等 如果 $a 不等於 $b,則為 TRUE。
!== $a !== $b 非恆等 如果 $a 與 $b 不相同,則為 TRUE。

PHP 中的條件運算子

PHP 中還有一個運算子稱為條件運算子。它也稱為三元運算子。它首先計算表示式的真假值,然後根據計算結果執行兩個給定語句中的一個。

運算子 描述 示例
? : 條件表示式 如果條件為真?則值為 X:否則值為 Y

PHP 中的運算子類別

我們上面討論的所有運算子都可以分為以下幾類:

  • 一元字首運算子,位於單個運算元之前。

  • 二元運算子,它接受兩個運算元並執行各種算術和邏輯運算。

  • 條件運算子(三元運算子),它接受三個運算元並根據第一個表示式的計算結果計算第二個或第三個表示式。

  • 賦值運算子,它將值賦給變數。

PHP 中的運算子優先順序

運算子的優先順序決定了表示式中運算子的執行順序。例如,在“2+6/3”中,首先執行 6/3 的除法,然後執行“2+2”的加法,因為除法運算子“/”比加法運算子“+”優先順序高。

要強制某個運算子在其他運算子之前呼叫,應使用括號。在這個例子中,(2+6)/3 首先執行加法,然後執行除法。

某些運算子可能具有相同的優先順序。在這種情況下,結合性順序(左或右)決定操作順序。具有相同優先順序但非結合性的運算子不能彼此相鄰使用。

下表列出了 PHP 運算子,按優先順序遞減排列:

運算子 用途
clone new clone 和 new
** 指數
++ -- 增量/減量
~(int) (float) (string) (array) (object) (bool) 型別轉換
instanceof 型別
! 邏輯
* / 乘法/除法
% 取模
+ - . 算術和字串
<< >> 按位移位
< <= > >= 比較
== != === !== <> <=> 比較
& 按位與/引用
^ 按位異或
| 按位或
&& 邏輯與
|| 邏輯或
?? 空值合併
? : 三元
= += -= *= **= /= .= %= &= |= ^= <<= >>= ??= 賦值運算子
yield from yield from
yield yield
print print
and 邏輯
xor 邏輯
or 邏輯

PHP - 算術運算子示例

在 PHP 中,算術運算子用於對數值執行數學運算。下表重點介紹了 PHP 支援的算術運算子。假設變數“$a”儲存 42,變數“$b”儲存 20:

運算子 描述 示例
+ 將兩個運算元相加 $a + $b = 62
- 從第一個運算元中減去第二個運算元 $a - $b = 22
* 將兩個運算元相乘 $a * $b = 840
/ 將分子除以分母 $a / $b = 2.1
% 模運算子和整數除法後的餘數 $a % $b = 2
++ 增量運算子,將整數值增加一 $a ++ = 43
-- 減量運算子,將整數值減少一 $a -- = 42

示例

以下示例演示如何在 PHP 中使用這些算術運算子:

<?php
   $a = 42;
   $b = 20;

   $c = $a + $b;
   echo "Addtion Operation Result: $c \n";

   $c = $a - $b;
   echo "Substraction Operation Result: $c \n";

   $c = $a * $b;
   echo "Multiplication Operation Result: $c \n";

   $c = $a / $b;
   echo "Division Operation Result: $c \n";

   $c = $a % $b;
   echo "Modulus Operation Result: $c \n";

   $c = $a++; 
   echo "Increment Operation Result: $c \n";

   $c = $a--; 
   echo "Decrement Operation Result: $c";
?>

它將產生以下輸出

Addtion Operation Result: 62 
Substraction Operation Result: 22 
Multiplication Operation Result: 840 
Division Operation Result: 2.1 
Modulus Operation Result: 2 
Increment Operation Result: 42 
Decrement Operation Result: 43

PHP - 比較運算子示例

在 PHP 中,比較運算子用於比較兩個值並確定它們之間的關係。這些運算子根據比較結果返回布林值 True 或 False。

下表突出顯示了 PHP 支援的比較運算子。假設變數 $a 包含 10,變數 $b 包含 20,則:

運算子 描述 示例
== 檢查兩個運算元的值是否相等,如果相等則條件為 true。 ($a == $b) 為 false
!= 檢查兩個運算元的值是否不相等,如果不相等則條件為 true。 ($a != $b) 為 true
> 檢查左運算元的值是否大於右運算元的值,如果是則條件為 true。 ($a > $b) 為 false
< 檢查左運算元的值是否小於右運算元的值,如果是則條件為 true。 ($a < $b) 為 true
>= 檢查左運算元的值是否大於或等於右運算元的值,如果是則條件為 true。 ($a >= $b) 為 false
<= 檢查左運算元的值是否小於或等於右運算元的值,如果是則條件為 true。 ($a <= $b) 為 true

此外,這些運算子還可以與邏輯運算子(&&、||、!)結合使用,形成複雜的條件,用於在 PHP 程式中進行決策。

示例

以下示例演示如何在 PHP 中使用這些比較運算子:

<?php
   $a = 42;
   $b = 20;

   if ($a == $b) {
      echo "TEST1 : a is equal to b \n";
   } else {
      echo "TEST1 : a is not equal to b \n";
   }

   if ($a > $b) {
      echo "TEST2 : a is greater than  b \n";
   } else {
      echo "TEST2 : a is not greater than b \n";
   }

   if ($a < $b) {
      echo "TEST3 : a is less than  b \n";
   } else {
      echo "TEST3 : a is not less than b \n";
   }

   if ($a != $b) {
      echo "TEST4 : a is not equal to b \n";
   } else {
      echo "TEST4 : a is equal to b \n";
   }

   if ($a >= $b) {
      echo "TEST5 : a is either greater than or equal to b \n";
   } else {
      echo "TEST5 : a is neither greater than nor equal to b \n";
   }    
   if ($a <= $b) {
      echo "TEST6 : a is either less than or equal to b \n";
   } else {
      echo "TEST6 : a is neither less than nor equal to b";
   }
?>

它將產生以下輸出

TEST1 : a is not equal to b
TEST2 : a is greater than b
TEST3 : a is not less than b
TEST4 : a is not equal to b
TEST5 : a is either greater than or equal to b
TEST6 : a is neither less than nor equal to b

PHP - 邏輯運算子示例

在 PHP 中,邏輯運算子用於組合條件語句。這些運算子允許您透過組合多個條件來建立更復雜的條件。

邏輯運算子通常用於條件語句(例如if、whilefor迴圈)中,根據特定條件控制程式執行流程。

下表突出顯示了 PHP 支援的邏輯運算子。

假設變數 $a 包含 10,變數 $b 包含 20,則:

運算子 描述 示例
and 稱為邏輯 AND 運算子。如果兩個運算元都為 true,則條件為 true。 (A and B) 為 true
or 稱為邏輯 OR 運算子。如果兩個運算元中的任何一個非零,則條件為 true。 (A or B) 為 true
&& 稱為邏輯與運算子。如果左側和右側運算元均為真,則 AND 運算子返回 true。 (A && B) 為 true
|| 稱為邏輯 OR 運算子。如果兩個運算元中的任何一個非零,則條件為 true。 (A || B) 為 true
! 稱為邏輯 NOT 運算子。用於反轉其運算元的邏輯狀態。如果條件為 true,則邏輯 NOT 運算子將使其為 false。 !(A && B) 為 false

示例

以下示例演示如何在 PHP 中使用這些邏輯運算子:

<?php
   $a = 42;
   $b = 0;

   if ($a && $b) {
      echo "TEST1 : Both a and b are true \n";
   } else {
      echo "TEST1 : Either a or b is false \n";
   }

   if ($a and $b) {
      echo "TEST2 : Both a and b are true \n";
   } else {
      echo "TEST2 : Either a or b is false \n";
   }

   if ($a || $b) {
      echo "TEST3 : Either a or b is true \n";
   } else {
      echo "TEST3 : Both a and b are false \n";
   }

   if ($a or $b) {
      echo "TEST4 : Either a or b is true \n";
   } else {
      echo "TEST4 : Both a and b are false \n";
   }

   $a = 10;
   $b = 20;

   if ($a) {
      echo "TEST5 : a is true \n";
   } else {
      echo "TEST5 : a is false \n";
   }

   if ($b) {
      echo "TEST6 : b is true \n";
   } else {
      echo "TEST6 : b is false \n";
   }

   if (!$a) {
      echo "TEST7 : a is true \n";
   } else {
      echo "TEST7 : a is false \n";
   }

   if (!$b) {
      echo "TEST8 : b is true \n";
   } else {
      echo "TEST8 : b is false";
   }
?>

它將產生以下輸出

TEST1 : Either a or b is false 
TEST2 : Either a or b is false 
TEST3 : Either a or b is true 
TEST4 : Either a or b is true 
TEST5 : a is true 
TEST6 : b is true 
TEST7 : a is false 
TEST8 : b is false

PHP - 賦值運算子示例

您可以在 PHP 中使用賦值運算子為變數賦值。賦值運算子是執行算術運算或其他運算的簡寫符號,同時為變數賦值。“=”運算子將右側的值賦給左側的變數。

此外,還有複合賦值運算子,如 +=、-=、*=、/= 和 %=,它們將算術運算與賦值結合起來。例如,“$x += 5”是“$x = $x + 5”的簡寫,將 $x 的值增加 5。賦值運算子提供了一種簡潔的方法來根據變數的當前值更新變數。

下表重點介紹了 PHP 支援的賦值運算子:

運算子 描述 示例
= 簡單賦值運算子。將右側運算元的值賦給左側運算元 C = A + B 將 A + B 的值賦給 C
+= 加法與賦值運算子。它將右側運算元加到左側運算元上,並將結果賦給左側運算元 C += A 等效於 C = C + A
-= 減法與賦值運算子。它從左側運算元中減去右側運算元,並將結果賦給左側運算元 C -= A 等效於 C = C - A
*= 乘法與賦值運算子。它將右側運算元乘以左側運算元,並將結果賦給左側運算元 C *= A 等效於 C = C * A
/= 除法與賦值運算子。它將左側運算元除以右側運算元,並將結果賦給左側運算元 C /= A 等效於 C = C / A
%= 取模與賦值運算子。它使用兩個運算元取模,並將結果賦給左側運算元 C %= A 等效於 C = C % A

示例

以下示例演示如何在 PHP 中使用這些賦值運算子:

<?php
   $a = 42;
   $b = 20;

   $c = $a + $b;
   echo "Addition Operation Result: $c \n";

   $c += $a;
   echo "Add AND Assignment Operation Result: $c \n";

   $c -= $a;
   echo "Subtract AND Assignment Operation Result: $c \n";

   $c *= $a;
   echo "Multiply AND Assignment Operation Result: $c \n";

   $c /= $a;
   echo "Division AND Assignment Operation Result: $c \n";

   $c %= $a;
   echo "Modulus AND Assignment Operation Result: $c";
?>

它將產生以下輸出

Addition Operation Result: 62 
Add AND Assignment Operation Result: 104 
Subtract AND Assignment Operation Result: 62 
Multiply AND Assignment Operation Result: 2604 
Division AND Assignment Operation Result: 62 
Modulus AND Assignment Operation Result: 20

PHP – 字串運算子

PHP 中有兩個運算子用於處理字串資料型別:連線運算子(“.”)和連線賦值運算子(“.=”)。閱讀本章以瞭解這些運算子在 PHP 中的工作方式。

PHP 中的連線運算子

點運算子(“.”)是 PHP 的連線運算子。它連線兩個字串運算元(右側字串的字元附加到左側字串),並返回一個新的字串。

$third = $first . $second;

示例

以下示例演示如何在 PHP 中使用連線運算子:

<?php
   $x="Hello";
   $y=" ";
   $z="PHP";
   $str=$x . $y . $z;
   echo $str;
?>

它將產生以下輸出

Hello PHP

PHP 中的連線賦值運算子

PHP 還具有“.=”運算子,可以稱為連線賦值運算子。它透過附加右側運算元的字元來更新其左側的字串。

$leftstring .= $rightstring;

示例

以下示例使用連線賦值運算子。連線兩個字串運算元,返回左側字串更新後的內容:

<?php
   $x="Hello ";
   $y="PHP";
   $x .= $y;
   echo $x;
?>

它將產生以下輸出

Hello PHP

PHP – 陣列運算子

PHP 定義了以下一組符號,用作陣列資料型別的運算子:

符號 示例 名稱 結果
+ $a + $b 聯合 $a 和 $b 的聯合。
== $a == $b 相等 如果 $a 和 $b 具有相同的鍵/值對,則為 TRUE。
=== $a === $b 恆等 如果 $a 和 $b 具有相同的鍵/值對,順序相同且型別相同,則為 TRUE。
!= $a != $b 不相等 如果 $a 不等於 $b,則為 TRUE。
<> $a <> $b 不相等 如果 $a 不等於 $b,則為 TRUE。
!== $a !== $b 非恆等 如果 $a 與 $b 不相同,則為 TRUE。

聯合運算子將右側陣列附加到左側陣列。如果兩個陣列中都存在鍵,則使用左側陣列中的元素,而忽略右側陣列中匹配的元素。

示例:PHP 中的聯合運算子

以下示例演示如何在 PHP 中使用聯合運算子:

<?php
   $arr1=array("phy"=>70, "che"=>80, "math"=>90);
   $arr2=array("Eng"=>70, "Bio"=>80,"CompSci"=>90);
   $arr3=$arr1+$arr2;
   var_dump($arr3);
?>

它將產生以下輸出

array(6) {
   ["phy"]=>
   int(70)
   ["che"]=>
   int(80)
   ["math"]=>
   int(90)
   ["Eng"]=>
   int(70)
   ["Bio"]=>
   int(80)
   ["CompSci"]=>
   int(90)
}

示例:當兩個陣列相等時

如果兩個陣列具有相同的鍵值對,則稱它們相等。

在下面的示例中,我們有一個索引陣列和另一個關聯陣列,其鍵對應於第一個陣列中元素的索引。因此,兩者相等。

<?php
   $arr1=array(0=>70, 2=>80, 1=>90);
   $arr2=array(70,90,80);
   var_dump ($arr1==$arr2);
   var_dump ($arr2!=$arr1);
?>

它將產生以下輸出

bool(true)
bool(false)

示例:當兩個陣列相同時

當且僅當兩個陣列都具有相同的鍵值對集且順序相同時,它們才相同。

<?php
   $arr1=array(0=>70, 1=>80, 2=>90);
   $arr2=array(70,90,80);
   var_dump ($arr1===$arr2);
   $arr3=[70,80,90];
   var_dump ($arr3===$arr1);
?>

它將產生以下輸出

bool(false)
bool(true)

PHP – 條件運算子示例

當需要根據條件設定值時,您將在 PHP 中使用條件運算子。它也稱為三元運算子。它首先計算表示式的真假值,然後根據計算結果執行兩個給定語句中的一個。

三元運算子提供了一種簡潔的方式來編寫條件表示式。它們由三部分組成:條件、如果條件計算結果為真則返回的值以及如果條件計算結果為假則返回的值。

運算子 描述 示例
? :

條件表示式 如果條件為真?則值為 X:否則值為 Y

語法

語法如下:

condition ? value_if_true : value_if_false

三元運算子特別適用於將if-else語句縮短為一行。您可以使用三元運算子根據條件為變數分配不同的值,而無需多行程式碼。它可以提高程式碼的可讀性。

但是,您應該謹慎使用三元運算子,否則最終會使程式碼過於複雜,難以理解。

示例

嘗試以下示例以瞭解條件運算子如何在 PHP 中工作。將以下 PHP 程式複製並貼上到 test.php 檔案中,將其儲存在 PHP 伺服器的文件根目錄中,然後使用任何瀏覽器瀏覽它。

<?php
   $a = 10;
   $b = 20;

   /* If condition is true then assign a to result otheriwse b */
   $result = ($a > $b ) ? $a :$b;

   echo "TEST1 : Value of result is $result \n";

   /* If condition is true then assign a to result otheriwse b */
   $result = ($a < $b ) ? $a :$b;

   echo "TEST2 : Value of result is $result";
?>

它將產生以下輸出

TEST1 : Value of result is 20
TEST2 : Value of result is 10

PHP 展開運算子

PHP 將三個點符號 (...) 識別為展開運算子。展開運算子有時也稱為splat 運算子。此運算子最早在 PHP 7.4 版本中引入。它可以有效地用於許多情況,例如解包陣列。

示例 1

在下面的示例中,$arr1 中的元素在其自身元素列表之後插入到 $arr2 中。

<?php
   $arr1 = [4,5];
   $arr2 = [1,2,3, ...$arr1];

   print_r($arr2);
?>

它將產生以下輸出

Array
(
   [0] => 1
   [1] => 2
   [2] => 3
   [3] => 4
   [4] => 5
)

示例 2

擴充套件運算子可以在一個表示式中使用多次。例如,在下面的程式碼中,透過擴充套件兩個陣列的元素來建立一個第三個陣列。

<?php
   $arr1 = [1,2,3];
   $arr2 = [4,5,6];
   $arr3 = [...$arr1, ...$arr2];

   print_r($arr3);
?>

它將產生以下輸出

Array
(
   [0] => 1
   [1] => 2
   [2] => 3
   [3] => 4
   [4] => 5
   [5] => 6
)

示例 3

請注意,可以使用array_merge()函式獲得相同的結果,如下所示:

<?php
   $arr1 = [1,2,3];
   $arr2 = [4,5,6];
   $arr3 = array_merge($arr1, $arr2);

   print_r($arr3);
?>

它將產生相同的輸出

Array
(
   [0] => 1
   [1] => 2
   [2] => 3
   [3] => 4
   [4] => 5
   [5] => 6
)

然而,使用(...)運算子效率更高,因為它避免了函式呼叫的開銷。

示例 4

PHP 8.1.0 還引入了另一個特性,允許在解包引數後使用命名引數。無需分別為每個引數提供值,而是使用 ...(三個點)在陣列前,將陣列中的值解包到相應的引數中。

<?php  
   function  myfunction($x, $y, $z=30) {
      echo "x = $x  y = $y  z = $z";
   }

   myfunction(...[10, 20], z:30);
?>

它將產生以下輸出

x = 10  y = 20  z = 30

示例 5

在下面的示例中,函式的返回值是一個數組。然後展開並解包陣列元素。

<?php
   function get_squares() {
      for ($i = 0; $i < 5; $i++) {
         $arr[] = $i**2;
      }
      return $arr;
   }
   $squares = [...get_squares()];
   print_r($squares);
?>

它將產生以下輸出

Array
(
   [0] => 0
   [1] => 1
   [2] => 4
   [3] => 9
   [4] => 16
)

PHP 空值合併運算子

空值合併運算子是 PHP 7 中引入的眾多新特性之一。“合併”的意思是將許多東西組合成一個。此運算子用於替換與isset()函式結合使用的三元運算子。

PHP 中的三元運算子

PHP 有一個由“?”符號表示的三元運算子。三元運算子比較布林表示式,如果為真則執行第一個運算元,否則執行第二個運算元。

expr ? statement1 : statement2;

示例

讓我們使用三元運算子來檢查某個變數是否已設定,方法是使用 isset() 函式,如果已宣告則返回 true,否則返回 false。

<?php
   $x = 1;
   $var = isset($x) ? $x : "not set";
   echo "The value of x is $var";
?>

它將產生以下輸出

The value of x is 1

現在,讓我們刪除“x”的宣告並重新執行程式碼:

<?php
   # $x = 1;
   $var = isset($x) ? $x : "not set";
   echo "The value of x is $var";
?>

程式碼現在將產生以下輸出

The value of x is not set

空值合併運算子

空值合併運算子由 "??" 符號表示。它充當與 isset() 結合使用三元運算子的便捷快捷方式。如果它的第一個運算元存在且不為空,則返回它;否則返回它的第二個運算元。

$Var = $operand1 ?? $operand2;

第一個運算元檢查某個變數是否為空(或是否已設定)。如果它不為空,則返回第一個運算元,否則返回第二個運算元。

示例

請看以下示例:

<?php
   # $num = 10;
   $val = $num ?? 0;
   echo "The number is $val";
?>

它將產生以下輸出

The number is 0

現在取消註釋將$num設定為 10 的第一條語句並重新執行程式碼:

<?php
   $num = 10;
   $val = $num ?? 0;
   echo "The number is $val";
?>

它現在將產生以下輸出

The number is 10

空值合併運算子的一個有用應用是檢查客戶端瀏覽器是否提供了使用者名稱。

示例

以下程式碼從 URL 讀取 name 變數。如果 URL 中的 name 引數確實有值,則顯示他的歡迎訊息。如果沒有,則使用者被稱為訪客。

<?php
   $username = $_GET['name'] ?? 'Guest';
   echo "Welcome $username";
?>

假設此指令碼“hello.php”位於 PHP 伺服器的 htdocs 資料夾中,請在 URL 中輸入https:///hello.php?name=Amar,瀏覽器將顯示以下訊息:

Welcome Amar

如果 URL 為https:///hello.php,瀏覽器將顯示以下訊息:

Welcome Guest

空值合併運算子用作檢查 isset() 函式的三元運算子的特定情況的替代。因此,以下語句給出類似的結果:

<?php
   $username = isset($_GET['name']) ? $_GET['name'] : 'Guest';
   echo "Welcome $username";
?>

它現在將產生以下輸出

Welcome Guest

您可以像下面這樣連結 "??" 運算子:

<?php
   $username = $_GET['name'] ?? $_POST['name'] ?? 'Guest';
   echo "Welcome $username";
?>

它現在將產生以下輸出

Welcome Guest

如果變數 $name 未透過 GET 或 POST 方法設定,這將把使用者名稱設定為訪客。

PHP 宇宙飛船運算子

太空船運算子是 PHP 7.0 版本中引入的眾多新特性之一。它是一個三元比較運算子。

傳統的比較運算子(<,>,!=,== 等)返回 true 或 false(相當於 1 或 0)。另一方面,太空船運算子有三個可能的返回值:-1、0 或 1。此運算子可用於整數、浮點數、字串、陣列、物件等。

語法

太空船運算子使用的符號是"<=>"

$retval = operand1 <=> operand2

這裡,如果運算元 1 小於運算元 2,則 $retval 為 -1;如果兩個運算元相等,則為 0;如果運算元 1 大於運算元 2,則為 1。

太空船運算子實現為組合比較運算子。傳統的比較運算子可以被認為是 <=> 的簡寫,如下表所示:

運算子

<=> 等價物

$a < $b

($a <=> $b) === -1

$a <= $b

($a <=> $b) === -1 || ($a <=> $b) === 0

$a == $b

($a <=> $b) === 0

$a != $b

($a <=> $b) !== 0

$a >= $b

($a <=> $b) === 1 || ($a <=> $b) === 0

$a > $b

($a <=> $b) === 1

示例 1

以下示例顯示如何在 PHP 中使用太空船運算子:

<?php
   $x = 5;
   $y = 10;
   $z = $x <=> $y/2;

   echo "$x <=> $y/2 = $z";
?>

它將產生以下輸出

5 <=> 10/2 = 0

示例 2

更改 $x=4 並檢查結果:

<?php
   $x = 4;
   $y = 10;
   $z = $x <=> $y/2;

   echo "$x <=> $y/2 = $z";
?>

它將產生以下輸出

4 <=> 10/2 = -1

示例 3

更改 $y=7 並再次檢查結果:

<?php
   $x = 7;
   $y = 10;
   $z = $x <=> $y/2;

   echo "$x <=> $y/2 = $z";
?>

它將產生以下輸出

7 <=> 10/2 = 1

示例 4

當與字串運算元一起使用時,太空船運算元的工作方式與 strcmp() 函式相同。

<?php
   $x = "bat";
   $y = "ball";
   $z = $x <=> $y;

   echo "$x <=> $y = $z";
?>

它將產生以下輸出

bat <=> ball = 1

示例 5

更改 $y = "baz" 並檢查結果:

<?php
   $x = "bat";
   $y = "baz";
   $z = $x <=> $y;

   echo "$x <=> $y = $z";
?>

它將產生以下輸出

bat <=> baz = -1

帶有布林運算元的太空船運算子

太空船運算子也適用於布林運算元:

true <=> false returns 1
false <=> true returns -1
true <=> true as well as false <=> false returns 0

PHP – 決策

預設情況下,計算機程式按順序遵循簡單的輸入-處理-輸出路徑。這種順序流程可以透過所有計算機程式語言(包括 PHP)提供的決策控制語句來更改。

計算機程式中的決策

決策是預測程式執行期間發生的條件以及根據條件採取的特定操作。

您可以在程式碼中使用條件語句來做出決策。實現條件邏輯的能力是程式語言的基本要求之一。

典型的決策結構

以下是大多數程式語言中典型的決策結構的通用形式:

Decision Making

PHP 中的決策語句

PHP 支援以下三種決策語句:

  • if...else 語句 – 如果要在一個條件為真時執行一組程式碼,而另一個條件為假時執行另一組程式碼,則使用此語句。

  • elseif 語句 – 將此語句與 if...else 語句一起使用,如果多個條件之一為真,則執行一組程式碼

  • switch 語句 – 如果要選擇要執行的多個程式碼塊之一,請使用 Switch 語句。switch 語句用於避免冗長的if..elseif..else 程式碼塊。

幾乎所有程式語言(包括 PHP)都定義了 if-else 語句。它允許條件執行程式碼片段。在 PHP 中使用 if-else 語句的語法類似於 C:

if (expr)
   statement1
else
   statement2

此處的表示式是布林表示式,計算結果為 true 或 false

  • 任何涉及布林運算子(如 <,>,<=,>=,!= 等)的表示式都是布林表示式。

  • 如果表示式的結果為 true,則將執行後續語句——它可以是簡單語句或複合語句,即包含在一對括號中的語句組。

  • 如果表示式為 false,則忽略後續語句,程式流程從下一條語句繼續。

  • else 語句的使用是可選的。如果程式邏輯需要在表示式(在if 關鍵字之後)計算結果為 false 時執行另一個語句或一組語句。

Decision Making

elseif 語句是ifelse 的組合。它允許您檢查多個表示式的 TRUE 並儘快執行程式碼塊,只要其中一個條件計算結果為 TRUE。與else 語句一樣,elseif 語句也是可選的。

switch 語句類似於對相同表示式的if 語句系列。我們將在本教程的後續章節中詳細瞭解這些語句。

PHP if…else 語句

實現條件邏輯的能力是任何程式語言(包括 PHP)的基本要求。PHP 有三個關鍵字(也稱為語言結構)——if、elseifelse——用於根據不同的條件做出決策。

if 關鍵字是條件執行程式碼片段的基本結構。通常,if 關鍵字與else 關鍵字一起使用,儘管並非總是強制性的。

如果要在一個條件為真時執行一些程式碼,而在同一條件為假時執行另一段程式碼,則使用“if....else”語句。

語法

if 語句在 PHP 中的用法和語法類似於 C 語言。以下是 PHP 中if 語句的語法:

if (expression)
   code to be executed if expression is true;
else
   code to be executed if expression is false;

if 語句之後總是一個布林表示式。

  • 如果 PHP 布林表示式的計算結果為 true,則將執行該布林表示式之後的語句。

  • 如果布林表示式的計算結果為 false,則忽略該語句。

  • 如果演算法需要在表示式為 false 時執行另一個語句,則將其寫在else 關鍵字之後。

示例

這是一個簡單的 PHP 程式碼,演示了if else 語句的用法。有兩個變數 $a 和 $b。程式碼確定哪個變數更大。

<?php
   $a=10;
   $b=20;
   if ($a > $b)
      echo "a is bigger than b";
   else
      echo "a is not bigger than b";
?>

執行上述程式碼時,它將顯示以下輸出

a is not bigger than b

互換“a”和“b”的值並再次執行。現在,您將獲得以下輸出:

a is bigger than b

示例

以下示例將顯示“祝您週末愉快!”如果今天是星期五,否則它將輸出“祝您今天愉快!”:

<?php
   $d = date("D");

   if ($d == "Fri")
      echo "Have a nice weekend!"; 
   else
      echo "Have a nice day!"; 
?>

它將產生以下輸出

Have a nice weekend!

在 PHP 中使用 endif

PHP 程式碼通常與 HTML 指令碼混合使用。我們可以在 PHP 程式碼的if 部分和else 部分中插入 HTML 程式碼。PHP 為ifelse 語句提供了另一種語法。將左大括號更改為冒號 (:),將右大括號更改為endif;,以便可以將 HTML 塊新增到ifelse 部分。

<?php
   $d = date("D");

   if ($d == "Fri"): ?>
      <h2>Have a nice weekend!</h2>

   <?php else: ?>
      <h2>Have a nice day!</h2>
<?php endif ?>

確保上述指令碼位於 PHP 伺服器的文件根目錄中。訪問 URLhttps:///hello.php。如果今天不是星期五,則應在瀏覽器中顯示以下輸出:

Have a nice day!

在 PHP 中使用 elseif

如果要在一個或多個條件為真時執行某些程式碼,則使用elseif 語句。PHP 中的elseif 語言結構是ifelse 的組合。

  • else 類似,它指定如果原始if 表示式的計算結果為 false,則要執行的備用語句。

  • 但是,與else 不同的是,它只會在elseif 條件表示式的計算結果為 true 時執行該備用表示式。

if (expr1)
   code to be executed if expr1 is true;
elseif (expr2)
   code to be executed if expr2 is true;
else
   code to be executed if expr2 is false;

示例

讓我們修改上面的程式碼,以便在星期日、星期五和其他日期顯示不同的訊息。

<?php
   $d = date("D");
   if ($d == "Fri")
      echo "<h3>Have a nice weekend!</h3>";

   elseif ($d == "Sun")
      echo "<h3>Have a nice Sunday!</h3>"; 

   else
      echo "<h3>Have a nice day!</h3>"; 
?>

在星期日,瀏覽器將顯示以下輸出

Have a nice Sunday!

示例

這是另一個示例,用於顯示if-elselif-else 語句的用法:

<?php
   $x=13;
   if ($x%2==0) {
      if ($x%3==0) 
         echo "<h3>$x is divisible by 2 and 3</h3>";
      else
         echo "<h3>$x is divisible by 2 but not divisible by 3</h3>";
   }

   elseif ($x%3==0)
      echo "<h3>$x is divisible by 3 but not divisible by 2</h3>"; 

   else
      echo "<h3>$x is not divisible by 3 and not divisible by 2</h3>"; 
?>

上面的程式碼還使用巢狀if 語句。

對於x 的值為 13、12 和 10,輸出將如下所示:

13 is not divisible by 3 and not divisible by 2
12 is divisible by 2 and 3
10 is divisible by 2 but not divisible by 3

PHP switch 語句

PHP 中的 `switch` 語句可以看作是一系列針對同一表示式的 `if…else` 語句的替代方案。假設你需要將一個表示式或變數與許多不同的值進行比較,並根據它等於哪個值來執行不同的程式碼塊。在這種情況下,你會使用多個 `if…elseif…else` 結構。

然而,這種結構會使程式碼變得相當混亂且難以理解。為了簡化此類程式碼,你可以使用 PHP 中的 `switch case` 結構,它提供了一種更緊湊的替代方案,避免了冗長的 `if..elseif..else` 程式碼塊。

下面的 PHP 指令碼使用了 `if elseif` 語句:

if ($x == 0) {
   echo "x equals 0";
} elseif ($x == 1) {
   echo "i equals 1";
} elseif ($x == 2) {
   echo "x equals 2";
}

你可以使用 `switch case` 語句獲得相同的結果,如下所示:

switch ($x) {
   case 0:
      echo "x equals 0";
   break;
   case 1:
      echo "x equals 1";
   break;
   case 2:
      echo "x equals 2";
   break;
}

`switch` 語句後面跟著一個表示式,該表示式依次與每個 `case` 子句中的值進行比較。如果發現表示式與任何 `case` 匹配,則執行相應的語句塊。

  • `switch` 語句逐行執行花括號內的語句。

  • 如果找到一個 `case` 語句,其表示式的計算結果與 `switch` 表示式的值匹配,則 PHP 開始執行語句,直到 `switch` 塊的末尾,或者第一次遇到 `break` 語句。

  • 如果你不在 `case` 語句列表的末尾編寫 `break` 語句,PHP 將繼續執行下一個 `case` 的語句。

示例

嘗試刪除上面的程式碼中的 `break` 語句並執行它。如果 `x` 的值為 0,你會發現輸出中包含 "x equals 1" 和 "x equals 2" 行。

<?php
   $x=0;
   switch ($x) {
      case 0:
         echo "x equals 0 \n";
      case 1:
         echo "x equals 1 \n";
      case 2:
         echo "x equals 2";
   }
?>

它將產生以下輸出

x equals 0
x equals 1
x equals 2

因此,務必確保每個 `case` 塊以 `break` 語句結尾。

Switch 語句中的預設情況

一個特殊的情況是 `default` 情況。這種情況匹配任何未被其他情況匹配的內容。使用 `default` 是可選的,但如果使用,它必須是花括號內最後一個 `case`。

你可以組合多個 `case` 來模擬多個用 `or` 運算子組合的邏輯表示式。

<?php
   $x=10;
   switch ($x) {
      case 0:
      case 1:
      case 2:
         echo "x between 0 and 2 \n";
      break;
      default:
         echo "x is less than 0 or greater than 2";
   }
?>

要比較的值在 `case` 子句中給出。該值可以是數字、字串,甚至是函式。但是,你不能在 `case` 子句中使用比較運算子(`<`,`>`,`==` 或 `!=`)作為值。

你可以選擇在 `case` 子句中使用分號而不是冒號。如果找不到匹配的 `case`,並且也沒有 `default` 分支,則不會執行任何程式碼,就像沒有哪個 `if` 語句為真一樣。

switch-endswitch 語句

PHP 允許使用替代語法,用 `switch-endswitch` 語句來界定 `switch` 結構。以下版本的 `switch case` 是可接受的。

<?php
   $x=0;
   switch ($x) :
      case 0:
         echo "x equals 0";
      break;
      case 1:
         echo "x equals 1 \n";
      break;
      case 2:
         echo "x equals 2 \n";
      break;
      default:
         echo "None of the above";
   endswitch
?>

在 Switch…Case 中使用 Break 語句

顯然,你不需要編寫 `break` 來終止 `default` 情況,因為它是在 `switch` 結構中的最後一個情況。

示例

請看以下示例:

<?php
   $d = date("D");

   switch ($d){
      case "Mon":
         echo "Today is Monday";
      break;

      case "Tue":
         echo "Today is Tuesday";
      break;
	  
      case "Wed":
         echo "Today is Wednesday";
      break;

      case "Thu":
         echo "Today is Thursday";
      break;

      case "Fri":
         echo "Today is Friday";
      break;

      case "Sat":
         echo "Today is Saturday";
      break;

      case "Sun":
         echo "Today is Sunday";
      break;

      default:
         echo "Wonder which day is this ?";
   }
?>

它將產生以下輸出

Today is Monday

PHP – 迴圈型別

PHP 中的迴圈用於執行相同的程式碼塊指定次數。PHP 支援以下四種迴圈型別。

  • `for` - 迴圈執行程式碼塊指定次數。

  • `foreach` - 迴圈遍歷陣列中每個元素的程式碼塊。

  • `while` - 只要指定的條件為真,就迴圈執行程式碼塊。

  • `do-while` - 迴圈執行程式碼塊一次,然後只要指定的條件為真就重複迴圈。

此外,我們還將解釋如何在 PHP 中使用 `continue` 和 `break` 語句來控制迴圈的執行。

PHP for 迴圈

當你知道要執行語句或語句塊多少次時,可以使用 `for` 語句。

for loop in Php

語法

for (initialization; condition; increment){
   code to be executed;
}

初始化器用於設定迴圈迭代次數計數器的起始值。可以在這裡為此目的宣告一個變數,並且傳統上將其命名為 `$i`。

示例

以下示例進行五次迭代,並在每次迴圈透過時更改兩個變數的賦值:

<?php
   $a = 0;
   $b = 0;

   for( $i = 0; $i<5; $i++ ) {
      $a += 10;
      $b += 5;
   }

   echo ("At the end of the loop a = $a and b = $b" );
?>

它將產生以下輸出

At the end of the loop a = 50 and b = 25

PHP foreach 迴圈

`foreach` 語句用於遍歷陣列。對於每次迭代,當前陣列元素的值都分配給 `$value`,並且陣列指標移動一位,在下一次迭代中將處理下一個元素。

語法

foreach (array as value) {
   code to be executed;
}

示例

嘗試以下示例列出陣列的值。

<?php
   $array = array( 1, 2, 3, 4, 5);

   foreach( $array as $value ) {
      echo "Value is $value \n";
   }
?>

它將產生以下輸出

Value is 1
Value is 2
Value is 3
Value is 4
Value is 5

PHP while 迴圈

只要測試表達式為真,`while` 語句就會執行程式碼塊。

如果測試表達式為真,則執行程式碼塊。程式碼執行後,將再次計算測試表達式,迴圈將繼續,直到測試表達式為假。

for loop in PHP

語法

while (condition) {
   code to be executed;
}

示例

此示例在每次迴圈迭代中遞減變數值,計數器遞增直到達到 10,此時計算結果為假,迴圈結束。

<?php
   $i = 0;
   $num = 50;

   while($i < 10) {
      $num--;
      $i++;
   }

   echo ("Loop stopped at i = $i and num = $num" );
?>

它將產生以下輸出

Loop stopped at i = 10 and num = 40 

PHP do-while 迴圈

`do-while` 語句至少執行一次程式碼塊 - 然後只要條件為真就重複迴圈。

語法

do {
   code to be executed;
}
while (condition);

示例

以下示例將至少增加一次 `i` 的值,並且只要 `i` 的值小於 10,它將繼續增加變數 `i`:

<?php
   $i = 0;
   $num = 0;

   do {
      $i++;
   }

   while( $i < 10 );
   echo ("Loop stopped at i = $i" );
?>

它將產生以下輸出

Loop stopped at i = 10

PHP break 語句

PHP `break` 關鍵字用於提前終止迴圈的執行。

`break` 語句位於語句塊內。它給你完全的控制權,無論何時你想退出迴圈,你都可以出來。退出迴圈後,將執行迴圈後的下一個語句。

PHP Break Statement

示例

在下面的示例中,當計數器值達到 3 時,條件測試變為真,迴圈終止。

<?php
   $i = 0;

   while( $i < 10) {
      $i++;
      if( $i == 3 )break;
   }
   echo ("Loop stopped at i = $i" );
?>

它將產生以下輸出

Loop stopped at i = 3

PHP continue 語句

PHP `continue` 關鍵字用於停止迴圈的當前迭代,但它不會終止迴圈。

就像 `break` 語句一樣, `continue` 語句位於包含迴圈執行的程式碼的語句塊內,前面是一個條件測試。對於遇到 `continue` 語句的迭代,其餘的迴圈程式碼將被跳過,並開始下一輪迭代。

PHP Continue Statement

示例

在下面的示例中,迴圈列印陣列的值,但對於條件為真的情況,它只是跳過程式碼並列印下一個值。

<?php
   $array = array( 1, 2, 3, 4, 5);

   foreach( $array as $value ) {
      if( $value == 3 )continue;
      echo "Value is $value \n";
   }
?>

它將產生以下輸出

Value is 1
Value is 2
Value is 4
Value is 5

PHP for 迴圈

程式預設情況下遵循語句的順序執行。如果程式流程指向程式中任何較早的語句,則構成迴圈。PHP 中的 `for` 語句是構成 PHP 指令碼中迴圈的便捷工具。本章將討論 PHP 的 `for` 語句。

"for" 迴圈的流程圖

下面的流程圖解釋了 `for` 迴圈的工作原理:

PHP For Loop

當你知道要執行語句或語句塊多少次時,可以使用 `for` 語句。

"for" 迴圈的語法

PHP 中 `for` 語句的語法與 C 語言中的 `for` 語句類似。

for (expr1; expr2; expr3){
   code to be executed;
}

`for` 關鍵字後面是一個括號,包含三個用分號分隔的表示式。它們中的每一個都可以為空,或者可以包含多個用逗號分隔的表示式。括號後面是一個或多個放在花括號內的語句。它構成迴圈的主體。

括號中的第一個表示式只在迴圈開始時執行。它通常充當 **初始化器**,用於設定迴圈迭代次數計數器的起始值。

在每次迭代開始時,都會計算 `expr2`。如果它的計算結果為真,則迴圈繼續,並且執行主體塊中的語句。如果它的計算結果為假,則迴圈的執行結束。通常,`expr2` 指定計數器的最終值。

`expr3` 在每次迭代結束時執行。在大多數情況下,此表示式遞增計數器變數。

示例

`for` 迴圈最通用的示例如下:

<?php
   for ($i=1; $i<=10; $i++){
      echo "Iteration No: $i \n";
   }
?>

這是它的**輸出**:

Iteration No: 1
Iteration No: 2
Iteration No: 3
Iteration No: 4
Iteration No: 5
Iteration No: 6
Iteration No: 7
Iteration No: 8
Iteration No: 9
Iteration No: 10

無限 "for" 迴圈

請注意,括號中的所有三個表示式都是可選的。只有兩個分號的 `for` 語句構成一個無限迴圈。

for (; ;) {
   Loop body
}

要停止無限迭代,需要在迴圈體中使用 `break` 語句。

遞減 "for" 迴圈

你也可以形成一個遞減的 `for` 迴圈。要有一個從 10 到 1 的 `for` 迴圈,請將迴圈變數初始化為 10,中間的表示式在每次迭代開始時計算是否大於 1。每次迭代結束時要執行的最後一個表示式應該將其遞減 1。

<?php
   for ($i=10; $i>=1; $i--){
      echo "Iteration No: $i \n";
   }
?>

它將產生以下輸出

Iteration No: 10 
Iteration No: 9 
Iteration No: 8 
Iteration No: 7 
Iteration No: 6 
Iteration No: 5 
Iteration No: 4 
Iteration No: 3 
Iteration No: 2 
Iteration No: 1

使用 "for…endfor" 結構

你也可以使用 ":" (冒號) 符號來啟動迴圈塊,並在塊的末尾放置 `endfor` 語句。

<?php
   for ($i=1; $i<=10; $i++):
      echo "Iteration No: $i \n";
   endfor;
?>

使用 "for" 迴圈迭代索引陣列

陣列中的每個元素都由從 "0" 開始遞增的索引標識。如果存在 5 個元素的陣列,則其下界為 0,上界為 4(陣列大小 -1)。

要獲取陣列中的元素個數,可以使用 `count()` 函式。因此,我們可以使用以下 `for` 語句迭代索引陣列:

<?php
   $numbers = array(10, 20, 30, 40, 50);

   for ($i=0; $i<count($numbers); $i++){
      echo "numbers[$i] = $numbers[$i] \n";
   }
?>

它將產生以下輸出

numbers[0] = 10
numbers[1] = 20
numbers[2] = 30
numbers[3] = 40
numbers[4] = 50

使用 "for" 迴圈迭代關聯陣列

PHP 中的關聯陣列是鍵值對的集合。箭頭符號 (=>) 用於顯示鍵與其值之間的關聯。我們使用 `array_keys()` 函式來獲取鍵的陣列。

下面的 `for` 迴圈從程式碼中定義的關聯陣列 `$capitals` 中列印每個州的首府:

<?php
   $capitals = array(
      "Maharashtra"=>"Mumbai", 
      "Telangana"=>"Hyderabad", 
      "UP"=>"Lucknow", 
      "Tamilnadu"=>"Chennai"
   );
   $keys=array_keys($capitals);

   for ($i=0; $i<count($keys); $i++){
      $cap = $keys[$i];
      echo "Capital of $cap is $capitals[$cap] \n";
   }
?>

這是它的**輸出**:

Capital of Maharashtra is Mumbai
Capital of Telangana is Hyderabad
Capital of UP is Lucknow
Capital of Tamilnadu is Chennai

在 PHP 中使用巢狀 "for" 迴圈

如果在現有迴圈的主體內部使用另一個 `for` 迴圈,則這兩個迴圈被稱為巢狀。

對於外迴圈的計數器變數的每個值,都會完成內迴圈的所有迭代。

<?php
   for ($i=1; $i<=3; $i++){
      for ($j=1; $j<=3; $j++){
         echo "i= $i j= $j \n";
      }
   }
?>

它將產生以下輸出

i= 1 j= 1
i= 1 j= 2
i= 1 j= 3
i= 2 j= 1
i= 2 j= 2
i= 2 j= 3
i= 3 j= 1
i= 3 j= 2
i= 3 j= 3

請注意,字串是陣列的一種形式。 `strlen()` 函式給出字串中字元的個數。

示例

下面的 PHP 指令碼使用兩個巢狀迴圈來列印每行中來自字串的遞增數量的字元。

<?php
   $str = "TutorialsPoint";
   for ($i=0; $i<strlen($str); $i++){
      for ($j=0; $j<=$i; $j++){
         echo "$str[$j]";
      }
      echo "\n";
   }
?>

它將產生以下輸出

T
Tu
Tut
Tuto
Tutor
Tutori
Tutoria
Tutorial
Tutorials
TutorialsP
TutorialsPo
TutorialsPoi
TutorialsPoin
TutorialsPoint

PHP foreach 迴圈

PHP 中的 `foreach` 結構專門用於迭代陣列。如果你嘗試將其用於具有不同資料型別的變數,PHP 將引發錯誤。

PHP 中的 `foreach` 迴圈可以與索引陣列和關聯陣列一起使用。有兩種型別的可用語法:

foreach (array as $value) {
   statements
}

上述方法在你想迭代索引陣列時很有用。下面的語法更適合關聯陣列。

foreach (array as $key => $value) {
   statements
}

但是,這兩種方法都適用於索引陣列,因為陣列中專案的索引也充當鍵。

使用 "foreach" 迴圈和索引陣列

上面的第一種語法在 `foreach` 關鍵字前面顯示一個括號。然後是待遍歷的陣列的名稱,後面跟著 "as" 關鍵字,然後是一個變數。

當第一次迭代開始時,陣列中的第一個元素被分配給變數。迴圈塊結束後,變數取下一個元素的值,並重復迴圈體中的語句,直到陣列中的元素用盡。

`foreach` 迴圈的典型用法如下:

<?php
   $arr = array(10, 20, 30, 40, 50);
   foreach ($arr as $val) {
      echo "$val \n";
   }
?>

示例

PHP 提供了一個非常有用的函式 **array_search()**,它返回給定值的鍵。由於索引陣列中索引本身就是鍵,因此對於每個 **$val**,array_search() 都返回每個值的從零開始的索引。下面的程式碼演示了它的工作原理:

<?php
   $arr = array(10, 20, 30, 40, 50);

   foreach ($arr as $val) {
      $index = array_search($val, $arr);
      echo "Element at index $index is $val \n";
   }
?>

它將產生以下輸出

Element at index 0 is 10
Element at index 1 is 20
Element at index 2 is 30
Element at index 3 is 40
Element at index 4 is 50

示例

**foreach** 語法的第二個變體將陣列中的每個元素解包到兩個變數中:一個用於 **鍵**,一個用於 **值**。

由於索引陣列中索引本身充當鍵,因此 **$k** 變數依次獲取陣列中每個元素的遞增索引。

<?php
   $arr = array(10, 20, 30, 40, 50);
   foreach ($arr as $k=>$v) {
      echo "Key: $k => Val: $v \n";
   }
?>

它將產生以下輸出

Key: 0 => Val: 10
Key: 1 => Val: 20
Key: 2 => Val: 30
Key: 3 => Val: 40
Key: 4 => Val: 50

使用 "foreach" 迴圈迭代關聯陣列

關聯陣列是鍵值對的集合。要遍歷關聯陣列,可以使用 foreach 語法的第二個變體。陣列中的每個元素都被解包到兩個變數中,每個變數分別取鍵及其值。

示例

這是一個示例,其中使用 **foreach** 迴圈遍歷州及其各自首府的陣列。

<?php
   $capitals = array(
      "Maharashtra"=>"Mumbai", "Telangana"=>"Hyderabad", 
      "UP"=>"Lucknow", "Tamilnadu"=>"Chennai"
   );

   foreach ($capitals as $k=>$v) {
      echo "Capital of $k is $v \n";
   }
?>

它將產生以下輸出

Capital of Maharashtra is Mumbai
Capital of Telangana is Hyderabad
Capital of UP is Lucknow
Capital of Tamilnadu is Chennai

但是,您仍然可以使用 **foreach** 語句的第一個版本,其中僅將陣列中每個鍵值對的值儲存在變數中。然後,我們使用之前使用過的 **array_search()** 函式獲取與值對應的鍵。

<?php
   $capitals = array(
      "Maharashtra"=>"Mumbai", "Telangana"=>"Hyderabad", 
      "UP"=>"Lucknow", "Tamilnadu"=>"Chennai"
   );

   foreach ($capitals as $pair) {
      $cap = array_search($pair, $capitals);         
      echo "Capital of $cap is $capitals[$cap] \n";
   }
?>

使用 "foreach" 迴圈迭代二維陣列

可以在 PHP 中宣告多維陣列,其中陣列中的每個元素都是另一個數組本身。請注意,外部陣列和子陣列都可以是索引陣列或關聯陣列。

在下面的示例中,我們有一個二維陣列,可以將其稱為陣列的陣列。我們需要巢狀迴圈來遍歷巢狀的陣列結構,如下所示:

<?php
   $twoD = array(
      array(1,2,3,4),
      array("one", "two", "three", "four"),
      array("one"=>1, "two"=>2, "three"=>3)
   );

   foreach ($twoD as $idx=>$arr) {
      echo "Array no $idx \n";
      foreach ($arr as $k=>$v) {
         echo "$k => $v" . "\n";
      }
      echo "\n";
   }
?>

它將產生以下輸出

Array no 0
0 => 1
1 => 2
2 => 3
3 => 4

Array no 1
0 => one
1 => two
2 => three
3 => four

Array no 2
one => 1
two => 2
three => 3

PHP while 迴圈

在 PHP 指令碼中建立迴圈最簡單的方法是使用 **while** 結構。PHP 中 **while** 迴圈的語法類似於 C 語言中的語法。只要 while 語句中的布林表示式為真,迴圈體塊就會重複執行。

下面的流程圖有助於理解 PHP 中 **while** 迴圈的工作原理:

PHP While Loop

每次在迴圈開始時都會檢查表示式的值。如果 **while** 表示式從一開始就計算為假,則迴圈甚至不會執行一次。即使表示式在塊的執行過程中變為假,執行也不會停止,直到迭代結束。

**while** 迴圈的語法可以表示如下:

while (expr){
   statements
}

示例

以下程式碼顯示了 **while** 迴圈在 PHP 中如何工作的簡單示例。變數 **$x** 在迴圈開始之前初始化為 1。只要它小於或等於 10,就要求執行迴圈體。迴圈體中的 **echo** 語句列印當前迭代次數,並遞增 **x** 的值,以便條件最終變為假。

<?php
   $x = 1;

   while ($x<=10) {
      echo "Iteration No. $x \n";
      $x++;
   }
?>

它將產生以下輸出

Iteration No. 1
Iteration No. 2
Iteration No. 3
Iteration No. 4
Iteration No. 5
Iteration No. 6
Iteration No. 7
Iteration No. 8
Iteration No. 9
Iteration No. 10

請注意,測試條件在每次迭代開始時都會被檢查。即使條件在迴圈內變為假,執行也不會停止,直到迭代結束。

示例

在下面的示例中,“x”在每次迭代中遞增 3。在第三次迭代中,“x”變為 9。由於測試條件仍然為真,因此進行下一輪迭代,其中“x”變為 12。當條件變為假時,迴圈停止。

<?php
   $x = 0;
   while ($x<=10){
      $x+=3;
      echo "Iteration No. $x \n";            
   }
?>

它將產生以下輸出

Iteration No. 3
Iteration No. 6
Iteration No. 9
Iteration No. 12

示例

迴圈變數不需要總是遞增。如果迴圈變數的初始值大於迴圈應該結束的值,則必須遞減它。

<?php
   $x = 5;
   while ($x>0) {
      echo "Iteration No. $x \n";
      $x--;
   }
?>

它將產生以下輸出

Iteration No. 5 
Iteration No. 4 
Iteration No. 3 
Iteration No. 2 
Iteration No. 1

使用 "while" 迭代陣列

PHP 中的索引陣列是元素的集合,每個元素都由從 0 開始的遞增索引標識。

您可以透過構造一個 **while** 迴圈來遍歷陣列,重複訪問第 x 個索引處的元素,直到“x”達到陣列的長度。這裡,“x”是一個計數器變數,每次迭代都會遞增。我們還需要一個 count() 函式來返回陣列的大小。

示例

請看以下示例:

<?php
   $numbers = array(10, 20, 30, 40, 50);
   $size = count($numbers);
   $x=0;

   while ($x<$size) {
      echo "Number at index $x is $numbers[$x] \n";
      $x++;
   }
?>

它將產生以下輸出

Number at index 0 is 10
Number at index 1 is 20
Number at index 2 is 30
Number at index 3 is 40
Number at index 4 is 50

巢狀 "while" 迴圈

您可以在另一個 **while** 迴圈內包含一個 **while** 迴圈。內外 while 迴圈都由兩個獨立的變數控制,這兩個變數在每次迭代後都會遞增。

示例

<?php
   $i=1;
   $j=1;

   while ($i<=3){
      while ($j<=3){
         echo "i= $i j= $j \n";
         $j++;
      }
      $j=1;
      $i++;
   }
?>

它將產生以下輸出

i= 1 j= 1
i= 1 j= 2
i= 1 j= 3
i= 2 j= 1
i= 2 j= 2
i= 2 j= 3
i= 3 j= 1
i= 3 j= 2
i= 3 j= 3

請注意,“j”(內部 **while** 迴圈的計數器變數)在獲取所有值後重新初始化為 1,以便對於下一個“i”值,“j”再次從 1 開始。

遍歷字串中的字元

在 PHP 中,字串可以被認為是字元的索引集合。因此,可以使用一個帶有計數器變數的 while 迴圈(從“0”到字串長度),一次獲取一個字元。

示例

下面的示例計算給定字串中母音的數量。我們使用 **strlen()** 獲取長度,並使用 **str_contains()** 檢查字元是否是母音之一。

<?php
   $line = "PHP is a popular general-purpose scripting language that is especially suited to web development.";
   $vowels="aeiou";
   $size = strlen($line);
   $i=0;
   $count=0;

   while ($i<$size){
      if (str_contains($vowels, $line[$i])) {
         $count++;
      }
      $i++;
   }
   echo "Number of vowels = $count";
?>

它將產生以下輸出

Number of vowels = 32

使用 "endwhile" 語句

PHP 還允許您為 **while** 迴圈使用替代語法。與其將多個語句放在花括號中,不如在條件之後用冒號 (:) 符號標記迴圈體,並在末尾使用 **endwhile** 語句。

示例

<?php
   $x = 1;
   while ($x<=10):
      echo "Iteration No. $x \n";
      $x++;
   endwhile;
?>

它將產生以下輸出

Iteration No. 1
Iteration No. 2
Iteration No. 3
Iteration No. 4
Iteration No. 5
Iteration No. 6
Iteration No. 7
Iteration No. 8
Iteration No. 9
Iteration No. 10

請注意,**endwhile** 語句以分號結尾。

PHP do…while 迴圈

"do…while" 迴圈是 PHP 中可用的另一種迴圈結構。這種型別的迴圈類似於 **while** 迴圈,只是測試條件是在每次迭代結束時檢查,而不是在新迭代開始時檢查。

**while** 迴圈在進入迴圈之前驗證真值條件,而在 "do…while" 迴圈中,真值條件在重新進入迴圈之前進行驗證。因此,"do…while" 迴圈保證至少有一次迭代,無論真值條件如何。

下圖透過使用這兩個迴圈的比較流程圖表示法,顯示了 "while" 迴圈和 "do…while" 迴圈的區別。

PHP Do While Loop

構成 "do…while" 迴圈的 **語法** 與其在 C 語言中的對應部分類似。

do {
   statements;
}
while (expression);

示例

這是一個 "do…while" 迴圈的簡單示例,它列印 1 到 5 的迭代次數。

<?php
   $i=1;
   do{
      echo "Iteration No: $i \n";
      $i++;
   }
   while ($i<=5);
?>

它將產生以下輸出

Iteration No: 1 
Iteration No: 2 
Iteration No: 3 
Iteration No: 4 
Iteration No: 5

示例

以下程式碼使用 **while** 迴圈並生成相同的輸出:

<?php
   $i=1;
   while ($i<=5){
      echo "<h3>Iteration No: $i</h3>";
      $i++;
   }         
?>

因此,可以說 "do…while" 和 "while" 迴圈的行為類似。但是,當計數器變數(在本例中為 **$i**)的初始值設定為大於 while 關鍵字前面的括號中使用的測試表達式中的值的任何值時,差異就會很明顯。

示例

在以下程式碼中,使用了兩個迴圈——**while** 和 "**do…while**"。**while** 迴圈的計數器變數是 **$i**,"do…while" 迴圈的計數器變數是 **$j**。兩者都初始化為 10(任何大於 5 的值)。

<?php
   echo "while Loop \n";
   $i=10;
   while ($i<=5){
      echo "Iteration No: $i \n";
      $i++;
   }   

   echo "do-while Loop \n"; 
   $j=10;
   do{
      echo "Iteration No: $j \n";
      $j++;
   }
   while ($j<=5);
?>

它將產生以下輸出

while Loop
do - while Loop
Iteration No: 10

結果顯示 **while** 迴圈沒有執行任何迭代,因為條件在一開始就是假的(**$i** 初始化為 10,大於測試條件 **$i<=5**)。另一方面,"do…while" 迴圈即使計數器變數 **$j** 初始化為大於測試條件的值,也會進行第一次迭代。

因此,我們可以推斷 "do…while" 迴圈保證至少一次迭代,因為測試條件是在迴圈塊結束時驗證的。**while** 迴圈可能不會進行任何迭代,因為測試條件是在進入迴圈塊之前驗證的。

另一個語法上的區別是 "do…while" 中的 **while** 語句以分號結尾。對於 **while** 迴圈,括號後面跟著一個花括號括起來的迴圈塊。

除此之外,沒有其他區別。可以使用這兩種型別的迴圈進行互換。

遞減 "do…while" 迴圈

要設計一個遞減計數的 "do…while",請將計數器變數初始化為較高的值,使用遞減運算子 (--) 在迴圈內減少每次迭代的計數器值,並將 **while** 括號中的測試條件設定為執行迴圈,直到計數器大於所需的最後一個值。

示例

在下面的示例中,計數器從 5 遞減到 1。

<?php
   $j=5;
   do{
      echo "Iteration No: $j \n";
      $j--;
   }
   while ($j>=1);
?>

它將產生以下輸出

Iteration No: 5
Iteration No: 4
Iteration No: 3
Iteration No: 2
Iteration No: 1

反向遍歷字串

在 PHP 中,字串可以被視為字元的索引陣列。我們可以透過執行遞減的 "do…while" 迴圈來從末尾到開頭一次提取和顯示一個字元,如下所示:

<?php
   $string = "TutorialsPoint";
   $j = strlen($string);

   do{
      $j--;
      echo "Character at index $j : $string[$j] \n";
   }
   while ($j>=1);
?>

它將產生以下輸出

Character at index 13 : t
Character at index 12 : n
Character at index 11 : i
Character at index 10 : o
Character at index 9 : P
Character at index 8 : s
Character at index 7 : l
Character at index 6 : a
Character at index 5 : i
Character at index 4 : r
Character at index 3 : o
Character at index 2 : t
Character at index 1 : u
Character at index 0 : T

巢狀 "do…while" 迴圈

像 **for** 迴圈或 **while** 迴圈一樣,您也可以編寫巢狀的 "do…while" 迴圈。在下面的示例中,上部的 "do…while" 迴圈使用 **$i** 計數迭代,內部 "do…while" 迴圈遞增 **$j**,並且每次列印 **$i*j** 的乘積,從而列印 1 到 10 的表格。

<?php
   $i=1;
   $j=1;

   do{
      print "\n";
      do{
         $k = sprintf("%4u",$i*$j);
         print "$k";
         $j++;
      } 
      while ($j<=10);
      $j=1;
      $i++;
   }
   while ($i<=10);
?>

它將產生以下輸出

1   2   3   4   5   6   7   8   9  10
2   4   6   8  10  12  14  16  18  20
3   6   9  12  15  18  21  24  27  30
4   8  12  16  20  24  28  32  36  40
5  10  15  20  25  30  35  40  45  50
6  12  18  24  30  36  42  48  54  60
7  14  21  28  35  42  49  56  63  70
8  16  24  32  40  48  56  64  72  80
9  18  27  36  45  54  63  72  81  90
10  20  30  40  50  60  70  80  90 100

PHP break 語句

PHP 中的 **break** 語句和 **continue** 語句被稱為“迴圈控制語句”。PHP 中的任何型別的迴圈(**for**、**while** 或 **do-while**)都設計為根據使用的測試條件執行一定次數的迭代。迴圈塊內的 **break** 語句將程式流程帶到塊之外,放棄可能剩下的其餘迭代。

**break** 語句通常有條件地使用。否則,迴圈會在第一次迭代本身完成之前終止。

**break** 語句的 **語法** 如下:

while(expr){
   if (condition){
      break;
   }
}

下面的 **流程圖** 解釋了 **break** 語句的工作原理:

PHP Break Statement

示例

下面的 PHP 程式碼是使用迴圈中 **break** 的一個簡單示例。**while** 迴圈預計執行十次迭代。但是,迴圈內的 **break** 語句在計數器超過 3 時終止它。

<?php
   $i = 1;

   while ($i<=10){
      echo "Iteration No. $i \n";
      if ($i>=3){
         break;
      }
      $i++;
   }
?>

它將產生以下輸出

Iteration No. 1
Iteration No. 2
Iteration No. 3

可以在 break 關鍵字前面提供一個可選的數字引數。它在巢狀迴圈結構中特別有用。它指示要中斷多少個巢狀的封閉結構。預設值為 1,只中斷直接封閉的結構。

示例

下面的示例有三個巢狀迴圈:一個 **for** 迴圈,其中包含一個 **while** 迴圈,而 **while** 迴圈又包含一個 **do-while** 迴圈。

最裡面的迴圈執行 **break**。它前面的數字“2”將控制從當前作用域帶到 **for** 迴圈,而不是直接的 **while** 迴圈。

<?php
   for ($x=1; $x<=3; $x++){
      $y=1;
      while ($y<=3){
         $z=1;
         do {
            echo "x:$x y:$y z:$z \n";
            if ($z==2){
               break 2;
            }
            $z++;
         }
         while ($z<=3);
         $z=1;
         $y++;
      }
   }
?>

它將產生以下輸出

x:1 y:1 z:1
x:1 y:1 z:2
x:2 y:1 z:1
x:2 y:1 z:2
x:3 y:1 z:1
x:3 y:1 z:2

請注意,每次“z”的值變為 2 時,程式都會跳出“y”迴圈。因此,“y”的值始終為 1。

PHP continue 語句

與 **break** 語句類似,**continue** 是 PHP 中的另一個“迴圈控制語句”。與 **break** 語句不同,**continue** 語句跳過當前迭代,並在條件評估以及下一個迭代開始處繼續執行。

**continue** 語句可用於任何型別的迴圈結構,即 **for、foreach、while** 或 **do-while** 迴圈。像 **break** 一樣,**continue** 關鍵字也通常有條件地使用。

while(expr){
   if (condition){
      continue;
   }
}

下面的 **流程圖** 解釋了 **continue** 語句的工作原理:

Php Continue Statement

示例

下面是一個簡單的示例,展示了 **continue** 的用法。**for** 迴圈預計完成十次迭代。但是,每當計數器 id 可被 2 整除時,**continue** 語句都會跳過迭代。

<?php
   for ($x=1; $x<=10; $x++){
      if ($x%2==0){
         continue;
      }
      echo "x = $x \n";
   }
?>

它將產生以下輸出

x = 1
x = 3
x = 5
x = 7
x = 9

示例

**continue** 語句接受一個可選的數字引數,該引數告訴它應該跳過多少層封閉迴圈的結束。預設值為 1。

<?php
   for ($i=1; $i<=3; $i++){
      for ($j=1; $j<=3; $j++){
         for ($k=1; $k<=3; $k++){
            if ($k>1){
               continue 2;
            }
            print "i: $i  j:$j  k: $k\n";
         }
      }
   }
?>

它將產生以下輸出

i: 1  j:1  k: 1
i: 1  j:2  k: 1
i: 1  j:3  k: 1
i: 2  j:1  k: 1
i: 2  j:2  k: 1
i: 2  j:3  k: 1
i: 3  j:1  k: 1
i: 3  j:2  k: 1
i: 3  j:3  k: 1

內部 **for** 迴圈中的 **continue** 語句跳過迭代 2 和 3,並直接跳轉到中間迴圈。因此,輸出顯示所有“i”和“k”變數的值的“k”都為 1。

PHP 陣列

陣列是一種資料結構,它在一個變數中儲存一個或多個具有某種關係的資料值。例如,如果您想儲存一個班級中 10 個學生的成績,那麼與其定義 10 個不同的變數,不如定義一個長度為 10 的陣列更容易。

PHP 中的陣列與 C 語言中的陣列略有不同,因為 PHP 是一種動態型別語言,而 C 是一種靜態型別語言。

  • PHP 中的陣列是有序對映,它將值與鍵關聯。

  • PHP 陣列可以用來實現不同的資料結構,例如堆疊、佇列、列表(向量)、雜湊表、字典等等。

  • 陣列元素的值部分可以是其他陣列。這個特性可以用來實現樹形資料結構和多維陣列。

在 PHP 中宣告陣列有兩種方法。一種是使用內建的 array() 函式,另一種是使用更簡短的語法,將陣列元素放在方括號內。

array() 函式

內建的`array()`函式使用給定的引數並返回陣列型別的物件。一個或多個用逗號分隔的引數是陣列中的元素。

array(mixed ...$values): array

括號中的每個值可以是單個值(可以是數字、字串、任何物件甚至另一個數組),也可以是鍵值對。“=>”符號表示鍵與其值之間的關聯。

示例

$arr1 = array(10, "asd", 1.55, true);
$arr2 = array("one"=>1, "two"=>2, "three"=>3);
$arr3 = array(
   array(10, 20, 30),
   array("Ten", "Twenty", "Thirty"),
   array("physics"=>70, "chemistry"=>80, "maths"=>90)
);

使用方括號 []

除了`array()`函式外,還可以將用逗號分隔的陣列元素放在方括號內來宣告陣列物件。在這種情況下,元素也可以是單個值、字串或另一個數組。

$arr1 = [10, "asd", 1.55, true];
$arr2 = ["one"=>1, "two"=>2, "three"=>3];
$arr3 = [ [10, 20, 30],
   ["Ten", "Twenty", "Thirty"],
   ["physics"=>70, "chemistry"=>80, "maths"=>90] ];

PHP 中的陣列型別

有三種不同型別的陣列,每個陣列值都使用稱為陣列索引的 ID 進行訪問。

  • 索引陣列 - 只包含值的陣列稱為索引陣列。每個值都由從“0”開始的位置索引標識。值以線性方式儲存和訪問。

  • 關聯陣列 - 如果陣列是鍵值對的集合,則稱為關聯陣列。對的鍵元件可以是數字或字串,而值部分可以是任何型別。關聯陣列根據鍵值儲存元素值,而不是嚴格的線性索引順序。

  • 多維陣列 - 如果索引陣列或關聯陣列中的每個值本身都是一個數組,則稱為多維陣列。值使用多個索引進行訪問。

注意 - 內建陣列函式在函式參考中給出 PHP 陣列函式

需要注意的是,PHP 內部將上述任何型別都視為關聯陣列本身。對於索引陣列,其中每個值都有索引,索引本身就是它的鍵。var_dump() 函式揭示了這一事實。

示例

在這個例子中,arr1 是一個索引陣列。但是,var_dump() 顯示任何物件的結構化資訊,顯示每個值都具有其索引作為其鍵。

<?php
   $arr1 = [10, "asd", 1.55, true];
   var_dump($arr1);
?>

它將產生以下輸出

array(4) {
  [0]=>
  int(10)
  [1]=>
  string(3) "asd"
  [2]=>
  float(1.55)
  [3]=>
  bool(true)
}

示例

同樣的原理也適用於多維索引陣列,其中陣列中的每個值都是另一個數組。

<?php
   $arr1 = [
      [10, 20, 30], 
      ["Ten", "Twenty", "Thirty"],
      [1.1, 2.2, 3.3]
   ];

   var_dump($arr1);
?>

它將產生以下輸出

array(3) {
  [0]=>
  array(3) {
    [0]=>
    int(10)
    [1]=>
    int(20)
    [2]=>
    int(30)
  }
  [1]=>
  array(3) {
    [0]=>
    string(3) "Ten"
    [1]=>
    string(6) "Twenty"
    [2]=>
    string(6) "Thirty"
  }
  [2]=>
  array(3) {
    [0]=>
    float(1.1)
    [1]=>
    float(2.2)
    [2]=>
    float(3.3)
  }
}

訪問陣列元素

要訪問給定陣列中的任何元素,可以使用 array[key] 語法。

示例

對於索引陣列,將索引放在方括號內,因為索引本身就是鍵。

<?php
   $arr1 = [10, 20, 30];
   $arr2 = array("one"=>1, "two"=>2, "three"=>3);

   var_dump($arr1[1]);
   var_dump($arr2["two"]);
?>

它將產生以下輸出

int(20)
int(2)

我們將在後續章節中更詳細地探討 PHP 陣列的型別。

PHP 索引陣列

在 PHP 中,陣列元素可以是鍵值對的集合,也可以只包含值。如果陣列僅包含值,則稱其為索引陣列,因為每個元素都由從“0”開始遞增的索引標識。

PHP 中的索引陣列可以使用 array() 函式或方括號語法建立。

$arr1 = array("a", 10, 9.99, true);
$arr2 = ["a", 10, 9.99, true];

陣列中的每個元素都有一個位置索引,第一個元素位於索引“0”處。var_dump() 函式顯示這些陣列的結構化資訊如下:

array(4) {
  [0]=>
  string(1) "a"
  [1]=>
  int(10)
  [2]=>
  float(9.99)
  [3]=>
  bool(true)
}

我們可以使用索引遍歷陣列,獲取給定索引處的值或就地修改元素的值。

遍歷 PHP 中的索引陣列

任何型別的 PHP 迴圈都可以用來遍歷陣列。如果我們想使用forwhile 迴圈,我們必須使用 count() 函式找到陣列中的元素數量,並將其值用作計數forwhile 迴圈的測試條件。

示例

以下程式碼使用for 迴圈列出索引陣列中的所有元素。

<?php
   $numbers = array(10, 20, 30, 40, 50);

   for ($i=0; $i<count($numbers); $i++){
      echo "numbers[$i] = $numbers[$i] \n";
   }
?>

它將產生以下輸出

numbers[0] = 10
numbers[1] = 20
numbers[2] = 30
numbers[3] = 40
numbers[4] = 50

您還可以使用whiledo-while 迴圈遍歷索引陣列。在這裡,我們也需要使用 count() 函式查詢陣列長度。

示例

以下程式碼反向遍歷給定的索引陣列:

<?php
   $numbers = array(10, 20, 30, 40, 50);
   $i = count($numbers)-1;
   while ($i>=0){
      echo "numbers[$i] = $numbers[$i] \n";
      $i--;
   }
?>

它將產生以下輸出

numbers[4] = 50
numbers[3] = 40
numbers[2] = 30
numbers[1] = 20
numbers[0] = 10

使用索引訪問陣列元素

您可以使用array[index] 語法訪問陣列中的任何值。特定索引處的值可以用新值賦值。因此,陣列將就地修改。

示例

以下程式從陣列$arr1 中獲取值,並將它們以相反的順序放入$arr2 中。因此,$arr1 中第 0 位的值成為 $arr2 中的最後一個值。

<?php
   $arr1 = array(10, 20, 30, 40, 50);
   $size = count($arr1);

   for ($i=0; $i<$size; $i++){
      $arr2[$size-$i-1] = $arr1[$i];
   }

   for ($i=0; $i<$size; $i++){
      echo "arr1[$i] = $$arr1[$i] arr2[$i] = $$arr2[$i] \n";
   }
?>

它將產生以下輸出

arr1[0] = $10 arr2[0] = $50
arr1[1] = $20 arr2[1] = $40
arr1[2] = $30 arr2[2] = $30
arr1[3] = $40 arr2[3] = $20
arr1[4] = $50 arr2[4] = $10

使用“foreach”迴圈遍歷索引陣列

您還可以使用foreach 迴圈迭代索引陣列。請看下面的示例

<?php
   $arr1 = [10, 20, 30, 40, 50];
   foreach ($arr1 as $val){
      echo "$val \n";
   } 
?>

它將產生以下輸出

10 
20 
30 
40 
50

請注意,PHP內部將索引陣列視為關聯陣列,其中索引被視為鍵。可以使用`var_dump()`輸出陣列來驗證此事實。

示例

我們可以使用foreach 語法將索引陣列的每個元素解包到鍵和值變數中:

<?php
   $arr1 = [10, 20, 30, 40, 50];
   foreach ($arr1 as $key => $val){
      echo "arr1[$key] = $val \n";
   }
?>

它將產生以下輸出

arr1[0] = 10
arr1[1] = 20
arr1[2] = 30
arr1[3] = 40
arr1[4] = 50

在 PHP 中,陣列可以混合包含值和鍵值對。PHP 只為沒有鍵的值分配索引。

示例

在這個例子中,PHP 為數字分配遞增索引,跳過其中出現的鍵值對。

<?php
   $arr1 = [10, 20, 
         "vals" => ["ten", "twenty"],
         30, 40, 50];

   var_dump($arr1);
?>

它將產生以下輸出

array(6) {
  [0]=>
  int(10)
  [1]=>
  int(20)
  ["vals"]=>
  array(2) {
    [0]=>
    string(3) "ten"
    [1]=>
    string(6) "twenty"
  }
  [2]=>
  int(30)
  [3]=>
  int(40)
  [4]=>
  int(50)
}

PHP 關聯陣列

如果 PHP 陣列中的每個元素都是鍵值對,則此類陣列稱為關聯陣列。在這種型別的陣列中,每個值都由其關聯的鍵而不是索引標識。

  • 關聯陣列用於實現字典、對映、樹等資料結構。

  • 在 PHP 中,使用“=>”符號建立鍵與其值之間的關聯。

如何在 PHP 中宣告關聯陣列?

可以使用宣告陣列的兩種方法——array() 函式和方括號表示法。

$arr1 = array(
   "Maharashtra"=>"Mumbai", 
   "Telangana"=>"Hyderabad", 
   "UP"=>"Lucknow", 
   "Tamilnadu"=>"Chennai"
);

$arr2 = ["Maharashtra"=>"Mumbai", 
   "Telangana"=>"Hyderabad", 
   "UP"=>"Lucknow", 
   "Tamilnadu"=>"Chennai"];

如果我們呼叫 var_dump() 函式,以上兩個陣列將顯示類似的結構:

array(4) {
   ["Maharashtra"]=>
   string(6) "Mumbai"
   ["Telangana"]=>
   string(9) "Hyderabad
   ["UP"]=>
   string(7) "Lucknow"
   ["Tamilnadu"]=>
   string(7) "Chennai"
}

關聯陣列中每個元素的部分可以是任何數字(整數、浮點數或布林值)或字串。部分可以是任何型別。但是,浮點鍵將轉換為整數。因此,布林 true/false 用作“1”或“0”作為鍵。

示例

請看以下示例:

<?php
   $arr1 = array(
      10=>"hello",
      5.75=>"world",
      -5=>"foo",
      false=>"bar"
   );
   var_dump($arr1);     
?>

它將產生以下輸出

array(4) {
  [10]=>
  string(5) "hello"
  [5]=>
  string(5) "world"
  [-5]=>
  string(3) "foo"
  [0]=>
  string(3) "bar"
}

請注意,鍵 5.75 將四捨五入為 5,鍵“true”反映為“0”。如果同一個鍵在陣列中出現多次,則最後出現的鍵值對將被保留,丟棄鍵與之前值的關聯。

PHP 內部甚至將索引陣列視為關聯陣列,其中索引實際上是值的鍵。這意味著第 0 個索引處的值的鍵等於“0”,依此類推。對索引陣列進行 var_dump() 也會顯示出 PHP 陣列的這種特性。

迭代 PHP 關聯陣列

foreach 迴圈是最簡單且最適合迭代關聯陣列的方法,儘管其他型別的迴圈也可以透過一些操作使用。

示例

讓我們看看foreach 迴圈的實現,其中每個鍵值對都解包到兩個變數中。

<?php
   $capitals = array(
      "Maharashtra"=>"Mumbai", 
      "Telangana"=>"Hyderabad", 
      "UP"=>"Lucknow", 
      "Tamilnadu"=>"Chennai"
   );

   foreach ($capitals as $k=>$v) {
      echo "Capital of $k is $v \n";
   }
?>

它將產生以下輸出

Capital of Maharashtra is Mumbai
Capital of Telangana is Hyderabad
Capital of UP is Lucknow
Capital of Tamilnadu is Chennai

還有另一種在 PHP 中使用foreach 迴圈的方法,其中每個元素都儲存在一個變數中。然後,我們可以使用array_search() 分離鍵和值部分,並在迴圈體中使用它們。

<?php
   $capitals = array(
      "Maharashtra"=>"Mumbai", 
      "Telangana"=>"Hyderabad", 
      "UP"=>"Lucknow", 
      "Tamilnadu"=>"Chennai"
   );

   foreach ($capitals as $pair) {
      $cap = array_search($pair, $capitals);         
      echo "Capital of $cap is $capitals[$cap] \n";
   }
?>

它將產生以下輸出

Capital of Maharashtra is Mumbai 
Capital of Telangana is Hyderabad 
Capital of UP is Lucknow 
Capital of Tamilnadu is Chennai

要使用 for、whiledo-while 迴圈,我們必須首先獲取所有鍵的陣列(使用 array_keys()),找到大小並將其用作迴圈語法中的測試條件。

示例

以下是如何使用for 迴圈遍歷關聯陣列:

<?php
   $capitals = array(
      "Maharashtra"=>"Mumbai", 
      "Telangana"=>"Hyderabad", 
      "UP"=>"Lucknow",
      "Tamilnadu"=>"Chennai"
   );
   $keys=array_keys($capitals);

   for ($i=0; $i<count($keys); $i++){
      $cap = $keys[$i];
      echo "Capital of $cap is $capitals[$cap] \n";
   }
?>

它將產生以下輸出

Capital of Maharashtra is Mumbai 
Capital of Telangana is Hyderabad 
Capital of UP is Lucknow 
Capital of Tamilnadu is Chennai

使用鍵訪問值

在關聯陣列中,鍵是值的識別符號而不是索引。因此,要獲取與某個鍵關聯的值,請使用 $arr[key] 語法。這也可以用來更新某個鍵的值。

示例

在下面的程式碼中,聲明瞭一個關聯陣列$arr1。建立另一個數組$arr2,以便它儲存來自$arr1 的每一對,每個鍵的值加倍。

<?php
   $arr1 = array("a"=>10, "b"=>20, "c"=>30, "d"=>40);
   foreach ($arr1 as $k=>$v){
      $arr2[$k] = $v*2;
   }
   print_r($arr2);
?>

它將產生以下輸出

Array
(
   [a] => 20
   [b] => 40
   [c] => 60
   [d] => 80
)

此處使用的print_r() 函式以易於理解的人類可讀形式顯示儲存在陣列中的資料。

PHP 多維陣列

多維陣列是陣列的陣列。在 PHP 陣列中,每個元素都可以是另一個數組。如果陣列包含值或鍵值對,其值是單個標量型別,則它是一維陣列。如果陣列中的每個元素都是一個或多個標量值的陣列,則它是一個二維陣列。

PHP 陣列也可以是二維關聯陣列,其中外部陣列的每個元素都是鍵值對,其值是另一個關聯陣列。

# one dimensional indexed array
$arr = [10, 20, 30, 40];

# one dimensional associative array
$arr = ["key1"=> "val1", "key2" => "val2", "key3" => "val3"];

# two dimensional indexed array
$arr = [
   [1,2,3,4],
   [10, 20, 30, 40],
   [100, 200, 300, 400]
];

# two dimensional associative array
$arr = [
   "row1" => ["key11" => "val11", "key12" => "val12", "key13" => "val13"],
   "row2" => ["key21" => "val21", "key22" => "val22", "key23" => "val23"],
   "row3" => ["key31" => "val31", "key32" => "val32", "key33" => "val33"]
];

迭代二維陣列

需要兩個巢狀迴圈才能遍歷二維陣列中的所有元素。foreach 迴圈更適合陣列遍歷。二維陣列就像資料以行和列形式的表格表示。

示例

以下示例顯示如何以表格形式重現二維陣列:

<?php
   $tbl = [
      [1,2,3,4],
      [10, 20, 30, 40],
      [100, 200, 300, 400]
   ];    
   echo ("\n");
   foreach ($tbl as $row){
      foreach ($row as $elem){
         $val = sprintf("%5d", $elem);
         echo $val;
      }
      echo "\n";
   }
?>

它將產生以下輸出

  1    2    3    4
 10   20   30   40
100  200  300  400

示例

我們還可以使用兩個巢狀的foreach 迴圈來遍歷二維關聯陣列。將外部陣列的每一行解包到行鍵和行值變數中,並使用內部foreach 迴圈遍歷每一行的元素。

<?php
   $tbl = [
      "row1" => ["key11" => "val11", "key12" => "val12", "key13" => "val13"],
      "row2" => ["key21" => "val21", "key22" => "val22", "key23" => "val23"],
      "row3" => ["key31" => "val31", "key32" => "val32", "key33" => "val33"]
   ];

   echo ("\n");
   foreach ($tbl as $rk=>$rv){
      echo "$rk\n";
      foreach ($rv as $k=>$v){
         echo "$k => $v  ";
      }
      echo "\n";
   }
?>

它將產生以下輸出

row1
key11 => val11  key12 => val12  key13 => val13
row2
key21 => val21  key22 => val22  key23 => val23
row3
key31 => val31  key32 => val32  key33 => val33

訪問二維陣列中的元素

訪問和修改陣列中元素的 $arr[$key] 語法也可以擴充套件到二維陣列。對於二維索引陣列,可以使用表示式“$arr[$i][$j]”獲取和賦值第 i 行中的第 j 個元素。

示例

<?php
   $tbl = [[1,2,3,4], [10, 20, 30, 40], [100, 200, 300, 400]];    

   # prints number in index 2 of the row 2
   print ("Value at [2], [2] :" . $tbl[2][2]);
?>

它將產生以下輸出

Value at [2], [2] :300

類似地,可以將第 i 行和第 j 列的值設定為另一個值。

$tbl[2][2] = 250;

示例

如果是二維關聯陣列,我們需要使用所需列的行鍵和鍵值變數來訪問或修改其值。

<?php
   $tbl = [
   "row1" => ["key11" => "val11", "key12" => "val12", "key13" => "val13"],
   "row2" => ["key21" => "val21", "key22" => "val22", "key23" => "val23"],
   "row3" => ["key31" => "val31", "key32" => "val32", "key33" => "val33"]
   ];

   print "value at row2 - key22 is " . $tbl["row2"]["key22"];
?>

它將產生以下輸出

value at row2 - key22 is val22

多維陣列

在上面的例子中,我們有一個數組,其中每個鍵的關聯值是另一個鍵值對的集合,我們稱之為二維陣列。這個概念可以擴充套件到任意數量的級別。例如,如果內部陣列中的每個元素將其鍵與另一個數組關聯,則它成為一個三維陣列。

這是一個三維陣列的示例

$arr3D = [
   [
      [1, 0, 9],
      [0, 5, 6],
      [1, 0, 3]
   ],
   [
      [0, 4, 6],
      [0, 0, 1],
      [1, 2, 7]
   ],
];

示例

要遍歷這樣的三維陣列,我們需要三個巢狀的foreach 迴圈,如下所示:

<?php
   $arr3D = [ 
      [[1, 0, 9],[0, 5, 6],[1, 0, 3]],
      [[0, 4, 6],[0, 0, 1],[1, 2, 7]],
   ];

   foreach ($arr3D as $arr) {
      foreach ($arr as $row) {
         foreach ($row as $element) {
            echo "$element ";
         }
         echo "\n";
      }
      echo "\n";
   }
?>

它將產生以下輸出

1 0 9
0 5 6
1 0 3

0 4 6
0 0 1
1 2 7

但是,完全可以宣告一個擴充套件到任意維度的陣列。為此,我們需要一個通用的解決方案來遍歷任意維度的陣列。

多維陣列的遞迴遍歷

以下程式碼顯示了一個遞迴函式,如果某個鍵的值是另一個數組,則該函式會呼叫自身。如果我們將任何陣列作為引數傳遞給此函式,它將被遍歷,顯示其中的所有鍵值對。

function showarray($arr) {
   foreach ($arr as $k=>$v) {
      if (is_array($v)) {
         showarray($v);
      } else {
         echo "$k => $v  ";
      }
   }
   echo "\n";
}

示例

讓我們將上面的三維陣列$arr3D 傳遞給它並檢視結果:

<?php
   $arr3D = [ 
      [[1, 0, 9],[0, 5, 6],[1, 0, 3]],
      [[0, 4, 6],[0, 0, 1],[1, 2, 7]],
   ];

   function showarray($arr){
      foreach ($arr as $k=>$v){
         if (is_array($v)){
            showarray($v);
         } else {
            echo "$k => $v  ";
         }
      }
      echo "\n";
   }
   showarray($arr3D);
?>

它將產生以下輸出

0 => 1  1 => 0  2 => 9
0 => 0  1 => 5  2 => 6
0 => 1  1 => 0  2 => 3
0 => 0  1 => 4  2 => 6
0 => 0  1 => 0  2 => 1
0 => 1  1 => 2  2 => 7

此遞迴函式可用於任何型別的陣列,無論是索引陣列還是關聯陣列,以及任何維度。

示例

讓我們使用二維關聯陣列作為引數傳遞給 showarray() 函式:

<?php
   $tbl = [
      "row1" => ["key11" => "val11", "key12" => "val12", "key13" => "val13"],
      "row2" => ["key21" => "val21", "key22" => "val22", "key23" => "val23"],
      "row3" => ["key31" => "val31", "key32" => "val32", "key33" => "val33"]
   ];

   function showarray($arr){
      foreach ($arr as $k=>$v){
         if (is_array($v)){
            showarray($v);
         } else {
            echo "$k => $v  ";
         }
      }
      echo "\n";
   }
   showarray($tbl);
?>

它將產生以下輸出

key11 => val11  key12 => val12  key13 => val13
key21 => val21  key22 => val22  key23 => val23
key31 => val31  key32 => val32  key33 => val33

PHP 陣列函式

PHP 陣列函式允許您以各種方式與陣列互動和操作它們。PHP 陣列對於儲存、管理和操作變數集至關重要。

PHP 支援簡單和多維陣列,可以是使用者建立的,也可以是由其他函式建立的。

安裝

使用PHP陣列函式無需安裝;它們是PHP核心的一部分,隨標準PHP安裝一起提供。

執行時配置

此擴充套件程式在php.ini中沒有定義任何配置指令。

PHP 陣列函式

下表列出了所有與PHP陣列相關的函式。其中,“版本”列指示支援該函式的最早PHP版本。

序號 函式及描述 版本
1 array()

建立陣列

4.2.0
2 array_change_key_case()

返回一個所有鍵都為小寫或大寫的陣列

4.2.0
3 array_chunk()

將陣列分割成多個數組塊

4.2.0
3 array_column()

返回輸入陣列中單列的值

5.5.0
4 array_combine()

使用一個數組作為鍵,另一個數組作為值來建立一個數組

5
5 array_count_values()

返回一個數組,其中包含每個值的出現次數

4
6 array_diff()

比較陣列值,並返回差異

4
7 array_diff_assoc()

比較陣列鍵和值,並返回差異

4
8 array_diff_key()

比較陣列鍵,並返回差異

5
9 array_diff_uassoc()

比較陣列鍵和值,並使用額外的使用者自定義函式進行檢查,然後返回差異

5
10 array_diff_ukey()

比較陣列鍵,並使用額外的使用者自定義函式進行檢查,然後返回差異

5
11 array_fill()

用值填充陣列

4
12 array_fill_keys()

用值填充陣列,並指定鍵

5
13 array_filter()

使用使用者自定義函式過濾陣列元素

4
14 array_flip()

交換陣列中所有鍵與其關聯的值

4
15 array_intersect()

比較陣列值,並返回匹配項

4
16 array_intersect_assoc()

比較陣列鍵和值,並返回匹配項

4
17 array_intersect_key()

比較陣列鍵,並返回匹配項

5
18 array_intersect_uassoc()

比較陣列鍵和值,並使用額外的使用者自定義函式進行檢查,然後返回匹配項

5
19 array_intersect_ukey()

比較陣列鍵,並使用額外的使用者自定義函式進行檢查,然後返回匹配項

5
20 array_key_exists()

檢查陣列中是否存在指定的鍵

4
21 array_keys()

返回陣列的所有鍵

4
22 array_map()

將陣列的每個值傳送到使用者自定義函式,該函式返回新值

4
23 array_merge()

將一個或多個數組合併成一個數組

4
24 array_merge_recursive()

將一個或多個數組合併成一個數組

4
25 array_multisort()

對多個或多維陣列進行排序

4
26 array_pad()

向陣列插入指定數量的項,並使用指定的值

4
27 array_pop()

刪除陣列的最後一個元素

4
28 array_product()

計算陣列中值的乘積

5
29 array_push()

向陣列的末尾插入一個或多個元素

4
30 array_rand()

從陣列中返回一個或多個隨機鍵

4
31 array_reduce()

使用使用者定義的函式將陣列作為字串返回

4
32 array_reverse()

按相反順序返回陣列

4
33 array_search()

在陣列中搜索給定值並返回鍵

4
34 array_shift()

刪除陣列的第一個元素,並返回已刪除元素的值

4
35 array_slice()

返回陣列的選定部分

4
36 array_splice()

刪除和替換陣列的指定元素

4
37 array_sum()

返回陣列中值的總和

4
38 array_udiff()

在使用者自定義函式中比較陣列值並返回一個數組

5
39 array_udiff_assoc()

比較陣列鍵,在使用者自定義函式中比較陣列值,並返回一個數組

5
40 array_udiff_uassoc()

在使用者自定義函式中比較陣列鍵和陣列值,並返回一個數組

5
41 array_uintersect()

在使用者自定義函式中比較陣列值並返回一個數組

5
42 array_uintersect_assoc()

比較陣列鍵,在使用者自定義函式中比較陣列值,並返回一個數組

5
43 array_uintersect_uassoc()

在使用者自定義函式中比較陣列鍵和陣列值,並返回一個數組

5
44 array_unique()

刪除陣列中的重複值

4
45 array_unshift()

向陣列的開頭新增一個或多個元素

4
46 array_values()

返回陣列的所有值

4
47 array_walk()

將使用者函式應用於陣列的每個成員

3
48 array_walk_recursive()

遞迴地將使用者函式應用於陣列的每個成員

5
49 arsort()

按相反順序對陣列進行排序並保持索引關聯

3
50 asort()

對陣列進行排序並保持索引關聯

3
51 compact()

建立包含變數及其值的陣列

4
52 count()

計算陣列中的元素個數或物件中的屬性個數

3
53 current()

返回陣列中的當前元素

3
54 each()

返回陣列中的當前鍵值對

3
55 end()

將陣列的內部指標設定為其最後一個元素

3
56 extract()

從陣列將變數匯入到當前符號表中

3
57 in_array()

檢查陣列中是否存在指定的值

4
58 key()

從陣列中獲取鍵

3
59 krsort()

按相反順序對陣列的鍵進行排序

3
60 ksort()

按鍵對陣列進行排序

3
61 list()

像陣列一樣分配變數

3
62 natcasesort()

使用不區分大小寫的“自然順序”演算法對陣列進行排序

4
63 natsort()

使用“自然順序”演算法對陣列進行排序

4
64 next()

推進陣列的內部陣列指標

3
65 pos()

current() 的別名

3
66 prev()

倒回內部陣列指標

3
67 range()

建立一個包含一系列元素的陣列

3
68 reset()

將陣列的內部指標設定為其第一個元素

3
69 rsort()

按相反順序對陣列進行排序

3
70 shuffle()

隨機排列陣列

3
71 sizeof()

count() 的別名

3
72 sort()

對陣列進行排序

3
73 uasort()

使用使用者定義的函式對陣列進行排序並保持索引關聯

3
74 uksort()

使用使用者定義的函式按鍵對陣列進行排序

3
75 usort()

使用使用者定義的函式按值對陣列進行排序

3

PHP陣列常量

序號 常量 & 說明
1

CASE_LOWER

與array_change_key_case()一起使用,將陣列鍵轉換為小寫

2

CASE_UPPER

與array_change_key_case()一起使用,將陣列鍵轉換為大寫

3

SORT_ASC

與array_multisort()一起使用,按升序排序

4

SORT_DESC

與array_multisort()一起使用,按降序排序

5

SORT_REGULAR

用於正常比較專案

6

SORT_NUMERIC

用於按數值比較專案

7

SORT_STRING

用於將專案作為字串進行比較

8

SORT_LOCALE_STRING

用於根據當前區域設定將專案作為字串進行比較

9

COUNT_NORMAL

10

COUNT_RECURSIVE

11

EXTR_OVERWRITE

12

EXTR_SKIP

13

EXTR_PREFIX_SAME

14

EXTR_PREFIX_ALL

15

EXTR_PREFIX_INVALID

16

EXTR_PREFIX_IF_EXISTS

17

EXTR_IF_EXISTS

18

EXTR_REFS

PHP 常量陣列

在PHP 5.6版本之前,無法宣告常量陣列。從PHP 5.6版本開始,可以使用“const”關鍵字宣告常量陣列。從PHP 7版本開始,也可以使用define()函式建立常量陣列。

常量陣列是在建立後無法修改的陣列。與普通陣列不同,它的識別符號不以“$”符號開頭。

宣告常量陣列的舊語法為:

const ARR = array(val1, val2, val3);

示例

<?php
   const FRUITS = array(
      "Watermelon", 
      "Strawberries",
      "Pomegranate",
      "Blackberry",
   );
   var_dump(FRUITS);
?>

它將產生以下輸出

array(4) {
   [0]=>
   string(10) "Watermelon"
   [1]=>
   string(12) "Strawberries"
   [2]=>
   string(11) "Pomegranate"
   [3]=>
   string(10) "Blackberry"
}

您也可以使用傳統的方括號語法在PHP中宣告常量陣列:

const FRUITS = [
   "Watermelon", 
   "Strawberries",
   "Pomegranate",
   "Blackberry",
];

示例

無法修改常量陣列中的任何元素。因此,以下程式碼會丟擲致命錯誤:

<?php
   const FRUITS = [
      "Watermelon", 
      "Strawberries",
      "Pomegranate",
      "Blackberry",
   ];
   FRUITS[1] = "Mango";
?>

它將產生以下輸出

PHP Fatal error:  Cannot use temporary expression in write context

PHP 7及更高版本中的常量陣列

較新版本的PHP允許您使用define()函式宣告常量陣列。

<?php
   define ('FRUITS',  [
      "Watermelon", 
      "Strawberries",
      "Pomegranate",
      "Blackberry",
   ]);
   print_r(FRUITS);
?>

它將產生以下輸出

Array
(
   [0] => Watermelon
   [1] => Strawberries
   [2] => Pomegranate
   [3] => Blackberry
)

您也可以在這裡使用array()函式宣告常量陣列。

define ('FRUITS',  array(
   "Watermelon", 
   "Strawberries",
   "Pomegranate",
   "Blackberry",
));

示例

也可以宣告關聯常量陣列。以下是一個示例:

<?php
   define ('CAPITALS',  array(
      "Maharashtra" => "Mumbai",
      "Telangana" => "Hyderabad",
      "Gujarat" => "Gandhinagar",
      "Bihar" => "Patna"
   ));
   print_r(CAPITALS);
?>

它將產生以下輸出

Array
(
   [Maharashtra] => Mumbai
   [Telangana] => Hyderabad
   [Gujarat] => Gandhinagar
   [Bihar] => Patna
)

PHP 函式

與大多數程式語言一樣,PHP中的函式是一塊組織良好的可重用程式碼塊,用於執行單個相關的操作。函式為您的應用程式提供更好的模組化和高度的程式碼重用性。

PHP透過定義獨立的可重用函式塊來安排處理邏輯,從而支援結構化程式設計方法。這種方法的主要優點是程式碼變得易於理解、開發和維護。

下圖顯示了工資計算過程如何被逐步分解成獨立且可重用的函式。

PHP Functions

函式型別

您已經看到了許多函式,例如fopen()fread()等。它們是內建函式,但PHP也允許您建立自己的函式。PHP中有兩種型別的函式:

  • 內建函式 - PHP的標準庫包含大量用於字串處理、檔案IO、數學計算等的內建函式。

  • 使用者定義函式 - 您也可以建立使用者定義函式,以滿足程式設計邏輯的要求。

可以透過傳遞所需資料(稱為引數自變數)從任何其他函式呼叫函式。被呼叫的函式將其結果返回給呼叫環境。

您應該清楚以下兩部分:

  • 建立PHP函式

  • 呼叫PHP函式

事實上,您幾乎不需要建立自己的PHP函式,因為已經有超過1000個針對不同領域的內建庫函式,您只需要根據您的需求呼叫它們。

請參考PHP函式參考以獲取完整的實用函式集。

PHP中的使用者定義函式

建立自己的PHP函式非常容易。讓我們從一個簡單的示例開始,然後我們將詳細說明它是如何工作的。假設您想建立一個PHP函式,當您呼叫它時,它會在您的瀏覽器上顯示一條簡單的訊息。

示例

在這個例子中,我們建立一個名為writeMessage()的函式,然後呼叫它來列印一條簡單的訊息:

<?php

   /* Defining a PHP Function */
   function writeMessage() {
      echo "You are really a nice person, Have a nice time!";
   }

   /* Calling a PHP Function */
   writeMessage();
   
?>

它將產生以下輸出

You are really a nice person, Have a nice time!

在PHP中建立函式

現在讓我們詳細瞭解這個過程。第一步是編寫一個函式,然後您可以根據需要多次呼叫它。要建立一個新的函式,請使用function關鍵字,後跟您可能想要使用的函式名稱。在名稱前面,加上一個括號,它可以包含也可以不包含引數。後面是一個由花括號分隔的語句塊。此函式塊包含每次呼叫函式時要執行的語句。

定義函式的一般語法如下:

function foo($arg_1, $arg_2, $arg_n) {
   statements;
   return $retval;
}

如果函式旨在將某些結果返回給呼叫環境,則函式塊中應該有一個return語句作為最後一條語句。return語句不是必需的,即使沒有它,程式流程也會返回到呼叫者,儘管沒有攜帶任何值。

任何有效的PHP程式碼都可能出現在函式內部,甚至包括其他函式和類定義。函式的名稱必須遵循與形成變數名稱相同的規則。它應該以字母或下劃線開頭,後跟任意數量的字母、數字或下劃線。

這是一個簡單的PHP函式。每當呼叫時,它都會顯示訊息“Hello World”。

function sayhello() {
   echo "Hello World";
}

在PHP中呼叫函式

定義函式後,可以從PHP程式碼中的任何位置多次呼叫它。請注意,函式不會自動呼叫。要呼叫函式,請在語句中使用其名稱;函式名稱後跟一個分號。

<?php
   # define a function
   function sayhello(){
      echo "Hello World";
   }
   # calling the function
   sayhello();
?>

它將產生以下輸出

Hello World

假設上述指令碼“hello.php”位於PHP伺服器的文件根目錄下,開啟瀏覽器並輸入URL為https:///hello.php。你應該會在瀏覽器視窗中看到“Hello World”訊息。

在這個例子中,函式的定義沒有引數也沒有返回值。在接下來的章節中,我們將學習如何定義和傳遞引數,以及如何使函式返回一些值。此外,還將詳細解釋PHP函式的一些高階特性,例如遞迴函式、按值呼叫函式與按引用呼叫函式等。

PHP 函式引數

PHP中的函式可以定義為接受一個或多個引數。函式引數是在定義函式時,函式名前括號內用逗號分隔的表示式列表。引數可以是任何標量型別(數字、字串或布林值)、陣列、物件,甚至是另一個函式。

function foo($arg_1, $arg_2, $arg_n) {
   statements;
   return $retval;
}

引數充當在函式體內部處理的變數。因此,它們遵循與任何普通變數相同的命名約定,即它們應該以“$”開頭,並且可以包含字母、數字和下劃線。

注意 - 對可以定義的引數數量沒有限制。

當需要呼叫一個帶引數的函式時,你必須確保傳遞給它的值的數量與函式定義中引數的數量相同。

foo(val1, val2, val_n);

一個定義了引數的函式可以產生一個動態變化的結果,這取決於傳遞的值。

示例

下面的程式碼包含了帶有兩個引數的addition()函式的定義,並顯示了這兩個數的和。執行時輸出取決於傳遞給函式的兩個值。

<?php
   function addition($first, $second) {
      $result = $first+$second;
      echo "First number: $first \n";
      echo "Second number: $second \n"; 
      echo "Addition: $result";
   }

   addition(10, 20);

   $x=100;
   $y=200;
   addition($x, $y);
?>

它將產生以下輸出

First number: 10 
Second number: 20 
Addition: 30 
First number: 100 
Second number: 200 
Addition: 300

形式引數和實際引數

有時術語引數(argument) 用於指代形參(parameter)。實際上,這兩個術語有一定的區別。

  • 形參是指在函式定義中使用的變數,而實參是指呼叫函式時傳遞給函式的值。

  • 實參可以是字面量、變數或表示式。

  • 函式定義中的形參也經常被稱為形式引數,而傳遞的值被稱為實際引數

  • 形式引數和實際引數的名稱不必相同。實際引數的值按照從左到右的順序賦值給對應的形式引數。

  • 函式中定義的形式引數的數量和傳遞的實際引數的數量應該相同。

示例

當實際引數的數量少於形式引數的數量時,PHP會引發ArgumentCountError錯誤。但是,如果實際引數的數量多於形式引數的數量,則多餘的實際引數將被忽略。

<?php
   function addition($first, $second) {
      $result = $first+$second;
      echo "First number: $first \n";
      echo "Second number: $second \n";
      echo "Addition: $result \n";
   }

   # Actual arguments more than formal arguments
   addition(10, 20, 30);

   # Actual arguments fewer than formal arguments
   $x=10;
   $y=20;
   addition($x);
?>

它將產生以下輸出

First number: 10 
Second number: 20 
Addition: 30 
PHP Fatal error:  Uncaught ArgumentCountError: Too few arguments
to function addition(), 1 passed in /home/cg/root/20048/main.php
on line 16 and exactly 2 expected in /home/cg/root/20048/main.php:2

引數型別不匹配

PHP是一種動態型別的語言,因此在將實際引數的值複製給形式引數時,它不強制執行型別檢查。但是,如果函式體內的任何語句試圖執行特定資料型別不支援的特定操作,PHP會引發異常。

在上面的addition()函式中,假設傳遞的是數值引數。如果傳遞字串引數,PHP不會有任何異議,但是執行加法的語句會遇到異常,因為"+"操作沒有為字串型別定義。

示例

請看以下示例:

<?php
   function addition($first, $second) {
      $result = $first+$second;
      echo "First number: $first \n";
      echo "Second number: $second \n";
      echo "Addition: $result";
   }

   # Actual arguments are strings
   $x="Hello";
   $y="World";
   addition($x, $y);
?>

它將產生以下輸出

PHP Fatal error:  Uncaught TypeError: Unsupported operand types: string + string in hello.php:5

但是,PHP是一種弱型別語言。它儘可能地嘗試將變數轉換為相容的型別。因此,如果傳遞的值之一是數字的字串表示,而第二個是數值變數,則PHP會將字串變數轉換為數值以執行加法運算。

示例

請看以下示例:

<?php
   function addition($first, $second) {
      $result = $first+$second;
      echo "First number: $first \n";
      echo "Second number: $second \n";
      echo "Addition: $result";
   }

   # Actual arguments are strings
   $x="10";
   $y=20;
   addition($x, $y);
?>

它將產生以下輸出

First number: 10 
Second number: 20 
Addition: 30

PHP - 按值呼叫

預設情況下,PHP使用“按值呼叫”機制將引數傳遞給函式。呼叫函式時,實際引數的值將被複制到函式定義的形式引數中。

在執行函式體期間,如果任何形式引數的值發生任何變化,則不會反映在實際引數中。

  • 實際引數 - 在函式呼叫中傳遞的引數。

  • 形式引數 - 在函式定義中宣告的引數。

示例

讓我們考慮一下下面程式碼中使用的函式 -

<?php  
   function  change_name($nm) {
      echo "Initially the name is $nm \n";
      $nm = $nm."_new";
      echo "This function changes the name to $nm \n";
   }

   $name = "John";
   echo "My name is $name \n";
   change_name($name);
   echo "My name is still $name";
?>

它將產生以下輸出

My name is John
Initially the name is John
This function changes the name to John_new
My name is still John

在這個例子中,change_name()函式將_new附加到傳遞給它的字串引數。但是,傳遞給它的變數的值在函式執行後保持不變。

實際上,形式引數充當函式的區域性變數。這樣的變數只能在其初始化的作用域內訪問。對於一個函式,其由花括號“{ }”標記的主體是其作用域。此作用域內的任何變數都無法被外部程式碼訪問。因此,對任何區域性變數的操作都不會影響外部世界。

“按值呼叫”方法適用於使用傳遞給它的值的函式。它執行某些計算並返回結果,而無需更改傳遞給它的引數的值。

注意 - 任何執行公式型別計算的函式都是按值呼叫的示例。

示例

請看以下示例:

<?php
   function addFunction($num1, $num2) {
      $sum = $num1 + $num2;
      return $sum;
   }
   $x = 10;
   $y = 20;
   $num = addFunction($x, $y);
   echo "Sum of the two numbers is : $num";
?>    

它將產生以下輸出

Sum of the two numbers is : 30  

示例

這是另一個按值傳遞引數呼叫函式的示例。該函式將接收到的數字加1,但這不會影響傳遞給它的變數。

<?php
   function increment($num) {
      echo "The initial value: $num \n";
      $num++;
      echo "This function increments the number by 1 to $num \n";
   }
   $x = 10;
   increment($x);
   echo "Number has not changed: $x";
?>

它將產生以下輸出

The initial value: 10
This function increments the number by 1 to 11
Number has not changed: 10

PHP還支援在呼叫函式時傳遞變數的引用。我們將在下一章討論它。

PHP 按引用傳遞

PHP預設使用“按值呼叫”機制將引數傳遞給函式。如果函式內的引數發生更改,則更改不會反映在函式外部。為了允許函式修改其引數,“按引用呼叫”機制必須被使用。

在PHP中,引用變數充當原始變數或宿主變數的“別名”,以便兩者都可以讀寫單個值。換句話說,兩個不同名稱的變數可以訪問相同的值,它們的行為就像它們是同一個變數一樣。

下面的PHP指令碼將有助於理解什麼是引用。這裡,$var是一個普通的字串變數。我們將$var1宣告為$var的引用,在後者後面附加“&”符號。

$var = "Hello";
$var1 = &$var;

當我們說$var1$var的別名或引用時,這意味著它的值發生任何變化也會改變$var的值,反之亦然。

示例

下面的例子演示了“按引用呼叫”如何在PHP中工作 -

<?php  
   $var = "Hello";
   $var1 = &$var;

   $var1 = "Hello World";
   echo "var=$var var1=$var1" . PHP_EOL;

   $var = "How are you?";
   echo "var=$var var1=$var1" . PHP_EOL;
?>

它將產生以下輸出

var=Hello World var1=Hello World
var=How are you? var1=How are you?

按引用呼叫PHP函式

要按引用呼叫函式,需要將形式引數名以“&”符號作為字首宣告。

function callref(&$arg1, &$arg2) {
   Statements;
}

函式的呼叫與“按值呼叫”方法一樣。

callref($x, $y);

當函式被呼叫時,$arg1成為$x的引用,$arg2成為$y的引用。

如果在函式體內部,$arg1$arg2(或兩者)的值發生變化,它也會導致$x$y的值發生變化。

示例

讓我們看下面的例子 -

<?php  
   function  change_name(&$nm) {
      echo "Initially the name is $nm" . PHP_EOL;
      $nm = $nm."_new";
      echo "This function changes the name to $nm" . PHP_EOL;
   }

   $name = "John";
   echo "My name is $name" . PHP_EOL;
   change_name($name);
   echo "My name now is $name" . PHP_EOL;
?>

變數$name傳遞給函式change_name()。引用變數&$nm成為其引用變數。$nm的任何變化都會反映在函式外部的$name中。

它將產生以下輸出

My name is John
Initially the name is John
This function changes the name to John_new
My name now is John_new

交換兩個變數

在下面的PHP程式碼中,我們透過按值傳遞引數來呼叫函式。該函式試圖交換它們的值。

在函式內部,它們的值發生了變化,但是這個交換在函式執行後並沒有反映在實際引數中。

當透過按引用傳遞引數呼叫相同的函式時,交換效果也會反映在實際引數中。

<?php  
   function  swap_value($a, $b) {
      echo "Initial values a = $a b = $b \n";
      $c = $a; $a = $b; $b = $c;
      echo "Swapped values a = $a b = $b \n";
   }

   $x = 10; $y =20;
   echo "Actual arguments x = $x y = $y \n\n";

   swap_value($x, $y);
   echo "Actual arguments do not change after the function: \n";
   echo "x = $x y = $y \n\n";

   function  swap_ref(&$a, &$b) {
      echo "Initial values a = $a b = $b \n";
      $c = $a; $a = $b; $b = $c;
      echo "Swapped values a = $a b = $b \n";
   }

   swap_ref($x, $y);
   echo "Actual arguments get changed after the function: \n";
   echo "x = $x y = $y";
?>

它將產生以下輸出

Actual arguments x = 10 y = 20 

Initial values a = 10 b = 20 
Swapped values a = 20 b = 10 
Actual arguments do not change after the function: 
x = 10 y = 20 

Initial values a = 10 b = 20 
Swapped values a = 20 b = 10 
Actual arguments get changed after the function: 
x = 20 y = 10

按引用返回

就像PHP中的函式可以按引用接受引數一樣,它也可以返回引用。要定義一個返回引用的函式,請在函式名前新增“&”符號。

示例

下面的程式碼顯示了一個返回引用的函式的示例。它返回$x,它是myfunction()內部的區域性靜態變數。由於“&”符號加在其前面,$a(儲存返回值的變數)成為&x的引用。因此,$a的任何更改也會更改$x的值。

<?php
   function &myfunction(){
      static $x=10;
      echo "x Inside function: $x \n";
      return $x;
   }

   $a=&myfunction(); 
   echo "Returned by Reference: $a \n";
   $a=$a+10; 
   $a=&myfunction();
?>

它將產生以下輸出

x Inside function: 10 
Returned by Reference: 10 
x Inside function: 20

PHP 預設引數

與大多數支援指令式程式設計的語言一樣,PHP中的函式可能有一個或多個具有預設值的引數。因此,這樣的函式可以在不向其傳遞任何值的情況下被呼叫。如果沒有要傳遞的值,則該函式將使用其預設值進行處理。如果函式呼叫提供了一個值,則預設值將被覆蓋。

function fun($arg1 = val1, $arg2 = val2) {
   Statements;
}

這樣的函式可以以不同的方式呼叫 -

fun();			# Function will use defaults for both arguments
fun($x);		# Function passes $x to arg1 and uses default for arg2
fun($x, $y);	# Both arguments use the values passed

示例 1

在這裡,我們定義了一個名為greeting()的函式,它有兩個引數,兩者都具有string作為其預設值。我們透過傳遞一個字串、兩個字串以及沒有任何引數來呼叫它。

<?php  
   function  greeting($arg1="Hello", $arg2="world") {
      echo $arg1 . " ". $arg2 . PHP_EOL;
   }

   greeting();
   greeting("Thank you");
   greeting("Welcome", "back");
   greeting("PHP");
?>

它將產生以下輸出

Hello world
Thank you world
Welcome back
PHP world

示例 2

你可以定義一個函式,其中只有一部分引數具有預設值,而其他引數必須傳遞值。

<?php  
   function  greeting($arg1, $arg2="World") {
      echo $arg1 . " ". $arg2 . PHP_EOL;
   }

   # greeting(); ## This will raise ArgumentCountError
   greeting("Thank you");
   greeting("Welcome", "back");
?>

它將產生以下輸出

Thank you World
Welcome back

第一次呼叫(無引數)會引發ArgumentCountError,因為你必須為第一個引數傳遞值。如果只傳遞一個值,它將被列表中的第一個引數使用。

但是,如果你在沒有預設值的引數之前宣告具有default的引數,則只有在為兩者都傳遞值的情況下才能呼叫該函式。你不能出現第一個引數使用預設值,而第二個使用傳遞的值的情況。

greeting()函式現在有帶預設值的$arg1和沒有任何預設值的$arg2

function  greeting($arg1="Hello", $arg2) {
   echo $arg1 . " ". $arg2 . PHP_EOL;
}

如果你傳遞一個字串“PHP” -

greeting("PHP");

並希望將結果列印為“Hello PHP”,則會顯示以下錯誤訊息。

PHP Fatal error: Uncaught ArgumentCountError: Too few arguments to function 
greeting(), 1 passed in hello.php on line 10 and exactly 2 expected

示例 3

讓我們定義一個名為percent()的函式,該函式計算三門科目成績的百分比。

假設每門科目的分數都是滿分100分,則函式定義中的$total引數的預設值為300。

<?php
   function  percent($p, $c, $m, $ttl=300) {
      $per = ($p+$c+$m)*100/$ttl;
      echo "Marks obtained: \n";
      echo "Physics = $p Chemistry = $c Maths = $m \n";
      echo "Percentage = $per \n";
   }
   percent(50, 60, 70);
?>

它將產生以下輸出

Marks obtained: 
Physics = 50 Chemistry = 60 Maths = 70 
Percentage = 60

但是,如果每門科目的最高分是50分,那麼你必須向函式傳遞第四個值,否則百分比將根據300而不是150計算。

<?php
   function  percent($p, $c, $m, $ttl=300) {
      $per = ($p+$c+$m)*100/$ttl;
      echo "Marks obtained: \n";
      echo "Physics = $p Chemistry = $c Maths = $m \n";
      echo "Percentage = $per \n";
   }
   percent(30, 35, 40, 150);
?>

它將產生以下輸出

Marks obtained: 
Physics = 30 Chemistry = 35 Maths = 40 
Percentage = 70

PHP 具名引數

命名引數的功能是在PHP 8.0版本中引入的。它是現有機制的擴充套件,該機制在呼叫時將位置引數傳遞給函式。

預設情況下,傳遞的引數的值將複製到相同位置的相應形式引數。PHP的命名引數功能使得可以根據引數名稱而不是位置傳遞值。

如果我們定義如下函式 -

function myfunction($x, $y) {
   statement1;
   statement2;
   . . .
}

並呼叫它為 -

myfunction(10, 20);

在這種情況下,值按照宣告的順序傳遞給變數“x”和“y”。這意味著,第一個值傳遞給第一個引數,第二個值傳遞給第二個引數,依此類推。“x”和“y”是位置引數。

要按命名引數傳遞值,請指定要將值傳遞到的引數名稱。引數的名稱是形式引數的名稱,沒有“$”符號。要傳遞的值放在“:”符號的前面。

myfunction(x:10, y:20);

示例

以下程式碼演示瞭如何在PHP中使用命名引數 -

<?php  
   function  myfunction($x, $y) {
      echo "x = $x  y = $y";
   }

   myfunction(x:10, y:20);
?>

它將產生以下輸出

x = 10  y = 20

使用命名引數可以按任何順序傳遞值,而不必按照函式定義中宣告引數的順序傳遞。我們可以像下面這樣呼叫myfunction(),它將產生相同的結果。

myfunction(y:20, x:10);

有了這個特性,引數就變得與順序無關並且具有自文件性。它還可以任意跳過具有預設值的引數。

將命名引數與位置引數組合

命名引數可以與位置引數組合,條件是命名引數必須放在位置引數之後。

示例

<?php  
   function  myfunction($x, $y, $z) {
      echo "x = $x  y = $y  z = $z";
   }
   myfunction(10, z:20, y:30);
?>

它將產生以下輸出

x = 10  y = 30  z = 20

但是,如果你嘗試將$z視為位置引數,

myfunction(x:10, y:20, 30);

在這種情況下,PHP會遇到以下錯誤 -

PHP Fatal error:  Cannot use positional argument after 
named argument in hello.php on line 7

從陣列中傳遞命名引數

PHP 8.1.0 還引入了另一個特性,允許在解包引數後使用命名引數。無需為每個引數單獨提供值,可以使用“...”(三個點)在陣列前將陣列中的值解包到相應的引數中。

示例

<?php  
   function  myfunction($x, $y, $z=30) {
      echo "x = $x  y = $y  z = $z";
   }
   myfunction(...[10, 20], z:30);
?>

它將產生以下輸出

x = 10  y = 20  z = 30

請注意,多次傳遞相同的引數會導致如下異常:

myfunction(x:10, z:20, x:20);

錯誤

PHP Fatal error:  Uncaught Error: Named parameter $x 
overwrites previous argument in hello.php:7

PHP 可變引數

在 PHP 中,可以編寫一個函式,該函式能夠接受元素數量可變的引數列表。要宣告可變引數列表,引數名前要加上“...”(三個點)符號。傳遞的值將收集到一個數組中,陣列名與引數名相同。

function myfunction(...$arg) {
   Statement1;
   Statement2;
}

要呼叫此類函式,請在括號中放入任意數量用逗號分隔的值。

myfunction(v1, v2, v3, . . . , vn);

函式中宣告的形式引數是所有傳遞值的一個數組。我們可以使用任何合適的內建陣列函式來執行此過程。

示例

在下面的示例中,使用者定義的函式myfunction()能夠接收可變數量的值並計算它們的平均值。

<?php  
   function  myfunction(...$numbers) {
      $avg = array_sum($numbers)/count($numbers);
      return $avg;
   }
   $avg = myfunction(5, 12, 9, 23, 8);
   echo "average = $avg";
?>

它將產生以下輸出

average = 11.4

嘗試更改傳遞陣列的大小並再次執行程式。

您可以使用foreach迴圈遍歷函式內的陣列。函式在可變長度引數之前可以有任何位置引數。從接收到的值中,將首先填充位置引數,其餘引數將複製到陣列中。

示例

<?php
   function myfunction($x, ...$numbers) {
      echo "First number: $x" . PHP_EOL;
      echo "Remaining numbers: ";
      foreach ($numbers as $n) {
         echo "$n  ";
      }
   }
   myfunction(5, 12, 9, 23, 8, 41);
?>

它將產生以下輸出

First number: 5
Remaining numbers: 12  9  23  8  41

可變引數函式

即使沒有“...”語法,也可以處理傳遞給函式的可變數量的引數。PHP 具有內建函式,如 func_num_args()、func_get_arg() 和 func_get_args(),這些函式可以獲得類似的結果。

  • func_num_args():返回傳遞給函式的引數個數。

  • func_get_arg():返回引數列表中的一個專案。

  • func_get_args():返回包含函式引數列表的陣列。

示例

上面的可變引數示例可以使用這些函式改寫如下:

<?php
   function myfunction() {
      $sum = 0;
      foreach (func_get_args() as $n) {
         $sum += $n;
      }
      return $sum;
   }
   echo myfunction(5, 12, 9, 23, 8, 41);
?>

它將產生以下輸出

98

示例

此程式列印傳遞給函式的所有數字:

<?php
   function myfunction() {
      $len = func_num_args();
      echo "Numbers : ";
      $i=0;
      for ($i=0; $i<$len; $i++)
      echo func_get_arg($i) . " ";
   }
   myfunction(5, 12, 9, 23, 8, 41);
?>

它將產生以下輸出

Numbers : 5 12 9 23 8 41

PHP 返回值

PHP 函式可以在其函式體的最後一個語句中使用可選的 return 語句。大多數 PHP 內建函式都會返回某個值。例如,strlen() 函式返回字串的長度。類似地,使用者定義的函式也可以返回某個值。

函式是一個獨立的、完整的和可重用的語句塊。呼叫時,它執行某個任務並將程式控制權返回到呼叫它的位置,即使沒有使用 return 語句也是如此。return 語句允許它將值和控制權一起返回到呼叫環境。

function foo($arg_1, $arg_2) {
   statements;
   return $retval;
}

函式可以返回任何型別的資料,包括標量變數、陣列和物件。沒有表示式在前的 return 關鍵字返回 null,這等效於函式根本沒有返回值。

函式返回的值可以儲存在變數中,可以放在表示式中,或者如果出現在 print 或 echo 中,則顯示在輸出中。

$res = foo($x, $y);

它允許在程式中進一步使用函式的返回值。

示例

讓我們修改上一章中的 addition() 函式,使其包含一個return語句以返回加法的結果。

<?php
   function addition($first, $second) {
      $result = $first+$second;
      return $result;
   }

   $x=10;
   $y=20;
   $z = addition($x, $y);
   echo "First number: $x Second number: $y Addition: $z". PHP_EOL;
?>

它將產生以下輸出

First number: 10 Second number: 20 Addition: 30

PHP 中的函式可以有任意數量的引數,但只能返回一個值。函式一旦遇到第一個return語句,就會立即返回到呼叫環境,放棄函式體中其餘的語句。

示例

如果嘗試在return語句中包含多個值,則會遇到 PHP 解析錯誤,如下所示:

<?php
   function raiseto($x) {
      $sqr =  $x**2;
      $cub =  $x**3;
      return $sqr, $cub;
   }
   $a = 5;
   $val = raiseto($a);
?>

它將產生以下輸出

PHP Parse error: syntax error, unexpected token ",", expecting ";" 

條件返回

您可以根據不同的條件語句執行多個return語句。

示例

在下面的程式中,raiseto()函式返回數字的平方或立方,取決於索引引數是 2 還是 3。

<?php
   function raiseto($x, $i) {
      if ($i == 2) {
         return $x**2;
      } elseif ($i==3) {
         return $x**3;
      }
   }
   $a = 5;
   $b = 2;
   $val = raiseto($a, $b);
   echo "$a raised to $b = $val" . PHP_EOL;

   $x = 7;
   $y = 3;
   echo "$x raised to $y = " . raiseto($x, $y) . PHP_EOL;
?>

它將產生以下輸出

5 raised to 2 = 25
7 raised to 3 = 343

將多個值作為陣列返回

PHP 中的函式只能返回單個值。但是,此單個值可以是包含多個值的陣列。我們可以利用此特性同時返回數字的平方和立方。

示例

請看以下示例:

<?php
   function raiseto($x){
      $sqr =  $x**2;
      $cub =  $x**3;
      $ret = ["sqr" => $sqr, "cub" => $cub];
      return $ret;
   }
   $a = 5;
   $val = raiseto($a);
   echo "Square of $a: " . $val["sqr"] . PHP_EOL;
   echo "Cube of $a: " . $val["cub"] . PHP_EOL;
?>

它將產生以下輸出

Square of 5: 25
Cube of 5: 125

PHP 傳遞函式

除了標量型別、陣列和物件之外,還可以將函式作為引數傳遞給 PHP 中的函式。如果定義的函式接受另一個函式作為引數,則將在函式內部呼叫傳遞的函式。PHP 的標準庫具有一些此型別的內建函式,其中一個要傳遞的引數是函式,該函式可以是另一個內建函式,甚至是使用者定義的函式。

array_map

array_map() 是內建函式之一。此函式的第一個引數是回撥函式。可能還有其他引數作為其他陣列。回撥函式將應用於所有陣列元素。

array_map(?callable $callback, array $array, array ...$arrays): array

array_map() 函式返回一個數組。它包含將回調函式應用於作為其他引數傳遞的陣列的對應元素的結果。

示例

在下面的示例中,我們有一個 square() 函式,它計算傳遞給它的數字的平方。此函式又用作 array_map() 函式的引數,以及另一個數字陣列。每個數字依次傳遞給 squares() 函式。結果陣列是平方列表。

<?php
   function square($number) {
      return $number * $number;
   }

   $arr = [1, 2, 3, 4, 5];
   $squares = array_map('square', $arr);
   var_dump($squares);
?>

它將產生以下輸出

array(5) {
   [0]=>
   int(1)
   [1]=>
   int(4)
   [2]=>
   int(9)
   [3]=>
   int(16)
   [4]=>
   int(25)
}

call_user_func

將函式傳遞給另一個函式的另一個示例是 call_user_func()。顧名思義,它呼叫另一個使用者定義的回撥函式,並將其他引數傳遞給回撥函式。

call_user_func(callable $callback, mixed ...$args): mixed

示例

在下面的示例中,square() 函式被重複呼叫,將陣列中的每個數字傳遞給它。

<?php
   function square($number) {
      return $number * $number;
   }
   $arr = [1, 2, 3, 4, 5];
   foreach($arr as $a) {
      echo "square of $a:" . call_user_func("square", $a). PHP_EOL;
   }
?>

它將產生以下輸出

square of 1:1
square of 2:4
square of 3:9
square of 4:16
square of 5:25

usort

作為傳遞函式的另一個示例,我們來看一下 usort() 函式。

usort(array &$array, callable $callback): true

第一個引數是陣列。陣列根據回撥函式排序,回撥函式是第二個引數。

回撥引數是一個比較函式,如果第一個引數分別小於、等於或大於第二個引數,則必須返回小於、等於或大於零的整數。

示例

這是一個示例。首先,我們有一個mysort()函式。它比較兩個數字,如果第一個數字小於、等於或大於第二個數字,則返回“-1”、“0”或“1”。

usort()的第一個引數是 mysort() 函式,第二個引數是陣列。首先,將前兩個數字傳遞給 mysort()。如果它返回 1,則交換它們。接下來,傳遞第二個和第三個數字,如果比較返回 1,則交換它們。該過程重複進行,以便陣列元素按升序排列。

<?php
   function mysort($a, $b) {
      if ($a == $b) {
         return 0;
      }
      return ($a < $b) ? -1 : 1;
   }

   $a = array(3, 2, 5, 6, 1);

   usort($a, "mysort");

   foreach ($a as $key => $value) {
      echo "$key: $value\n";
   }
?>

它將產生以下輸出

0: 1
1: 2
2: 3
3: 5
4: 6

將回調傳遞給使用者定義的函式

除了上述內建函式之外,您還可以定義自己的函式,該函式接受一個引數作為另一個函式。

在下面的示例中,我們有兩個函式 square() 和 cube(),它們分別返回給定數字的平方和立方。

接下來,是myfunction(),它的第一個引數用作變數函式,第二個引數傳遞給它。

因此,myfunction() 在內部呼叫 square() 或 cube() 以返回給定數字的平方或立方。

示例

<?php
   function myfunction($function, $number) {
      $result = $function($number);
      return $result;
   }

   function cube($number) {
      return $number ** 2;
   }

   function square($number) {
      return $number ** 3;
   }

   $x = 5;

   $cube = myfunction('cube', $x);
   $square = myfunction('square', $x);

   echo "Square of $x = $square" . PHP_EOL;
   echo "Cube of $x = $cube" . PHP_EOL;
?>

它將產生以下輸出

Square of 5 = 125
Cube of 5 = 25

PHP 遞迴函式

遞迴函式是這樣一種函式,它會呼叫自身,直到滿足某個條件。在 PHP 中,可以定義遞迴函式。

  • 當某個問題用自身來定義時,就會使用遞迴。

  • 有時,使用迭代方法解決問題可能會很繁瑣。遞迴方法為看似複雜的問題提供了一種非常簡潔的解決方案。

  • PHP 中的遞迴與 C 和 C++ 中的遞迴非常相似。

  • 遞迴函式尤其用於遍歷巢狀資料結構以及搜尋或排序演算法。

  • 二叉樹遍歷、堆排序和查詢最短路徑是一些使用遞迴的情況。

使用遞迴計算階乘

遞迴最流行的示例是階乘的計算。從數學上講,階乘定義為:

n! = n × (n-1)!

可以看出,我們使用階乘本身來定義階乘。因此,這是一個編寫遞迴函式的合適案例。

讓我們展開上述定義,計算 5 的階乘值。

5! = 5 × 4!
      5 × 4 × 3!
      5 × 4 × 3 × 2!
      5 × 4 × 3 ×  2 × 1!
      5 × 4 × 3 ×  2 × 1
   = 120

雖然我們可以使用迴圈執行此計算,但其遞迴函式會透過遞減數字直到達到 1 來連續呼叫它。

示例

以下是計算階乘的遞迴函式。

<?php
   function factorial ($n) {
      if ($n == 1) {
         echo $n . PHP_EOL;
         return 1;
      } else {
         echo "$n * ";
         return $n*factorial($n-1);
      }
   }
   echo "Factorial of 5 = " . factorial(5);
?>

它將產生以下輸出

5 * 4 * 3 * 2 * 1
Factorial of 5 = 120

使用遞迴進行二分查詢

讓我們再看一個示例,瞭解遞迴是如何工作的。手頭的問題是檢查給定數字是否存在於列表中。

雖然我們可以使用for迴圈並比較每個數字來對列表中的某個數字進行順序搜尋,但順序搜尋效率不高,尤其是在列表過大的情況下。在這裡,我們可以使用二分查詢演算法,該演算法檢查索引“high”是否大於索引“low”。根據“mid”變數中存在的值,再次呼叫函式來搜尋元素。

我們有一個按升序排列的數字列表。然後,我們找到列表的中點,並根據所需數字是否小於或大於中點處的數字,將檢查限制在中點的左側或右側。

下圖顯示了二分查詢的工作原理:

PHP Recursive Functions

示例

以下程式碼實現了遞迴二分搜尋技術:

<?php
   function bsearch($my_list, $low, $high, $elem) {
      if ($high >= $low) {
         $mid = intval(($high + $low)/2);

         if ($my_list[$mid] == $elem)
         return $mid;

         elseif ($my_list[$mid] > $elem)
         return bsearch($my_list, $low, $mid - 1, $elem);

         else
         return bsearch($my_list, $mid + 1, $high, $elem);
      }
      else
      return -1;
   }

   $list = [5,12,23, 45, 49, 67, 71, 77, 82];
   $num = 67;
   $result = bsearch($list,0,count($list)-1, $num);
   if ($result != -1)
   echo " Number $num found at index " . $result;
   else
   echo "Element not found!";
?>

它將產生以下輸出

Number 67 found at index 5

您可以檢查給定列表中存在的不同數字以及列表中不存在的數字的輸出。

PHP 型別提示

PHP 支援在宣告函式定義中的變數以及類中的屬性或例項變數時使用“型別提示”。PHP 被廣泛認為是一種弱型別語言。在 PHP 中,無需在為變數賦值之前宣告變數的型別。

PHP 解析器會盡最大努力將變數強制轉換為相容型別。因此,如果傳遞的值之一是數字的字串表示形式,而第二個是數字變數,則 PHP 會將字串變數強制轉換為數字以執行加法運算。

示例

請看以下示例:

<?php
   function addition($x, $y) {
      echo "First number: $x Second number: $y Addition: " . $x+$y;
   }
   $x="10";
   $y=20;
   addition($x, $y);
?>

它將產生以下輸出

First number: 10 Second number: 20 Addition: 30

但是,如果上面的示例中的$x是一個不包含有效數字表示的字串,則會遇到錯誤。

<?php
   function addition($x, $y) {
      echo "First number: $x Second number: $y Addition: " . $x+$y;
   }
   $x="Hello";
   $y=20;
   addition($x, $y);
?>

它將產生以下輸出

PHP Fatal error:  Uncaught TypeError: Unsupported operand types: string + int in hello.php:5

從 PHP 5.6 版本開始支援型別提示。這意味著您可以明確宣告程式碼中宣告的變數的預期型別。PHP 允許您對函式引數、返回值和類屬性進行型別提示。有了它,就可以編寫更健壯的程式碼了。

讓我們在上面的程式中的 addition 函式中加入型別提示:

function addition($x, $y) {
   echo "First number: $x Second number: $y Addition: " . $x+$y;
}

型別提示功能主要由 IDE(整合開發環境)使用,以提示使用者函式宣告中使用的引數的預期型別。

下圖顯示了 VS Code 編輯器在您鍵入時彈出的函式原型:

PHP Type Hints 1

如果滑鼠懸停在函式名稱上,則會顯示引數和返回值的型別宣告:

PHP Type Hints 2

請注意,僅僅在變數宣告中使用資料型別並不能防止引發不匹配型別異常,因為 PHP 是一種動態型別語言。換句話說,$x="10" 和 $y=20 仍然會將結果加起來為 30,而 $x="Hello" 會使解析器引發錯誤。

strict_types

可以使 PHP 對型別轉換施加更嚴格的規則,以便不會將“10”隱式轉換為 10。這可以透過在 declare() 語句中將 strict_types 指令設定為 1 來強制執行。declare() 語句必須是 PHP 程式碼中的第一個語句,緊跟在“<?php”標籤之後。

示例

<?php
   declare (strict_types=1);
   function addition(int $x, int $y) {
      echo "First number: $x Second number: $y Addition: " . $x+$y;
   }
   $x=10;
   $y=20;
   addition($x, $y);
?>

它將產生以下輸出

First number: 10 Second number: 20 Addition: 30

現在,如果將$x設定為“10”,則不會進行隱式轉換,從而導致以下錯誤:

PHP Fatal error:  Uncaught TypeError: addition(): Argument #1 ($x) must be of type int, string given

VS Code IDE 也指示了相同效果的錯誤:

PHP Type Hints 3

從 PHP 7 開始,型別提示支援已擴充套件到函式返回,以防止出現意外的返回值。您可以透過在引數列表後新增預期型別(在冒號 (:) 符號字首)來對返回值進行型別提示。

示例

讓我們為上面加法函式的返回值新增型別提示。

<?php
   declare (strict_types=1);
   function addition(int $x, int $y) : int {
      return $x+$y;
   }

   $x=10;
   $y=20;

   $result = addition($x, $y);
   echo "First number: $x Second number: $y Addition: " . $result;
?>

同樣,如果發現函式返回的值不是整數,IDE 甚至在執行之前就會指出原因。

PHP Type Hints 4

聯合型別

PHP 從 8.0 版本開始引入聯合型別。現在可以為單個宣告指定多個型別。資料型別用“|”符號分隔。

示例

在下面 addition() 函式的定義中,$x$y 引數可以是 intfloat 型別。

<?php
   declare (strict_types=1);
   function addition(int|float $x, int|float $y) : float {
      return $x+$y;
   }
   $x=10.55;
   $y=20;

   $result = addition($x, $y);
   echo "First number: $x Second number: $y Addition: " . $result;
?>

類中的型別提示

在 PHP 中,從 7.4 版本開始,可以在類屬性和方法的宣告中使用型別提示。

示例

在下面的示例中,類建構函式使用了型別提示。

<?php
   declare (strict_types=1);
   class Student {
      public $name;
      public $age;
      public function __construct(string $name, int $age) {
         $this->name = $name;
         $this->age = $age;
      }

      public function dispStudent() {
         echo "Name: $this->name Age: $this->age";
      }
   }
   $s1 = new Student("Amar", 21);
   $s1->dispStudent();
?>

也可以在類屬性的宣告中使用型別提示。

class Student {
   public string $name;
   public int $age;

   public function __construct($name, $age) {
      $this->name = $name;
      $this->age = $age;
   }

   public function dispStudent() {
      echo "Name: $this->name Age: $this->age";
   }
}

程式開發中最常見的錯誤是型別錯誤。型別提示功能有助於減少此類錯誤。

PHP 變數作用域

在 PHP 中,變數的作用域是指其定義的上下文以及可訪問的範圍。通常,一個簡單的順序 PHP 指令碼(沒有任何迴圈或函式等)只有一個作用域。在 "<?php" 和 "?>" 標籤內宣告的任何變數,從定義點開始都可以在整個程式中使用。

根據作用域,PHP 變數可以是以下三種類型之一:

主指令碼中的變數也可以提供給使用 includerequire 語句包含的任何其他指令碼。

示例

在下面的示例中,"test.php" 指令碼包含在主指令碼中。

main.php

<?php
   $var=100;
   include "test.php";
?>

test.php

<?php
   echo "value of \$var in test.php : " . $var;
?>

執行主指令碼時,將顯示以下輸出

value of $var in test.php : 100

但是,當指令碼具有使用者定義的函式時,內部的任何變數都具有區域性作用域。因此,在函式內部定義的變數無法在外部訪問。在函式外部(上方)定義的變數具有全域性作用域。

示例

請看以下示例:

<?php
   $var=100;   // global variable
   function myfunction() {
      $var1="Hello"; 	// local variable
      echo "var=$var  var1=$var1" . PHP_EOL;
   }
   myfunction();
   echo "var=$var  var1=$var1" . PHP_EOL; 
?>

它將產生以下輸出

var=  var1=Hello
var=100  var1=

PHP Warning:  Undefined variable $var in /home/cg/root/64504/main.php on line 5
PHP Warning:  Undefined variable $var1 in /home/cg/root/64504/main.php on line 8

注意,全域性變數不會自動在函式的區域性作用域中可用。同樣,函式內部的變數在外部也無法訪問。

"global" 關鍵字

要在函式的區域性作用域內訪問全域性變數,應使用"global"關鍵字顯式執行此操作。

示例

PHP 指令碼如下:

<?php
   $a=10; 
   $b=20;
   echo "Global variables before function call: a = $a b = $b" . PHP_EOL;
   function myfunction() {
      global $a, $b;
      $c=($a+$b)/2;
      echo "inside function a = $a b = $b c = $c" . PHP_EOL;
      $a=$a+10;
   }
   myfunction();
   echo "Variables after function call: a = $a b = $b c = $c";
?>

它將產生以下輸出

Global variables before function call: a = 10 b = 20
inside function a = 10 b = 20 c = 15
Variables after function call: a = 20 b = 20 c = 
PHP Warning:  Undefined variable $c in /home/cg/root/48499/main.php on line 12

現在可以在函式內處理全域性變數。此外,在函式內對全域性變數所做的任何更改都將反映在全域性名稱空間中。

$GLOBALS 陣列

PHP 將所有全域性變數儲存在一個名為 $GLOBALS 的關聯陣列中。變數的名稱和值構成鍵值對。

示例

在下面的 PHP 指令碼中,使用 $GLOBALS 陣列訪問全域性變數:

<?php
   $a=10; 
   $b=20;
   echo "Global variables before function call: a = $a b = $b" . PHP_EOL;

   function myfunction() {
      $c=($GLOBALS['a']+$GLOBALS['b'])/2;
      echo "c = $c" . PHP_EOL;
      $GLOBALS['a']+=10;
   }
   myfunction();
   echo "Variables after function call: a = $a b = $b c = $c";
?>

它將產生以下輸出

Global variables before function call: a = 10 b = 20
c = 15
PHP Warning:  Undefined variable $c in C:\xampp\htdocs\hello.php on line 12
Variables after function call: a = 20 b = 20 c =

靜態變數

使用 static 關鍵字定義的變數不會在每次呼叫函式時都進行初始化。此外,它保留上次呼叫的值。

示例

請看以下示例:

<?php
   function myfunction() {
      static $x=0;
      echo "x = $x" . PHP_EOL;
      $x++;
   }
   for ($i=1; $i<=3; $i++) {
      echo "call to function :$i : ";
      myfunction();
   }
?>

它將產生以下輸出

call to function :1 : x = 0
call to function :2 : x = 1
call to function :3 : x = 2

PHP 嚴格型別

PHP 被廣泛認為是一種弱型別語言。在 PHP 中,不需要在為變數賦值之前宣告其型別。PHP 解析器會盡最大可能將變數強制轉換為相容的型別。

例如,如果傳遞的值之一是數字的字串表示形式,而第二個是數值變數,則 PHP 會將字串變數強制轉換為數字以執行加法運算。

示例

請看以下示例:

<?php
   function addition($x, $y) {
      echo "First number: $x Second number: $y Addition: " . $x+$y;
   }

   $x="10";
   $y=20;
   addition($x, $y);
?>

它將產生以下輸出

First number: 10 Second number: 20 Addition: 30

但是,如果上面示例中的 $x 是一個不包含有效數字表示的字串,則會遇到錯誤。

<?php
   function addition($x, $y) {
      echo "First number: $x Second number: $y Addition: " . $x+$y;
   }
   $x="Hello";
   $y=20;
   addition($x, $y);
?>

它將產生以下輸出

PHP Fatal error:  Uncaught TypeError: Unsupported operand 
types: string + int in hello.php:5

型別提示

從 PHP 5.6 版本開始支援型別提示。這意味著您可以明確宣告程式碼中宣告的變數的預期型別。PHP 允許您對函式引數、返回值和類屬性進行型別提示。有了它,就可以編寫更健壯的程式碼了。

讓我們在上面的程式中的 addition 函式中加入型別提示:

function addition(int $x, int $y) {
   echo "First number: $x Second number: $y Addition: " . $x+$y;
}

請注意,僅僅在變數宣告中使用資料型別並不能防止引發不匹配型別異常,因為 PHP 是一種動態型別語言。換句話說,$x="10" 和 $y=20 仍然會將結果相加為 30,而 $x="Hello" 會導致解析器引發錯誤。

示例

<?php
   function addition($x, $y) {
      echo "First number: $x \n";
      echo "Second number: $y \n";
      echo "Addition: " . $x+$y . "\n\n";
   }

   $x=10;
   $y=20;
   addition($x, $y);

   $x="10";
   $y=20;
   addition($x, $y);

   $x="Hello";
   $y=20;
   addition($x, $y);
?>

它將產生以下輸出

First number: 10 
Second number: 20 
Addition: 30

First number: 10 
Second number: 20 
Addition: 30

First number: Hello 
Second number: 20
PHP Fatal error:  Uncaught TypeError: Unsupported operand 
types: string + int in hello.php:5

strict_types

可以透過將 strict_types 指令在 declare() 語句中設定為 1 來強制 PHP 對型別轉換實施更嚴格的規則,以便不會將 "10" 隱式轉換為 10。

declare() 語句必須是 PHP 程式碼中的第一條語句,緊跟在 "<?php" 標籤之後。

示例

請看以下示例:

<?php
   declare (strict_types=1);
   function addition(int $x, int $y) {
      echo "First number: $x Second number: $y Addition: " . $x+$y;
   }

   $x=10;
   $y=20;
   addition($x, $y);
?>

它將產生以下輸出

First number: 10 Second number: 20 Addition: 30

現在,如果將 $x 設定為 "10",則不會進行隱式轉換,從而導致以下錯誤

PHP Fatal error:  Uncaught TypeError: addition(): Argument #1 
($x) must be of type int, string given

從 PHP 7 開始,型別提示支援已擴充套件到函式返回,以防止出現意外的返回值。可以透過在引數列表後新增預期型別(以冒號 (:) 符號為字首)來提示返回型別。

示例

讓我們為下面的 division() 函式的返回值新增型別提示。

<?php
   declare (strict_types=1);
   function division(int $x, int $y) : int {
      return $x/$y;
   }

   $x=10;
   $y=20;
   $result = division($x, $y);
   echo "First number: $x Second number: $y Addition: " . $result;
?>

因為函式返回 0.5,它不是 int 型別(即函式返回值使用的型別提示),所以會顯示以下錯誤

Fatal error: Uncaught TypeError: division(): Return value must be 
of type int, float returned in hello.php:5

PHP 匿名函式

什麼是匿名函式?

PHP 允許定義匿名函式。通常,當我們在 PHP 中定義函式時,我們通常會為其提供一個名稱,該名稱用於在需要時呼叫函式。相反,匿名函式是在定義時沒有指定任何名稱的函式。此類函式也稱為閉包lambda 函式

有時,您可能只需要一個一次性使用的函式。匿名函式最常見的用途是建立內聯回撥函式

匿名函式使用 Closure 類實現。Closure 是一個匿名函式,它封閉在其定義的環境中。

定義匿名函式的語法如下:

$var=function ($arg1, $arg2) { return $val; };

請注意,在 function 關鍵字和左括號之間沒有函式名,並且函式定義之後有一個分號。這意味著匿名函式定義是表示式。當分配給變數時,可以使用變數的名稱稍後呼叫匿名函式。

示例

請看以下示例:

<?php
   $add = function ($a, $b) {
      return "a:$a b:$b addition: " . $a+$b; 
   };
   echo $add(5,10);
?>

它將產生以下輸出

a:5 b:10 addition: 15

匿名函式作為回撥

匿名函式通常用作回撥。回撥函式用作另一個函式的引數之一。匿名函式會動態執行,其返回值成為父函式的引數,父函式可以是內建函式或使用者定義函式。

示例

在此示例中,我們在 usort() 函式內使用匿名函式,這是一個內建函式,它使用使用者定義的比較函式按值對陣列進行排序。

<?php
   $arr = [10,3,70,21,54];
   usort ($arr, function ($x , $y) {
      return $x > $y;
   });
   foreach ($arr as $x){
      echo $x . "\n";
   }
?>

它將產生以下輸出

3
10
21
54
70

示例

以下示例使用匿名函式計算陣列中連續數字後的累積和。在這裡,我們使用 array_walk() 函式。此函式將使用者定義的函式應用於陣列中的每個元素。

<?php
   $arr=array(1,2,3,4,5);
   array_walk($arr, function($n){
      $s=0;
      for($i=1;$i<=$n;$i++){
         $s+=$i;
      }
      echo "Number: $n Sum: $s". PHP_EOL;
   });
?>

它將產生以下輸出

Number: 1 Sum: 1
Number: 2 Sum: 3
Number: 3 Sum: 6
Number: 4 Sum: 10
Number: 5 Sum: 15

匿名函式作為閉包

閉包也是一個匿名函式,它可以在"use"關鍵字的幫助下訪問其作用域之外的變數。

示例

請看下面的例子:

<?php
   $maxmarks=300;
   $percent=function ($marks) use ($maxmarks) {
      return $marks*100/$maxmarks;
   };
   $m = 250;
   echo "Marks = $m Percentage = ". $percent($m);
?>

它將產生以下輸出

Marks = 250 Percentage = 83.333333333333

PHP 箭頭函式

箭頭函式是在 PHP 7.4 版本中引入的。箭頭函式提供了一種更簡單、更簡潔的語法來編寫匿名函式。使用 PHP 7.4,引入了關鍵字"fn"來定義箭頭函式,而不是傳統上使用"function"關鍵字。

fn (argument_list) => expr
  • "=>" 符號之後只有一個表示式,其值為箭頭函式的返回值。

  • 箭頭函式沒有顯式的 return 語句。

  • 與匿名函式一樣,箭頭函式被分配給一個變數以便呼叫它。

示例

以下示例演示如何在 PHP 中使用箭頭函式:

<?php
   $add = fn ($a, $b) => $a + $b;

   $x = 10;
   $y = 20; 
   echo " x: $x y: $y Addition: " . $add($x, $y);
?>

它將產生以下輸出

x: 10 y: 20 Addition: 30

使用箭頭函式作為回撥函式

我們也可以使用箭頭函式作為回撥函式。回撥函式用作另一個函式的引數之一。箭頭函式會動態執行,"=>" 之後表示式的值成為父函式的引數,父函式可以是內建函式或使用者定義函式。

示例

在此示例中,我們在 usort() 函式內使用箭頭函式,這是一個內建函式,它使用使用者定義的比較函式按值對陣列進行排序。

<?php
   $arr = [10,3,70,21,54];
   usort ($arr, fn ($x , $y) => $x > $y);

   foreach ($arr as $x){
      echo $x . "\n";
   }
?>

它將產生以下輸出

3
10
21
54
70

訪問父作用域中的變數

箭頭函式可以自動訪問父作用域中的變數。與匿名函式不同,不需要 "use" 關鍵字即可充當閉包。當表示式中使用的變數在父作用域中定義時,它將被隱式按值捕獲。

<?php
   $maxmarks=300;
   $percent=fn ($marks) => $marks*100/$maxmarks;

   $m = 250;
   echo "Marks = $m Percentage = ". $percent($m);
?>

它將產生以下輸出

Marks = 250 Percentage = 83.333333333333

示例

箭頭函式會自動按值捕獲變數,即使巢狀也是如此。

在下面的示例中,箭頭函式在另一個箭頭函式的表示式部分中定義。

<?php
   $z = 1;
   $fn = fn($x) => fn($y) => $x * $y + $z;
   $x = 5;
   $y = 10; 
   echo "x:$x y:$y \n";
   echo "Result of nested arrow functions: " . ($fn($x)($y));
?>

它將產生以下輸出

x:5 y:10 
Result of nested arrow functions: 51

與匿名函式一樣,箭頭函式語法允許任意函式簽名,包括引數和返回型別、預設值、可變引數,以及按引用傳遞和返回。

PHP 變數處理函式

PHP 變數處理函式是內建的 PHP 庫函式,使我們能夠以各種方式操作和測試 php 變數。

安裝

使用 PHP 變數處理函式不需要安裝;它們是 PHP 核心的一部分,並隨標準 PHP 安裝一起提供。

執行時配置

此擴充套件程式在php.ini中沒有定義任何配置指令。

PHP 變數處理函式

下表列出了所有與 PHP 變數處理相關的函式。此處“版本”列指示支援該函式的 PHP 最早版本。

序號 函式及描述 版本
1 boolval()

函式返回已定義變數的布林值,即返回 TRUE 或 FALSE。

5.5.0
2 debug_zval_dump()

函式用於將內部 zend 值的字串表示形式轉儲到輸出。

4.2.0
3 doubleval()

函式用於返回已定義變數的浮點值。

4, 5, 7, 8
4 empty()

函式用於檢查已定義變數的值是否為空。

4, 5, 7, 8
5 floatval()

函式用於返回已定義變數的浮點值。

4.2.0, 5, 7, 8
6 get_defined_vars()

函式用於將所有已定義變數作為陣列返回。

4.0.4, 5, 7, 8
7 get_resource_id()

函式用於返回給定資源的整數識別符號。

8
8 get_resource_type()

函式返回已定義變數資源的型別。

4.0.2, 5, 7, 8
9 gettype()

函式返回已定義變數的型別。

4, 5, 7, 8
10 intval()

函式返回已定義變數的整數值。

4, 5, 7, 8
11 is_array()

函式用於檢查已定義變數是否為陣列。

4, 5, 7, 8
12 is_bool()

函式用於檢查已定義變數是否為布林值,即返回 true 或 false 值。

4, 5, 7, 8
13 is_callable()

函式用於檢查變數中的資料是否可以作為函式呼叫。

4.0.6, 5, 7, 8
14 is_countable()

函式用於檢查變數中的資料是否可計數。

7.3.0, 8
15 is_double()

函式用於檢查已定義變數的型別是否為浮點型。

4, 5, 7, 8
16 is_float()

該函式用於檢查定義的變數是否為浮點數。

4, 5, 7, 8
17 is_int()

該函式用於檢查定義的變數是否為整數型別。

4, 5, 7, 8
18 is_integer()

該函式用於檢查定義的變數是否為整數。

4, 5, 7, 8
19 is_iterable()

該函式用於檢查變數中的資料是否為可迭代值。

7.1.0, 8
20 is_long()

該函式用於檢查變數是否為整數型別。

4, 5, 7, 8
21 is_null()

該函式檢查變數是否具有NULL值。

4.0.4, 5, 7, 8
22 is_numeric()

該函式用於檢查定義的變數是否為數字或數字字串。

4, 5, 7, 8
23 is_object()

該函式用於檢查變數是否為物件。

4, 5, 7, 8
24 is_real()

該函式用於檢查定義的變數是否為浮點數。

4, 5, 7, 8
25 is_resource()

該函式用於檢查定義的變數是否為資源。

4, 5, 7, 8
26 is_scalar()

該函式用於檢查定義的變數是否為標量。

4.0.5, 5, 7, 8
27 is_string()

該函式用於檢查定義的變數是否為字串型別。

4, 5, 7, 8
28 isset()

該函式用於檢查變數是否已宣告並已設定值。

4, 5, 7, 8
29 print_r()

該函式用於以可讀的格式顯示或列印變數的資料。

4, 5, 7, 8
30 serialize()

該函式用於將變數的資料轉換為可儲存的表示形式,以便資料可以儲存在檔案或記憶體緩衝區中。

4, 5, 7, 8
31 settype()

該函式用於將變數設定為特定型別。

4, 5, 7, 8
32 strval()

該函式用於返回變數的字串值。

4, 5, 7, 8
33 unserialize()

該函式用於反序列化變數的資料,即該函式返回序列化變數的實際資料。

4, 5, 7, 8
34 unset()

該函式用於取消設定變數。

4, 5, 7, 8
35 var_dump()

該函式用於轉儲一個或多個變數的資訊。資訊包含變數的型別和值。

4, 5, 7, 8
36 var_export()

該函式返回關於變數的結構化資訊。

4.2.0, 5, 7, 8

PHP 區域性變數

作用域可以定義為變數在其宣告的程式中具有的可用範圍。PHP 變數可以是四種作用域型別之一:

  • 區域性變數
  • 全域性變數
  • 靜態變數
  • 函式引數

區域性變數

在函式中宣告的變數被認為是區域性變數;也就是說,它只能在該函式中引用。在該函式之外的任何賦值都將被視為與函式中包含的變數完全不同的變數。

<?php
   $x = 4;
   
   function assignx () { 
      $x = 0;
      print "\$x inside function is $x. \n";
   }
   
   assignx();
   print "\$x outside of function is $x.";
?>

這將產生以下結果:

$x inside function is 0. 
$x outside of function is 4. 

PHP 全域性變數

在PHP中,任何可以在PHP指令碼中的任何地方訪問的變數都被稱為**全域性變數**。如果變數在指令碼中的所有函式或類之外宣告,則它成為全域性變數。

雖然全域性變數可以直接在函式外部訪問,但它們不會自動在函式內部可用。

示例

在下面的指令碼中,**$name**對於函式**sayhello()**是全域性的。

<?php
   $name = "Amar";
   function sayhello() {
      echo "Hello " . $name;
   }
   sayhello();
?>

但是,該變數在函式內部不可訪問。因此,您將收到**錯誤訊息**“未定義變數 $name”。

Hello 
PHP Warning: Undefined variable $name in /home/cg/root/93427/main.php on line 5

示例

要在函式內訪問它,需要在變數前使用“global”關鍵字。

<?php
   $name = "Amar";
   function sayhello() {
      GLOBAL $name;
      echo "Hello " . $name;
   }
   sayhello();
?>

它將產生以下輸出

Hello Amar

如果函式訪問全域性變數並修改它,則在函式呼叫完成後,修改後的值在任何地方都可用。

讓我們在**sayhello()**函式內部更改**$name**的值,並在函式呼叫後檢查其值。

示例

看一下下面的例子 -

<?php
   $name = "Amar";
   function sayhello() {
      GLOBAL $name;
      echo "Global variable name: $name" .PHP_EOL;
      $name = "Amarjyot";
      echo "Global variable name changed to: $name" .PHP_EOL;
   }
   sayhello();
   echo "Global variable name after function call: $name" .PHP_EOL;
?>

它將產生以下輸出

Global variable name: Amar
Global variable name changed to: Amarjyot
Global variable name after function call: Amarjyot

$GLOBALS 陣列

PHP維護一個名為**$GLOBALS**的關聯陣列,其中包含在全域性範圍內宣告的所有變數及其值。$GLOBALS陣列還儲存許多稱為超級全域性變數的預定義變數以及使用者定義的全域性變數。

任何全域性變數也可以在任何函式內部使用訪問陣列元素的常規語法訪問。例如,全域性變數**$name**的值由**$GLOBALS["name"]**給出。

示例

在下面的示例中,兩個全域性變數 $x 和 $y 在 addition() 函式內部被訪問。

<?php
   $x = 10;
   $y = 20;

   function addition() {
      $z = $GLOBALS['x']+$GLOBALS['y'];
      echo "Addition: $z" .PHP_EOL;
   }
   addition();
?>

它將產生以下輸出

Addition: 30

示例

您還可以透過將任何區域性變數新增到 $GLOBALS 陣列中來將其新增到全域性作用域中。讓我們將**$z**新增到全域性作用域。

<?php
   $x = 10;
   $y = 20;
   function addition() {
      $z = $GLOBALS['x']+$GLOBALS['y'];
      $GLOBALS['z'] = $z;
   }
   addition();
   echo "Now z is the global variable. Addition: $z" .PHP_EOL;
?>

它將產生以下輸出

Now z is the global variable. Addition: 30

在一個PHP指令碼中包含另一個PHP指令碼

你可以在一個PHP指令碼中包含另一個PHP指令碼。在包含的指令碼中宣告的變數將新增到包含它的PHP指令碼的全域性作用域中。

這是“a.php”檔案:

<?php
   include 'b.php';
   function addition() {
      $z = $GLOBALS['x']+$GLOBALS['y'];
      echo "Addition: $z" .PHP_EOL;
   }
   addition();
?>

它包含具有**$x**和**$y**變數的“b.php”,因此它們成為“a.php”指令碼中**addition()**函式的全域性變數。

<?php
   $x = 10;
   $y = 20;
?>

全域性變數通常在實現單例模式、訪問嵌入式系統中的暫存器以及許多函式使用一個變數時使用。

PHP 超全域性變數

PHP解析器在其全域性名稱空間中填充當前指令碼的許多預定義變數。預定義變數被稱為“**PHP超級全域性變數**”。

  • 任何在任何函式、方法或類之外宣告的使用者定義變數也是全域性變數。但是,要訪問它,需要使用**global**關鍵字。

  • 相反,**超級全域性變數**始終可以在PHP指令碼中的任何地方使用,無需使用**global**關鍵字。

PHP中的大多數超級全域性變數都是關聯陣列,由Web伺服器填充。因此,如果指令碼在命令列環境中執行,一些超級全域性變數可能為空。

PHP中超級全域性變數的列表包括以下內容:

  • $GLOBALS

  • $_SERVER

  • $_GET

  • $_POST

  • $_FILES

  • $_COOKIE

  • $_SESSION

  • $_REQUEST

  • $_ENV

本章將簡要介紹PHP中的這些超級全域性變數。在後續章節中,我們將詳細討論這些超級全域性變數。

$GLOBALS

這是一個對所有全域性定義變數的引用的關聯陣列。變數名構成鍵,其內容是關聯陣列的值。

$_SERVER

所有伺服器和執行環境相關資訊都包含在這個關聯陣列中。

5.4.0之前的PHP版本包含$HTTP_SERVER_VARS包含相同的資訊,但現在已被刪除。

$_GET

這是一個關聯陣列,透過附加到HTTP請求URL的查詢字串傳遞給當前指令碼的變數。請注意,除了GET請求外,所有帶有查詢字串的請求都會填充該陣列。

查詢字串是所有變數及其值的列表,其形式為var=val,並由“&”符號連線。

查詢字串本身附加在“?”符號後的PHP指令碼名稱之後。例如,**https:///hello.php?first_name=Amar&last_name=Sharma**。

$_POST

這是一個鍵值對的關聯陣列,透過使用**URLEncoded**或**multipart/form-data**內容型別的HTTP POST方法傳遞到URL。

$HTTP_POST_VARS也包含與$_POST相同的資訊,但它不是超級全域性變數,現在已被棄用。向伺服器傳送POST請求資料的最簡單方法是將HTML表單的method屬性指定為POST。

$_FILES

$_FILES變數是一個關聯陣列,包含透過HTTP POST方法上傳的專案。當HTML表單包含一個檔案型別的輸入元素,其enctype屬性設定為multipart/form-data,並且method屬性設定為HTTP POST方法時,將上傳檔案。

$_COOKIE

Cookie是伺服器儲存在客戶端計算機上的文字檔案,它們用於跟蹤目的。

超級全域性變數$_COOKIE儲存與HTTP請求一起傳遞給當前PHP指令碼的變數,形式為cookie。

$_SESSION

HTTP會話是使用者與伺服器建立連線的時間和連線終止的時間之間的時間段。在此期間,一些資料以會話變數的形式跨頁面持久可用。

$_SESSION超級全域性變數是當前指令碼可用的會話變數的關聯陣列。

$_REQUEST

$_REQUEST是一個關聯陣列,它是$_GET、$_POST和$_COOKIE變數內容的集合。

這些變數的順序由“php.ini”檔案中**requests_order**和**variables_order**設定的值決定。

$_ENV

$_ENV是一個關聯陣列,儲存當前指令碼可用的所有環境變數。如果PHP作為伺服器模組或CGI處理器執行,此陣列還包括CGI變數。

PHP $GLOBALS

$GLOBALS是PHP中的“**超級全域性變數**”或“**自動全域性變數**”之一。它在整個指令碼的所有範圍內都可用。無需執行“**global $variable;**”即可在函式或方法中訪問它。

$GLOBALS是對所有全域性定義變數的引用的關聯陣列。變數名構成鍵,其內容是關聯陣列的值。

示例

此示例顯示$GLOBALS陣列包含全域性變數的名稱和內容:

<?php
   $var1="Hello";
   $var2=100;
   $var3=array(1,2,3);

   echo $GLOBALS["var1"] . "\n";
   echo $GLOBALS["var2"] . "\n";
   echo implode($GLOBALS["var3"]) . "\n";
?>

它將產生以下輸出

Hello
100
123

示例

在下面的示例中,**$var1**在全域性名稱空間以及函式內的區域性變數中定義。全域性變數是從$GLOBALS陣列中提取的。

<?php
   function myfunction() {
      $var1="Hello PHP";
      echo "var1 in global namespace: " . $GLOBALS['var1']. "\n";
      echo "var1 as local variable: ". $var1;
   }
   $var1="Hello World";
   myfunction();
?>

它將產生以下輸出

var1 in global namespace: Hello World
var1 as local variable: Hello PHP

示例

在PHP 8.1.0之前,全域性變數可以透過$GLOBALS陣列的副本進行修改。

<?php
   $a = 1;
   $globals = $GLOBALS; 
   $globals['a'] = 2;
   var_dump($a);
?>

它將產生以下輸出

int(1)

這裡,**$globals**是$GLOBALS超級全域性變數的副本。將副本中的元素(其鍵為“a”)更改為2,實際上會更改**$a**的值。

它將產生以下輸出

int(2)

示例

從PHP 8.1.0開始,$GLOBALS是全域性符號表的只讀副本。也就是說,不能透過其副本修改全域性變數。與上述相同的操作不會將**$a**更改為2。

<?php
   $a = 1;
   $globals = $GLOBALS; 
   $globals['a'] = 2;
   var_dump($a);
?>

它將產生以下輸出

int(1)

PHP $_SERVER

$_SERVER是PHP中的超級全域性變數。它包含有關HTTP標頭、路徑和指令碼位置等資訊。

  • $_SERVER是一個關聯陣列,它包含所有伺服器和執行環境相關資訊。

  • 此關聯陣列中的大多數條目都由Web伺服器填充。條目可能因Web伺服器而異,因為伺服器可能會省略一些條目,或提供其他條目。

  • 對於在命令列上執行的PHP指令碼,大多數這些條目將不可用或沒有任何意義。

  • PHP還將使用請求標頭中的值建立其他元素。這些條目的名稱將為“HTTP_”,後跟標頭名稱,大寫,並使用下劃線而不是連字元。

  • 例如,“Accept-Language”標頭將作為$_SERVER['HTTP_ACCEPT_LANGUAGE']提供。

  • 5.4.0之前的PHP版本包含`$HTTP_SERVER_VARS`,其中包含相同的資訊,但現在已被移除。

下表列出了一些重要的$_SERVER陣列伺服器變數及其值的描述。

序號 伺服器變數及描述
1

PHP_SELF

儲存當前正在執行指令碼的檔名。

2

SERVER_ADDR

此陣列屬性返回當前指令碼正在執行的伺服器的IP地址。

3

SERVER_NAME

當前指令碼正在執行的伺服器主機名。如果伺服器在本地執行,則返回localhost。

4

QUERY_STRING

查詢字串是由“&”符號分隔的鍵值對字串,附加在“?”符號後的URL之後。

例如,https:///testscript?name=xyz&age=20 URL返回尾隨查詢字串

5

REQUEST_METHOD

用於訪問URL的HTTP請求方法,例如POST、GET、PUT或DELETE。

在上例查詢字串中,附加到帶有“?”符號的查詢字串的URL使用GET方法請求頁面。

6

DOCUMENT_ROOT

返回伺服器上配置為文件根目錄的目錄名。

在XAMPP Apache伺服器上,它返回**htdocs**作為文件根目錄c:/xampp/htdocs的名稱。

7

REMOTE_ADDR

使用者檢視當前頁面的機器的IP地址。

8

SERVER_PORT

Web伺服器偵聽傳入請求的埠號。預設為80。

示例

從XAMPP伺服器的文件根目錄呼叫的以下指令碼列出了所有伺服器變數:

<?php
   foreach ($_SERVER as $k=>$v)
   echo $k . "=>" . $v . "\n";
?>

它將產生以下輸出

MIBDIRS=>C:/xampp/php/extras/mibs
MYSQL_HOME=>\xampp\mysql\bin
OPENSSL_CONF=>C:/xampp/apache/bin/openssl.cnf
PHP_PEAR_SYSCONF_DIR=>\xampp\php
PHPRC=>\xampp\php
TMP=>\xampp\tmp
HTTP_HOST=>localhost
HTTP_CONNECTION=>keep-alive
HTTP_SEC_CH_UA=>"Chromium";v="116", "Not)
A;Brand";v="24", "Google Chrome";v="116"
HTTP_SEC_CH_UA_MOBILE=>?0
HTTP_SEC_CH_UA_PLATFORM=>"Windows"
HTTP_DNT=>1
HTTP_UPGRADE_INSECURE_REQUESTS=>1
HTTP_USER_AGENT=>Mozilla/5.0 (Windows NT 10.0; Win64; x64)
 AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36
HTTP_ACCEPT=>text/html,application/xhtml+xml,application/xml;
q=0.9,image/avif,image/webp,image/apng,*/*;
q=0.8,application/signed-exchange;v=b3;q=0.7
HTTP_SEC_FETCH_SITE=>none
HTTP_SEC_FETCH_MODE=>navigate
HTTP_SEC_FETCH_USER=>?1
HTTP_SEC_FETCH_DEST=>document
HTTP_ACCEPT_ENCODING=>gzip, deflate, br
HTTP_ACCEPT_LANGUAGE=>en-US,en;q=0.9,mr;q=0.8
PATH=>C:\Python311\Scripts\;
C:\Python311\;C:\WINDOWS\system32;
C:\WINDOWS;C:\WINDOWS\System32\Wbem;
C:\WINDOWS\System32\WindowsPowerShell\v1.0\;
C:\WINDOWS\System32\OpenSSH\;C:\xampp\php;
C:\Users\user\AppData\Local\Microsoft\WindowsApps;
C:\VSCode\Microsoft VS Code\bin
SystemRoot=>C:\WINDOWS
COMSPEC=>C:\WINDOWS\system32\cmd.exe
PATHEXT=>.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC;.PY;.PYW
WINDIR=>C:\WINDOWS
SERVER_SIGNATURE=>
Apache/2.4.56 (Win64) OpenSSL/1.1.1t PHP/8.0.28 Server at localhost Port 80

SERVER_SOFTWARE=>Apache/2.4.56 (Win64) OpenSSL/1.1.1t PHP/8.0.28
SERVER_NAME=>localhost
SERVER_ADDR=>::1
SERVER_PORT=>80
REMOTE_ADDR=>::1
DOCUMENT_ROOT=>C:/xampp/htdocs
REQUEST_SCHEME=>http
CONTEXT_PREFIX=>
CONTEXT_DOCUMENT_ROOT=>C:/xampp/htdocs
SERVER_ADMIN=>postmaster@localhost
SCRIPT_FILENAME=>C:/xampp/htdocs/hello.php
REMOTE_PORT=>54148
GATEWAY_INTERFACE=>CGI/1.1
SERVER_PROTOCOL=>HTTP/1.1
REQUEST_METHOD=>GET
QUERY_STRING=>
REQUEST_URI=>/hello.php
SCRIPT_NAME=>/hello.php
PHP_SELF=>/hello.php
REQUEST_TIME_FLOAT=>1694802456.9816
REQUEST_TIME=>1694802456

PHP $_REQUEST

在PHP中,`$_REQUEST`是一個超級全域性變數。它是一個關聯陣列,包含`$_GET`、`$_POST`和`$_COOKIE`變數的內容。

  • “php.ini”檔案中的設定決定了此變數的組成。

  • “php.ini”中的一個指令是**request_order**,它決定PHP註冊GET、POST和COOKIE變數的順序。

  • 此陣列中列出的變數的存在和順序根據PHP的**variables_order**定義。

  • 如果從命令列執行PHP指令碼,則`$_REQUST`陣列中不包含**argc**和**argv**變數,因為它們的值取自`$_SERVER`陣列,而`$_SERVER`陣列又由Web伺服器填充。

使用GET方法的$_REQUEST

將以下指令碼儲存到Apache伺服器的文件資料夾中。如果您在Windows上使用XAMPP伺服器,請將指令碼作為“hello.php”放在“c:/xampp/htdocs”資料夾中。

<html>
<body>
   <?php
      echo "<h3>First Name: " . $_REQUEST['first_name'] . "<br />" 
      . "Last Name: " . $_REQUEST['last_name'] . "</h3>";
   ?>
</body>
</html>

啟動XAMPP伺服器,並在瀏覽器視窗中輸入**https:///hello.php?first_name=Amar&last_name=Sharma**作為URL。

您應該獲得以下**輸出**:

PHP $ Request 1

使用POST方法的$_REQUEST

在文件根目錄下,將以下指令碼儲存為“hello.html”。

<html>
<body>
   <form action="hello.php" method="post">
      First Name: <input type="text" name="first_name" /> <br />
      Last Name: <input type="text" name="last_name" />
      <input type="submit" value="Submit" />
   </form>
</body>
</html>

在瀏覽器中,輸入URL“https:///hello.html”。您應該在瀏覽器視窗中獲得類似的**輸出**。

PHP $ Request 2

您也可以將PHP程式碼嵌入HTML指令碼中,並使用PHP_SELF變數將表單POST到自身:

<html>
<body>
   <form action="<?php echo $_SERVER['PHP_SELF'];?>" method="post">
      <p>First Name: <input type="text" name="first_name" /></p>
      <p>Last Name: <input type="text" name="last_name" /></p>
      <input type="submit" value="Submit" />
   </form>
   <?php
      if ($_SERVER["REQUEST_METHOD"] == "POST")
      echo "<h3>First Name: " . $_REQUEST['first_name'] . "<br />" 
      . "Last Name: " . $_REQUEST['last_name'] . "</h3>";
   ?>
</body>
</html>

它將產生以下輸出

PHP $ Request 3

PHP $_POST

`$_POST`是PHP中預定義的或超級全域性變數之一。它是一個鍵值對的關聯陣列,透過使用URLEncoded或multipart/form-data內容型別的HTTP POST方法傳遞到URL。

  • `$HTTP_POST_VARS`也包含與`$_POST`相同的資訊,但它不是超級全域性變數,現在已被棄用。

  • 使用POST請求向伺服器傳送資料的最簡單方法是將HTML表單的**method屬性**指定為**POST**。

假設瀏覽器中的URL是“https:///hello.php”,則在下面的HTML表單“hello.html”中設定method=POST:

<html>
<body>
   <form action="hello.php" method="post">
      <p>First Name: <input type="text" name="first_name"/> </p>
      <p>Last Name: <input type="text" name="last_name" /> </p>
      <input type="submit" value="Submit" />
   </form>
</body>
</html>

此練習的“hello.php”指令碼(位於文件根目錄資料夾中)如下所示:

<?php
   echo "<h3>First name: " . $_POST['first_name'] . "<br /> " . 
   "Last Name: " . $_POST['last_name'] . "</h3>";
?>

現在,在瀏覽器中開啟**https:///hello.html**。您應該在螢幕上看到以下輸出:

PHP $ POST 1

當您按下**提交**按鈕時,資料將使用POST方法提交到“hello.php”。

PHP $ POST 2

您也可以在hello.php中混合HTML表單和PHP程式碼,並使用“PHP_SELF”變數將表單資料釋出到自身:

<html>
<body>
   <form action="<?php echo $_SERVER['PHP_SELF'];?>" method="post">
      <p>First Name: <input type="text" name="first_name"/> </p> <br />
      <p>Last Name: <input type="text" name="last_name" /></p>
      <input type="submit" value="Submit" />
   </form>
   <?php
      echo "<h3>First Name: " . $_POST['first_name'] . "<br /> " . 
      "Last Name: " . $_POST['last_name'] . "</h3>";
   ?>
</body>
</html>

它將產生以下輸出

PHP $ POST 3

PHP $_GET

`$_GET`是PHP中的超級全域性變數之一。它是透過附加到HTTP請求URL的查詢字串傳遞給當前指令碼的變數的關聯陣列。請注意,除了GET請求外,所有帶有查詢字串的請求都會填充此陣列。

`$HTTP_GET_VARS`包含相同的資訊,但現在已被棄用。

預設情況下,客戶端瀏覽器使用HTTP GET方法向伺服器傳送URL請求。附加到URL的查詢字串可能包含由“&”符號連線的鍵值對。`$_GET`關聯陣列儲存這些鍵值對。

將以下指令碼儲存到Apache伺服器的文件資料夾中。如果您在Windows上使用XAMPP伺服器,請將指令碼作為“hello.php”放在“c:/xampp/htdocs”資料夾中。

<?php
   echo "<h3>First Name: " . $_REQUEST['first_name'] . "<br />" . 
   "Last Name: " . $_REQUEST['last_name'] . "</h3>";
?>

啟動XAMPP伺服器,並在瀏覽器視窗中輸入“https:///hello.php?first_name=Mukesh&last_name=Sinha”作為URL。您應該獲得以下**輸出**:

PHP $ GET 1

`$_GET`陣列在HTML表單資料使用GET方法提交到URL時也會被填充。

在文件根目錄下,將以下指令碼儲存為“**hello.html**”:

<html>
<body>
   <form action="hello.php" method="get">
      <p>First Name: <input type="text" name="first_name"/></p>
      <p>Last Name: <input type="text" name="last_name" /></p>
      <input type="submit" value="Submit" />
   </form>
</body>
</html>

在瀏覽器中,輸入URL“**https:///hello.html**”:

PHP $ GET 2

您應該在瀏覽器視窗中獲得類似的**輸出**:

PHP $ GET 3

在下面的例子中,`htmlspecialchars()`用於將字元轉換為HTML實體:

字元

替換

& (與號)

&amp;

" (雙引號)

&quot;

' (單引號)

&#039; 或 &apos;

< (小於號)

&lt;

> (大於號)

&gt;

假設瀏覽器中的URL是“https:///hello.php?name=Suraj&age=20”:

<?php
   echo  "Name: " . htmlspecialchars($_GET["name"]) . "";
   echo  "Age: " . htmlspecialchars($_GET["age"]) . "<br/>";
?>

它將產生以下輸出

Name: Suraj
Age: 20

PHP $_FILES

`$_FILES`是PHP中的“超級全域性”或自動全域性變數之一。它在整個指令碼的所有範圍內都可用。`$_FILES`變數是一個關聯陣列,包含透過HTTP POST方法上傳的專案。

當HTML表單包含一個檔案型別的輸入元素、其enctype屬性設定為multipart/form-data以及method屬性設定為HTTP POST方法時,將上傳檔案。

`$HTTP_POST_FILES`也包含相同的資訊,但它不是超級全域性變數,現在已被棄用。

下面的HTML指令碼包含一個表單,其中包含**檔案**型別的**輸入**元素:

<input type="file" name="file">

此“input type”呈現一個標題為檔案的按鈕。單擊時,會彈出一個檔案對話方塊。您可以選擇要上傳的檔案。

伺服器上的PHP指令碼可以在`$_FILES`變數中訪問檔案資料。

`$_FILES`陣列包含以下屬性:

  • **`$_FILES['file']['name']`** - 使用者選擇上傳的檔案的原始名稱。

  • **`$_FILES['file']['type']`** - 檔案的MIME型別。例如“image/gif”。但是,此MIME型別不會在PHP端進行檢查。

  • **`$_FILES['file']['size']`** - 上傳檔案的以位元組為單位的大小。

  • **`$_FILES['file']['tmp_name']`** - 上傳檔案在伺服器上儲存的臨時檔名。

  • **`$_FILES['file']['full_path']`** - 瀏覽器提交的完整路徑。從PHP 8.1.0開始可用。

  • **`$_FILES['file']['error']`** - 與此檔案上傳相關的錯誤程式碼。

**錯誤程式碼**如下所示:

錯誤程式碼 描述

UPLOAD_ERR_OK (值=0)

沒有錯誤,檔案上傳成功。

UPLOAD_ERR_INI_SIZE (值=1)

上傳的檔案超過了php.ini中的upload_max_filesize指令。

UPLOAD_ERR_FORM_SIZE (值=2)

上傳的檔案超過了MAX_FILE_SIZE。

UPLOAD_ERR_PARTIAL (值=3)

上傳的檔案僅部分上傳。

UPLOAD_ERR_NO_FILE (值=4)

沒有上傳檔案。

UPLOAD_ERR_NO_TMP_DIR (值=6)

缺少臨時資料夾。

UPLOAD_ERR_CANT_WRITE (值=7)

無法將檔案寫入磁碟。

UPLOAD_ERR_EXTENSION (值=8)

PHP擴充套件阻止了檔案上傳。

示例

下面的“test.html”包含一個HTML表單,其enctype設定為multiform/form-data。它還包含一個input file元素,該元素在表單上呈現一個按鈕,供使用者選擇要上傳的檔案。將此檔案儲存到Apache伺服器的文件根目錄資料夾中。

<html>
<body>
   <form action="hello.php" method="POST" enctype="multipart/form-data">
      <p><input type="file" name="file"></p>
      <p><input type ="submit" value="submit"></p>
   </form>
</body>
</html>

上面的HTML在瀏覽器視窗中呈現一個名為“選擇檔案”的按鈕。要開啟檔案對話方塊,請單擊“選擇檔案”按鈕。當所選檔案的名稱出現後,單擊**提交**按鈕。

PHP $ Files 1

示例

文件根目錄資料夾中的伺服器端PHP指令碼(**upload.php**)讀取`$_FILES`陣列變數如下:

<?php
   echo "Filename: " . $_FILES['file']['name']."<br>";
   echo "Type : " . $_FILES['file']['type'] ."<br>";
   echo "Size : " . $_FILES['file']['size'] ."<br>";
   echo "Temp name: " . $_FILES['file']['tmp_name'] ."<br>";
   echo "Error : " . $_FILES['file']['error'] . "<br>";
?>

它將產生以下輸出

Filename: abc.txt
Type : text/plain
Size : 556762
Temp name: C:\xampp\tmp\phpD833.tmp
Error : 0

示例

在PHP中,您可以使用HTML陣列功能上傳多個檔案:

<html>
<body>
   <form action="hello.php" method="POST" enctype="multipart/form-data">
      <input type="file" name="files[]"/>
      <input type="file" name="files[]"/>
      <input type ="submit" value="submit"/>
   </form>
</body>
</html>

現在,將PHP指令碼(**hello.php**)更改為:

<?php
   foreach ($_FILES["files"]["name"] as $key => $val) {       
      echo "File uploaded: $val <br>";
   }
?>

瀏覽器將顯示多個“選擇檔案”按鈕。上傳所選檔案後,單擊“提交”按鈕,瀏覽器將顯示響應URL **https:///hello.html**的檔名稱,如下所示:

PHP $ Files 2

PHP $_ENV

**`$_ENV`**是PHP中的超級全域性變數。它是一個關聯陣列,儲存當前指令碼中可用的所有環境變數。**`$HTTP_ENV_VARS`**也包含相同的資訊,但它不是超級全域性變數,現在已被棄用。

環境變數被匯入到全域性名稱空間。大多數這些變數由執行PHP解析器的shell提供。因此,環境變數列表在不同的平臺上可能不同。

如果PHP作為伺服器模組或CGI處理器執行,則此陣列(`$_ENV`)還包含CGI變數。

我們可以使用**foreach**迴圈來顯示所有可用的環境變數:

<?php
   foreach ($_ENV as $k=>$v)
   echo $k . " => " . $v . "<br>";
?>

在Windows作業系統和XAMPP伺服器上,您可能會獲得如下所示的環境變數列表:

變數

ALLUSERSPROFILE

C:\ProgramData

APPDATA

C:\Users\user\AppData\Roaming

CommonProgramFiles

C:\Program Files\Common Files

CommonProgramFiles(x86)

C:\Program Files (x86)\Common Files

CommonProgramW6432

C:\Program Files\Common Files

COMPUTERNAME

GNVBGL3

ComSpec

C:\WINDOWS\system32\cmd.exe

DriverData

C:\Windows\System32\Drivers\DriverData

HOMEDRIVE

C:

HOMEPATH

\Users\user

LOCALAPPDATA

C:\Users\user\AppData\Local

LOGONSERVER

\\GNVBGL3

MOZ_PLUGIN_PATH

C:\Program Files (x86)\ Foxit Software\ Foxit PDF Reader\plugins\

NUMBER_OF_PROCESSORS

8

OneDrive

C:\Users\user\OneDrive

OneDriveConsumer

C:\Users\user\OneDrive

OS

Windows_NT

Path

C:\Python311\Scripts\;

C:\Python311\;

C:\WINDOWS\system32;

C:\WINDOWS;

C:\WINDOWS\System32\Wbem;

C:\WINDOWS\System32\WindowsPowerShell\ v1.0\;

C:\WINDOWS\System32\OpenSSH\;

C:\xampp\php;

C:\Users\user\AppData\Local\Microsoft\ WindowsApps;

C:\VSCode\Microsoft VS Code\bin

PATHEXT

.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE; .WSF;.WSH;.MSC;.PY;.PYW

PROCESSOR_ARCHITECTURE

AMD64

PROCESSOR_IDENTIFIER

Intel64 Family 6 Model 140 Stepping 1, GenuineIntel

PROCESSOR_LEVEL

6

PROCESSOR_REVISION

8c01

ProgramData

C:\ProgramData

ProgramFiles

C:\Program Files

ProgramFiles(x86)

C:\Program Files (x86)

ProgramW6432

C:\Program Files

PSModulePath

C:\Program Files\WindowsPowerShell\Modules;

C:\WINDOWS\system32\WindowsPowerShell\v1.0\ Modules

PUBLIC

C:\Users\Public

SystemDrive

C:

SystemRoot

C:\WINDOWS

TEMP

C:\Users\user\AppData\Local\Temp

TMP

C:\Users\user\AppData\Local\Temp

USERDOMAIN

GNVBGL3

USERDOMAIN_ROAMINGPROFILE

GNVBGL3

USERNAME

user

USERPROFILE

C:\Users\user

windir

C:\WINDOWS

ZES_ENABLE_SYSMAN

1

__COMPAT_LAYER

RunAsAdmin Installer

AP_PARENT_PID

10608

您也可以訪問單個環境變數的值。此程式碼獲取PATH環境變數:

<?php
   echo "Path: " . $_ENV['Path'];
?>

它將產生以下輸出

Path:
C:\Python311\Scripts\;C:\Python311\;C:\WINDOWS\system32;
C:\WINDOWS;C:\WINDOWS\System32\Wbem;
C:\WINDOWS\System32\WindowsPowerShell\v1.0\;
C:\WINDOWS\System32\OpenSSH\;C:\xampp\php;
C:\Users\mlath\AppData\Local\Microsoft\WindowsApps;
C:\VSCode\Microsoft VS Code\bin

**注意** - `$_ENV`陣列可能產生空結果,這取決於“php.ini”設定“variables_order”。您可能需要編輯“php.ini”檔案並將**variables_order="EGPCS"**設定為**variables_order="GPCS"**值。

getenv()函式

PHP庫提供`getenv()`函式來檢索所有環境變數的列表或特定環境變數的值。

下面的指令碼顯示所有可用的環境變數的值。

<?php
   $arr=getenv();
   foreach ($arr as $key=>$val)
   echo "$key=>$val";
?>

要獲取特定變數的值,請使用其名稱作為 getenv() 函式的引數。

<?php
   echo "Path: " . getenv("PATH");
?>

putenv() 函式

PHP 還提供 putenv() 函式來建立新的環境變數。環境變數僅在當前請求期間存在。

應避免更改某些環境變數的值。預設情況下,使用者只能設定以“PHP_”開頭的環境變數(例如 PHP_FOO=BAR)。

"php.ini" 中的 "safe_mode_protected_env_vars" 指令包含一個逗號分隔的環境變數列表,終端使用者將無法使用 putenv() 更改這些變數。

<?php
   putenv("PHP_TEMPUSER=GUEST");
   echo "Temp user: " . getenv("PHP_TEMPUSER");
?>

瀏覽器將顯示以下輸出

Temp user: GUEST

PHP $_COOKIE

PHP 超全域性變數 $_COOKIE 儲存傳遞給當前 PHP 指令碼以及 HTTP 請求的 cookie 形式的變數。$HTTP_COOKIE_VARS 也包含相同的資訊,但它不是超全域性變數,現在已被棄用。

什麼是 Cookie?

Cookie 是伺服器儲存在客戶端計算機上的文字檔案,用於跟蹤目的。PHP 透明地支援 HTTP Cookie。Cookie 通常在 HTTP 標頭中設定。JavaScript 也可以直接在瀏覽器上設定 Cookie。

伺服器指令碼向瀏覽器傳送一組 Cookie。它將此資訊儲存在本地機器上以備將來使用。下次瀏覽器向 Web 伺服器傳送任何請求時,它會將這些 Cookie 資訊傳送到伺服器,伺服器使用這些資訊來識別使用者。

setcookie() 函式

PHP 提供setcookie 函式來建立一個 Cookie 物件,以便與 HTTP 響應一起傳送到客戶端。

setcookie(name, value, expire, path, domain, security);

引數

  • 名稱 - 儲存的 Cookie 名稱。

  • - 這設定命名變數的值。

  • 過期時間 - 這指定自 1970 年 1 月 1 日 00:00:00 GMT 以來的秒數。

  • 路徑 - Cookie 有效的目錄。

  • 域名 - 在非常大的域名中指定域名。

  • 安全性 - HTTPS 為 1。常規 HTTP 預設值為 0。

如何設定 Cookie

請檢視以下示例。如果尚未設定名為username 的 Cookie,則此指令碼會設定它。

示例

<?php
   if (isset($_COOKIE['username'])) {
      echo "<h2>Cookie username already set: " . $_COOKIE['username'] . "</h2>";
   } else {
      setcookie("username", "Mohan Kumar");
      echo "<h2>Cookie username is now set.</h2>";
   }
?>

從 Apache 伺服器的文件根目錄執行此指令碼。您應該會看到此訊息作為輸出

Cookie username is now set

如果重新執行此指令碼,則 Cookie 現在已設定。

Cookie username already set: Mohan Kumar

示例

要在客戶端後續訪問時檢索 Cookie:

<?php
   $arr=$_COOKIE;
   foreach ($arr as $key=>$val);
   echo "<h2>$key => $val </h2>";
?>

瀏覽器將顯示以下輸出

Username => Mohan Kumar

如何刪除 Cookie

要刪除 Cookie,請使用已過期的日期設定 Cookie,以便瀏覽器觸發 Cookie 刪除機制。

<?php
   setcookie("username", "", time() - 3600);
   echo "<h2>Cookie username is now removed</h2>";
?>

瀏覽器現在將顯示以下輸出

Cookie username is now removed

使用陣列表示法設定 Cookie

您也可以使用 Cookie 名稱中的陣列表示法來設定陣列 Cookie。

setcookie("user[three]", "Guest");
setcookie("user[two]", "user");
setcookie("user[one]", "admin");

如果 Cookie 名稱包含點 (.),則 PHP 會將其替換為下劃線 (_)。

PHP $_SESSION

PHP 中的一個超全域性變數$_SESSION 是當前指令碼中可用的會話變數的關聯陣列。$HTTP_SESSION_VARS 也包含相同的資訊,但它不是超全域性變數,現在已被棄用。

什麼是會話?

會話是在整個網站頁面之間訪問資料的另一種方法。它是使用者與伺服器建立連線的時間與連線終止之間的時間持續時間。在此期間,使用者可以導航到不同的頁面。很多時候,需要一些資料在頁面之間持久可用。這是由會話變數促成的。

會話在伺服器上的臨時目錄中建立一個檔案,其中儲存已註冊的會話變數及其值。在此訪問期間,網站上的所有頁面都可以使用這些資料。

伺服器為每個會話分配一個唯一的 SESSIONID。由於 HTTP 是無狀態協議,會話變數中的資料會在會話終止時自動刪除。

session_start() 函式

為了啟用對會話資料的訪問,必須呼叫 session_start() 函式。session_start() 基於透過 GET 或 POST 請求傳遞的會話識別符號,或透過 Cookie 傳遞的會話識別符號來建立會話或恢復當前會話。

session_start(array $options = []): bool

如果成功啟動會話,此函式返回true,否則返回false

處理會話變數

要建立新的會話變數,請在 $_SESSION 陣列中新增鍵值對:

$_SESSION[ "var"]=value;

要讀取會話變數的值,可以使用echo/print 語句,或var_dump()print_r() 函式。

echo $_SESSION[ "var"];

要獲取當前會話中所有會話變數的列表,可以使用foreach 迴圈遍歷$_SESSION

foreach ($_SESSION as $key=>$val)
echo $key . "=>" . $val;

要手動清除所有會話資料,可以使用session_destroy() 函式。也可以透過呼叫unset() 函式釋放特定的會話變數。

unset($_SESSION[ "var"]);

會話函式列表

在 PHP 中,有很多用於管理會話資料的內建函式。

會話函式 描述
session_abort 丟棄會話陣列更改並結束會話
session_cache_expire 返回當前快取過期時間
session_cache_limiter

獲取和/或設定當前快取限制器

session_commit

session_write_close 的別名
session_create_id 建立新的會話 ID
session_decode 從會話編碼字串解碼會話資料
session_destroy 銷燬註冊到會話的所有資料
session_encode 將當前會話資料編碼為會話編碼字串
session_gc 執行會話資料垃圾收集
session_get_cookie_params 獲取會話 Cookie 引數
session_id

獲取和/或設定當前會話 ID
session_is_registered 找出全域性變數是否在會話中註冊
session_module_name 獲取和/或設定當前會話模組
session_name 獲取和/或設定當前會話名稱
session_regenerate_id 使用新生成的 ID 更新當前會話 ID
session_register_shutdown 會話關閉函式
session_register 將一個或多個全域性變數與當前會話註冊
session_reset

使用原始值重新初始化會話陣列
session_save_path

獲取和/或設定當前會話儲存路徑
session_set_cookie_params 設定會話 Cookie 引數

session_set_save_handler

設定使用者級會話儲存函式

session_start 啟動新會話或恢復現有會話
session_status 返回當前會話狀態
session_unregister 從當前會話登出全域性變數
session_unset 釋放所有會話變數
session_write_close 寫入會話資料並結束會話

示例

以下 PHP 指令碼呈現 HTML 表單。表單資料用於建立三個會話變數。超連結將瀏覽器帶到另一個頁面,該頁面讀取會話變數。

將此程式碼另存為文件根目錄中的“test.php”,並在客戶端瀏覽器中開啟它。輸入資料並按提交按鈕。

<html>
<body>
   <form action="<?php echo $_SERVER['PHP_SELF'];?>" method="post">
      <h3>User's ID: <input type="text" name="ID"/></h3>
      <h3>Your Name: <input type="text" name="name"/></h3>
      <h3>Enter Age: <input type="text" name="age"/></h3>
      <input type="submit" value="Submit"/>
   </form>
   <?php
      session_start();
      if ($_SERVER["REQUEST_METHOD"] == "POST") {
         $_SESSION['UserID'] = $_POST['ID'];
         $_SESSION['Name'] = $_POST['name'];
         $_SESSION['age'] = $_POST['age'];
      }
      echo "Following Session Variables Created: \n";

      foreach ($_SESSION as $key=>$val)
      echo "<h3>" . $key . "=>" . $val . "</h3>";
      echo "<br/>" . '<a href="hello.php">Click Here</a>';
   ?>
</body>
</html>

單擊“提交”按鈕時,它將顯示建立的所有會話變數的列表:

PHP $ SESSION 1

接下來,在“hello.php”檔案中儲存以下指令碼。

<?php
session_start();
   echo "<h2>Following Session variables Read:</h2>";
   foreach ($_SESSION as $key=>$val)
   echo "<h3>" . $key . "=>" . $val . "</h3>";
?>

現在,請按照“test.php”頁面上的連結導航到“hello.php”。它將顯示讀取的會話變數:

PHP $ SESSION 2

PHP 檔案處理

在 PHP 中,檔案是一個資源物件,可以以線性方式從中讀取或寫入資料。“檔案處理”是指 PHP 中的一組函式,這些函式可以使用 PHP 程式碼對磁碟檔案執行讀/寫操作。

檔案物件被分類為。任何在其上執行線性讀/寫操作的資源都是流。其他類似流的物件是 TCP 套接字、標準輸入流(即由“php://stdin”表示的系統鍵盤)、由“php://stdout”表示的標準輸出流和錯誤流“php://stderr”。

注意 - 常量 STDIN、STDOUT 和 STDERR 分別代表相應的標準流。

儘管 PHP 被認為是用於開發 Web 應用程式的伺服器端指令碼語言,但 PHP 也具有命令列介面來執行控制檯 IO 操作。

示例

PHP 中的 readline() 函式接受來自標準鍵盤的使用者輸入,而 echo/print 語句在控制檯上呈現輸出。

<?php
   $str = readline("Type something:");
   echo $str;
?>

它將產生以下輸出

C:\xampp\php>php hello.php
Type something: Are you enjoying this PHP tutorial?
Are you enjoying this PHP tutorial?

示例

我們可以透過從“php://stdin”讀取輸入並將其輸出到“php://stdout”來獲得相同的效果。

<?php
   $f = fopen("php://stdin", "r");
   echo "Type something: ";

   $str = fgets($f);
   $f1 = fopen("php://stdout", "w");

   fputs($f1, $str);
?>

在這裡,fopen() 函式用於開啟stdin 流以進行讀取和stdout 流以進行寫入。

示例

PHP 支援各種流協議,用於流相關函式,例如 fopen()、file_exists() 等。使用 php_get_wrappers() 函式獲取所有已註冊包裝器的列表。

<?php
   print_r(stream_get_wrappers());
?>

它將產生以下輸出

Array
(
   [0] => php
   [1] => file
   [2] => glob
   [3] => data
   [4] => http
   [5] => ftp
   [6] => zip
   [7] => compress.zlib
   [8] => compress.bzip2
   [9] => https
   [10] => ftps
   [11] => phar
)

流引用為“scheme://target”。例如,檔案流是“file://xyz.txt”。

來自控制檯的輸入資料儲存在計算機的主記憶體 (RAM) 中,直到應用程式執行為止。此後,RAM 中的記憶體內容將被擦除。

我們希望以一種可以在需要時從持久介質(如磁碟檔案)中檢索到的方式儲存它。因此,我們將使用磁碟檔案來讀取資料,並使用目標來儲存資料,而不是標準流(鍵盤用於輸入,顯示裝置用於輸出)。

除了在上述示例中使用的讀和寫模式(與標準流的 IO 操作)之外,檔案流還可以以各種其他模式開啟,例如“r+”和“w+”用於同時讀/寫,“b”用於二進位制模式等。

要開啟磁碟檔案以進行讀取並獲取其引用指標,請使用 fopen() 函式。

$handle = fopen('file://' . __DIR__ . '/data.txt', 'r');

“file://” 方案是預設方案。因此,尤其是在處理本地檔案時,可以輕鬆省略。

注意 − 建議始終關閉已開啟的流。為此,請使用 fclose() 函式。

fclose($handle);

PHP 提供多個內建函式用於對檔案流執行讀/寫操作。在後續章節中,我們將探討檔案系統函式。

PHP 開啟檔案

PHP 的內建函式庫提供 fopen() 函式來開啟檔案或任何其他流,並返回其“引用指標”,也稱為“控制代碼”。

PHP 中的 fopen() 函式類似於 C 中的 fopen() 函式,不同之處在於 C 中的 fopen() 函式無法開啟 URL。

fopen() 的語法

fopen() 函式具有以下簽名:

fopen(
   string $filename,
   string $mode,
   bool $use_include_path = false,
   ?resource $context = null
): resource|false

$filename$mode 引數是必需的。以下是引數的說明:

  • $filename − 此引數是一個字串,表示要開啟的資源。它可以是本地檔案系統中的檔案,也可以是遠端伺服器上的檔案,帶有 scheme:// 字首。

  • $mode − 一個字串,表示授予檔案/資源的訪問型別。

  • $use_include_path − 一個可選的布林引數,如果要也在 include_path 中搜索檔案,則可以將其設定為“1”或 true。

  • $context − 一個上下文流資源。

開啟檔案的模式

PHP 允許以以下模式開啟檔案:

模式 描述
r 只讀開啟檔案。
w 只寫開啟檔案;即使檔案存在,也會建立一個新檔案。
a 以追加模式開啟檔案
x 建立一個只寫的新檔案。
r+ 讀/寫開啟檔案。
w+ 讀/寫開啟檔案;即使檔案存在,也會建立一個新檔案。
a+ 以追加模式讀/寫開啟檔案。
x+ 建立一個讀/寫的新檔案。
c 如果檔案不存在,則開啟檔案進行寫入。但是,如果檔案存在,則不會截斷(與 w 模式不同)。
c+ 如果檔案不存在,則開啟檔案進行讀/寫。但是,如果檔案存在,則不會截斷(與 w 模式不同)。
e 在開啟的檔案描述符上設定 close-on-exec 標誌。僅在符合 POSIX.1-2008 系統上編譯的 PHP 中可用。

如果 fopen() 函式成功執行,則它將返回繫結到檔案流的“檔案指標”或“控制代碼”資源。但是,如果失敗,則返回 false 併發出 E_WARNING。

$handle = fopen('a.txt, 'r');
var_dump($handle);

如果檔案存在於當前目錄中,則輸出將顯示成功:

resource(5) of type (stream)

如果沒有,則會收到以下錯誤訊息

Warning: fopen(a.txt): Failed to open stream: 
No such file or directory in a.php on line 2
bool(false)

示例

以下示例顯示了 fopen() 函式的不同用法:

<?php
   $handle = fopen("hello.txt", "w");
   $handle = fopen("c:/xampp/htdocs/welcome.png", "rb");
   $handle = fopen("https:///hello.txt", "r");
?>

請注意,當檔名是目錄時,此函式也可能成功。在這種情況下,您可能需要使用is_dir()函式在執行任何讀/寫操作之前檢查它是否是檔案。

開啟檔案後,您可以使用fwrite()fputs()等函式向其中寫入資料,並使用fread()fgets()函式從中讀取資料。

關閉檔案

建議始終關閉控制代碼引用的開啟流:

fclose($handle);

PHP 讀取檔案

PHP 中有多種選項可用於讀取使用 fopen() 函式開啟的檔案中的資料。PHP 庫中的以下內建函式可以幫助我們執行讀取操作:

  • fgets() − 從檔案指標獲取一行。

  • fgetc() − 返回檔案指標中單個字元的字串。

  • fread() − 從檔案指標讀取指定數量的位元組。

  • fscanf() − 從檔案讀取資料並根據指定的格式進行解析。

fgets() 函式

fgets() 函式可以從開啟的檔案中返回一行。此函式在指定長度的新行或 EOF 處停止返回,以先到達者為準,並在失敗時返回false

fgets(resource $stream, ?int $length = null): string|false

這裡,$stream引數是指向使用 fopen() 函式以讀或讀/寫模式開啟的檔案的檔案指標或控制代碼,$length是指定要讀取的位元組數的可選引數。

當讀取“length-1”個位元組或遇到換行符時,讀取操作結束,以先到達者為準。

示例

以下程式碼從“hello.txt”檔案讀取第一行:

<?php
   $file = fopen("hello.txt", "r");
   $str = fgets($file);
   echo $str;
   fclose($file);
?>

它將產生以下輸出

Hello World

示例

您可以將 fgets() 函式放在迴圈中,以讀取檔案直到檔案結束。

<?php
   $file = fopen("hello.txt", "r");
   while(! feof($file)) {
      echo fgets($file). "<br>";
   }
   fclose($file);
?>

它將產生以下輸出

Hello World
TutorialsPoint
PHP Tutorials

這裡,我們使用了feof()函式,如果檔案指標位於 EOF 處,則返回 true;否則返回 false。

fgetc() 函式

fgetc() 函式返回從檔案控制代碼的當前位置讀取的單個字元。遇到 EOF 時返回false

fgetc(resource $stream): string|false

這裡,$stream引數是指向使用 fopen() 函式以讀或讀/寫模式開啟的檔案的檔案指標或控制代碼。

示例

以下程式碼顯示從“hello.txt”檔案讀取的第一個字元:

<?php
   $file = fopen("hello.txt", "r");
   $str = fgets($file);
   echo $str;
   fclose($file);
?>

它將產生以下輸出

H

示例

您還可以將fgetc()函式放在迴圈中,以逐個字元讀取檔案,直到到達 EOF。

<?php
   $file = fopen("hello.txt", "r");
   while(! feof($file)) {
      $char = fgetc($file);
      if ($char == "\n")
      echo "<br>";
      echo $char;
   }
   fclose($file);
?>

它將產生以下輸出

Hello World
TutorialsPoint
PHP Tutorials

fread() 函式

PHP 中的 fread() 函式是用於從檔案讀取資料的二進位制安全函式。fgets() 函式僅從文字檔案讀取,而 fread() 函式可以以二進位制模式讀取檔案。

fread(resource $stream, int $length): string|false

這裡,$stream引數是指向使用 fopen() 函式以二進位制讀或讀/寫模式(rbrb+)開啟的檔案的檔案指標或控制代碼。$length引數指定要讀取的位元組數。

如果沒有給出$length引數,PHP 將嘗試讀取整個檔案,直到到達 EOF,這取決於指定的塊大小。

示例

以下程式碼讀取文字檔案:

<?php
   $name = "hello.txt";
   $file = fopen($name, "r");
   $data = fread($file, filesize($name));
   echo $data;
   fclose($file);
?>

它將產生以下輸出

Hello World TutorialsPoint PHP Tutorials

示例

您還可以讀取以rb模式開啟的非 ASCII 檔案(例如影像檔案)。

<?php
   $name = "welcome.png";
   $file = fopen($name, "rb");
   $data = fread($file, filesize($name));
   var_dump($data);
   fclose($file);
?>

瀏覽器將“var_dump”資訊顯示為:

PHP Read File

fscanf() 函式

PHP 中的 fscanf() 函式從檔案流讀取輸入並根據指定的格式進行解析,從而將其轉換為相應型別的變數。每次呼叫該函式都會從檔案中讀取一行。

fscanf(resource $stream, string $format, mixed &...$vars): array|int|false|null

這裡,$stream引數是指向使用 fopen() 函式以讀模式開啟的檔案的控制代碼。並且,$format是一個包含一個或多個以下格式說明符的字串:

  • %% − 返回百分號

  • %b − 二進位制數

  • %c − 根據 ASCII 值的字元

  • %f − 浮點數

  • %F − 浮點數

  • %o − 八進位制數

  • %s − 字串

  • %d − 帶符號十進位制數

  • %e − 科學計數法

  • %u − 無符號十進位制數

  • %x − 小寫字母的十六進位制數

  • %X − 大寫字母的十六進位制數

$vars是一個可選引數,它透過引用指定變數,這些變數將包含已解析的值。

假設“employees.txt”檔案位於包含以下 PHP 指令碼的同一目錄中。文字檔案中的每一行都包含每個員工的姓名、電子郵件、職位薪水,並用製表符分隔。

示例

以下 PHP 指令碼使用 fscanf() 函式中的格式說明符讀取檔案:

<?php
   $fp = fopen("employees.txt", "r");
   while ($employee_info = fscanf($fp, "%s\t%s\t%s\t%d\n")) {
      list ($name, $email, $post, $salary) = $employee_info;
      echo "<b>Name</b>: $name <b>Email</b>: 
	  $email <b>Salary</b>: Rs. $salary <br>";
   }
   fclose($fp);
?>

它將產生以下輸出

Name: Ravishankar Email: ravi@gmail.com Salary: Rs. 40000
Name: Kavita Email: kavita@hotmail.com Salary: Rs. 25000
Name: Nandkumar Email: nandu@example.com Salary: Rs. 30000

PHP 寫入檔案

PHP 的內建函式庫提供兩個函式來對檔案流執行寫操作。這兩個函式是fwrite()fputs()

為了能夠向檔案中寫入資料,必須以寫入模式 (w)、追加模式 (a)、讀/寫模式 (r+ 或 w+) 或二進位制寫入/追加模式 (rb+、wb+ 或 wa) 開啟檔案。

fputs() 函式

fputs() 函式將字串寫入以可寫模式開啟的檔案。

fputs(resource $stream, string $string, int $length)

這裡,$stream引數是指向以可寫模式開啟的檔案的控制代碼。$string引數是要寫入的資料,$length是指定要寫入的最大位元組數的可選引數。

fputs() 函式返回寫入的位元組數,如果函式不成功,則返回false

示例

以下程式碼開啟一個新檔案,向其中寫入一個字串,並返回寫入的位元組數。

<?php
   $fp = fopen("hello.txt", "w");
   $bytes = fputs($fp, "Hello World\n");
   echo "bytes written: $bytes";
   fclose($fp);
?>

它將產生以下輸出

bytes written: 12

示例

如果需要在現有檔案中新增文字,則必須以追加模式 (a) 開啟它。讓我們在前面示例的同一檔案中再新增一個字串。

<?php
   $fp = fopen("hello.txt", "a");
   $bytes = fputs($fp, "Hello PHP");
   echo "bytes written: $bytes";
   fclose($fp);
?>

如果在文字編輯器中開啟“hello.txt”檔案,則應該看到其中的兩行。

示例

在以下 PHP 指令碼中,一個現有的檔案 (hello.txt) 在迴圈中逐行讀取,每一行都寫入另一個檔案 (new.txt)

假設“hello.txt”包含以下文字:

Hello World
TutorialsPoint
PHP Tutorials

以下是建立現有檔案副本的 PHP 程式碼:

<?php
   $file = fopen("hello.txt", "r");
   $newfile = fopen("new.txt", "w");
   while(! feof($file)) {
      $str = fgets($file);
      fputs($newfile, $str);
   }
   fclose($file);
   fclose($newfile);
?>

新建立的“new.txt”檔案應該具有完全相同的內容。

fwrite() 函式

frwrite() 函式是 fread() 函式的對應函式。它執行二進位制安全寫操作。

fwrite(resource $stream, string $data, ?int $length = null): int|false

這裡,$stream引數是指向以可寫模式開啟的檔案的資源。要寫入檔案的資料在$data引數中提供。可以提供可選的$length引數來指定要寫入的位元組數。它應該是int型別,寫入將在寫入 length 個位元組或到達資料末尾後停止,以先到達者為準。

fwrite() 函式返回寫入的位元組數,如果失敗,則返回false以及 E_WARNING。

示例

以下程式開啟一個新檔案,執行寫操作並顯示寫入的位元組數。

<?php
   $file = fopen("/PhpProject/sample.txt", "w");
   echo fwrite($file, "Hello Tutorialspoint!!!!!");
   fclose($file);
?>

示例

在以下示例程式碼中,以二進位制讀取模式開啟現有的“welcome.png”檔案。fread() 函式用於將它的位元組讀取到“$data”變數中,然後寫入另一個檔案“new.png”:

<?php
   $name = "welcome.png";
   $file = fopen($name, "rb");
   $newfile = fopen("new.png", "wb");
   $size = filesize($name);
   $data = fread($file, $size);
   fwrite($newfile, $data, $size);
   fclose($file);
   fclose($newfile);
?>

執行上述程式碼。當前目錄現在應該有一個現有“welcome.png”檔案的副本。

PHP 檔案是否存在

在對檔案執行任何處理之前,檢查您嘗試開啟的檔案是否真的存在通常非常有用。否則,程式可能會引發執行時異常

PHP 的內建庫在這方面提供了一些實用程式函式。本章將討論的一些函式包括:

  • file_exists() − 測試檔案是否存在

  • is_file() − 如果 fopen() 返回的控制代碼是指檔案還是目錄。

  • is_readable() − 測試您開啟的檔案是否允許讀取資料

  • is_writable() − 測試是否允許向檔案中寫入資料

file_exists() 函式

此函式適用於檔案和目錄。它檢查給定的檔案或目錄是否存在。

file_exists(string $filename): bool

此函式的唯一引數是一個字串,表示具有完整路徑的檔案/目錄。該函式根據檔案是否存在返回 true 或 false。

示例

以下程式檢查檔案“hello.txt”是否存在。

<?php
   $filename = 'hello.txt';
   if (file_exists($filename)) {
      $message = "The file $filename exists";
   } else {
      $message = "The file $filename does not exist";
   }
   echo $message;
?>

如果檔案存在於當前目錄中,則訊息為:

The file hello.txt exists

如果不存在,則訊息為:

The file hello.txt does not exist

示例

指向檔案的字串可以具有相對路徑或絕對路徑。假設“hello.txt”檔案位於當前目錄內的“hello”子目錄中。

<?php
   $filename = 'hello/hello.txt';
      if (file_exists($filename)) {
   $message = "The file $filename exists";
   } else {
      $message = "The file $filename does not exist";
   }
   echo $message;
?>

它將產生以下輸出

The file hello/hello.txt exists

示例

嘗試給出如下所示的絕對路徑:

<?php
   $filename = 'c:/xampp/htdocs/hello.txt';
   if (file_exists($filename)) {
      $message = "The file $filename exists";
   } else {
      $message = "The file $filename does not exist";
   }
   echo $message;
?>

它將產生以下輸出

The file c:/xampp/htdocs/hello.txt exists

is_file() 函式

file_exists()函式對現有檔案和目錄都返回trueis_file()函式可以幫助您確定它是否是檔案。

is_file ( string $filename ) : bool

以下示例顯示了is_file()函式的工作方式:

<?php
   $filename = 'hello.txt';

   if (is_file($filename)) {
      $message = "$filename is a file";
   } else {
      $message = "$filename is a not a file";
   }
   echo $message;
?>

輸出表明它是一個檔案:

hello.txt is a file

現在,將“$filename”更改為目錄,然後檢視結果:

<?php
   $filename = hello;

   if (is_file($filename)) {
      $message = "$filename is a file";
   } else {
      $message = "$filename is a not a file";
   }
   echo $message;
?>

現在,您將被告知“hello”不是檔案。

請注意,is_file()函式接受一個$filename,並且只有當$filename是一個檔案並且存在時才返回true

is_readable() 函式

有時,您可能想提前檢查是否可以從中讀取檔案。is_readable()函式可以確定這一事實。

is_readable ( string $filename ) : bool

示例

下面是is_readable()函式工作方式的示例:

<?php
   $filename = 'hello.txt';
   if (is_readable($filename)) {
      $message = "$filename is readable";
   } else {
      $message = "$filename is not readable";
   }
   echo $message;
?>

它將產生以下輸出

hello.txt is readable

is_writable() 函式

可以使用 `is_writable()` 函式檢查檔案是否存在以及是否可以對指定檔案執行寫入操作。

is_writable ( string $filename ) : bool

示例

以下示例演示了 `**is_writable()**` 函式的工作原理:

<?php
   $filename = 'hello.txt';

   if (is_writable($filename)) {
      $message = "$filename is writable";
   } else {
      $message = "$filename is not writable";
   }
   echo $message;
?>

對於普通的存檔檔案,程式會顯示其可寫。但是,將其屬性更改為“只讀”並執行程式。現在您將看到:

hello.txt is writable

PHP 下載檔案

大多數現代瀏覽器允許自動下載某些型別的檔案,無需任何伺服器端程式碼(例如 PHP 指令碼)。例如,zip 檔案或 EXE 檔案。

如果 HTML 超連結指向 ZIP 或 EXE 檔案,瀏覽器會將其下載並彈出儲存對話方塊。但是,文字檔案、影像檔案等不會下載,而是在瀏覽器中開啟,您可以將其儲存到本地檔案系統。

`readfile()` 函式

要下載此類檔案(而不是瀏覽器自動開啟它們),我們可以使用 PHP 內建函式庫中的 `**readfile()**` 函式。

readfile(string $filename, 
bool $use_include_path = false, 
?resource $context = null)
: int|false

此函式讀取檔案並將其寫入輸出緩衝區。

第二個引數 `**$use_include_path**` 預設值為 false,因此將下載當前目錄中的檔案。如果設定為 `**true**`,則將搜尋新增到 `**php.ini**` 配置的 `**include_path**` 設定中的目錄,以找到要下載的檔案。

`readfile()` 函式返回讀取的位元組數,即使成功完成或未成功完成也是如此,返回false。

示例

以下 PHP 指令碼顯示了 `readfile()` 函式的用法。

要下載檔案,應將 `**Content-Type**` 響應標頭設定為 `**application/octet-stream**`。此 MIME 型別是二進位制檔案的預設型別。瀏覽器通常不會執行它,甚至不會詢問是否應該執行它。

此外,將 `Content-Disposition` 標頭設定為 `attachment` 會提示彈出“另存為”對話方塊。

<?php
   $filePath = 'welcome.png';

   // Set the Content-Type header to application/octet-stream
   header('Content-Type: application/octet-stream');

   // Set the Content-Disposition header to the filename of the downloaded file
   header('Content-Disposition: attachment; filename="'. basename($filePath).'"');

   // Read the contents of the file and output it to the browser.
   readfile($filePath);
?>

將上述指令碼儲存為文件根資料夾中的“download.php”。確保要下載的檔案位於同一資料夾中。

啟動伺服器並在瀏覽器中訪問 `**https:///download.php**`。您將看到如下所示的“另存為”對話方塊:

PHP Download File

您可以選擇名稱並下載檔案。

對於大型檔案,您可以從檔案流中以特定預定義大小的塊讀取它。如果 `Content-Disposition` 頭設定為“attachment”(如前面的示例),瀏覽器會提供將其儲存到本地檔案系統。

<?php
   $filename = 'welcome.png';

   header('Content-Type: application/octet-stream');
   header('Content-Disposition: attachment; filename="' . basename($filename) . '"');

   $handle = fopen($filename, 'rb');
   $buffer = '';
   $chunkSize = 1024 * 1024;

   ob_start();
   while (!feof($handle)) {
      $buffer = fread($handle, $chunkSize);		
      echo $buffer;
      ob_flush();
      flush();
   }
   fclose($handle);
?>

PHP 複製檔案

您可以透過三種不同的方式將現有檔案複製到新檔案:

  • 迴圈讀取一行並寫入另一行

  • 將整個內容讀取到字串中並將字串寫入另一個檔案

  • 使用 PHP 內建函式庫,包括 `copy()` 函式。

方法 1

在第一種方法中,您可以從現有檔案中讀取每一行並寫入新檔案,直到現有檔案到達檔案結尾。

在以下 PHP 指令碼中,一個現有的檔案 (hello.txt) 在迴圈中逐行讀取,每一行都寫入另一個檔案 (new.txt)

假設“hello.txt”包含以下文字:

Hello World
TutorialsPoint
PHP Tutorials

示例

以下是建立現有檔案副本的 PHP 程式碼:

<?php
   $file = fopen("hello.txt", "r");
   $newfile = fopen("new.txt", "w");
   while(! feof($file)) {
      $str = fgets($file);
      fputs($newfile, $str);
   }
   fclose($file);
   fclose($newfile);
?>

新建立的“new.txt”檔案應該具有完全相同的內容。

方法 2

這裡我們使用 PHP 庫中的兩個內建函式:

file_get_contents(
   string $filename,
   bool $use_include_path = false,
   ?resource $context = null,
   int $offset = 0,
   ?int $length = null
): string|false

此函式將整個檔案讀取到字串中。`$filename` 引數是一個包含要讀取的檔名的字串。

另一個函式是:

file_put_contents(
   string $filename,
   mixed $data,
   int $flags = 0,
   ?resource $context = null
): int|false

該函式將 `$data` 的內容放入 `$filename` 中。它返回寫入的位元組數。

示例

在下面的示例中,我們將“hello.txt”的內容讀取到字串 `$data` 中,並將其用作引數寫入“test.txt”檔案。

<?php
   $source = "hello.txt";
   $target = "test.txt";
   $data = file_get_contents($source);
   file_put_contents($target, $data);
?>

方法 3

PHP 提供了 `copy()` 函式,專門用於執行復制操作。

copy(string $from, string $to, ?resource $context = null): bool

`$from` 引數是一個包含現有檔案的字串。`$to` 引數也是一個包含要建立的新檔名的字串。如果目標檔案已存在,它將被覆蓋。

複製操作將根據檔案是否成功複製返回 `true` 或 `false`。

示例

讓我們使用 `copy()` 函式將“text.txt”作為“hello.txt”檔案的副本。

<?php
   $source = "a.php";
   $target = "a1.php";
   if (!copy($source, $target)) {
      echo "failed to copy $source...\n";
   }
?>

PHP 追加檔案

在 PHP 中,`fopen()` 函式返回在不同開啟模式下使用的檔案的指標,例如“w”表示寫入模式,“r”表示讀取模式,“r+”或“w+”模式表示同時讀/寫操作,“a”模式表示追加模式。

當檔案以“w”模式引數開啟時,它總是開啟一個新檔案。這意味著如果檔案已存在,其內容將丟失。隨後的 `fwrite()` 函式將資料放在檔案的起始位置。

假設存在一個名為“new.txt”的檔案,其內容如下:

Hello World
TutorialsPoint
PHP Tutorial

以下語句:

$fp = fopen("new.txt", "w");

在寫入新內容之前擦除所有現有資料。

讀/寫模式

顯然,如果檔案以“r”模式開啟,則無法新增新資料。“r+”或“w+”模式以“r/w”模式開啟檔案,但仍然在開啟檔案後立即執行 `fwrite()` 語句將覆蓋內容。

示例

請看下面的程式碼:

<?php
   $fp = fopen("new.txt", "r+");
   fwrite($fp, "PHP-MySQL Tutorial\n");
   fclose($fp);
?>

使用此程式碼,“new.txt”檔案的內容現在將變為:

PHP-MySQL Tutorial
lsPoint
PHP Tutorial

要確保新內容新增到現有檔案的末尾,我們需要在寫入操作之前手動將檔案指標移到末尾。(初始檔案指標位置在第 0 個位元組)

`fseek()` 函式

PHP 的 `fseek()` 函式可以將檔案指標放在您想要的任何位置:

fseek(resource $stream, int $offset, int $whence = SEEK_SET): int

`$whence` 引數是從哪裡計算偏移量的。其值為:

  • `**SEEK_SET**` - 將位置設定為等於偏移量位元組。

  • `**SEEK_CUR**` - 將位置設定為當前位置加上偏移量。

  • `**SEEK_END**` - 將位置設定為檔案末尾加上偏移量。

示例

因此,我們需要使用 `fseek()` 函式將指標移動到末尾,如下面的程式碼所示,該程式碼將新內容新增到末尾。

<?php
   $fp = fopen("new.txt", "r+");
   fseek($fp, 0, SEEK_END);
   fwrite($fp, "\nPHP-MySQL Tutorial\n");
   fclose($fp);
?>

現在檢查“new.txt”的內容。它將包含以下文字:

Hello World
TutorialsPoint
PHP Tutorial
PHP-MySQL Tutorial

追加模式

無需手動將指標移動到末尾,`fopen()` 函式中的“a”引數以追加模式開啟檔案。每個 `fwrite()` 語句都會將內容新增到現有內容的末尾,方法是自動將指標移動到 `SEEK_END` 位置。

<?php
   $fp = fopen("new.txt", "a");
   fwrite($fp, "\nPHP-MySQL Tutorial\n");
   fclose($fp);
?>

`fopen()` 函式允許的模式之一是“r+”模式,該模式下檔案執行讀/追加操作。要從任何位置讀取資料,您可以使用 `fseek()` 將指標置於所需的位元組。但是,每個 `fwrite()` 操作都只在末尾寫入新內容。

示例

在下面的程式中,檔案以“a+”模式開啟。要讀取第一行,我們從開頭將檔案位置移到第 0 個位置。但是,`fwrite()` 語句仍然將新內容新增到末尾,並且不會像“r+”模式那樣覆蓋下一行。

<?php
   $fp = fopen("new.txt", "a+");
   fseek($fp, 0, SEEK_SET);
   $data = fread($fp, 12);
   echo $data;
   fwrite($fp, "PHP-File Handling");
   fclose ($fp);
?>

因此,如果檔案以“r+/w+”模式或“a/a+”模式開啟,我們可以將資料追加到現有檔案中。

PHP 刪除檔案

PHP 沒有 `delete` 關鍵字或 `delete()` 函式。相反,它提供了 `unlink()` 函式,該函式在呼叫時會從檔案系統中刪除檔案。它類似於 Unix/C 的 `unlink` 函式。

如果無法完成刪除操作,PHP 將返回 false 並顯示 E_WARNING 訊息。

unlink(string $filename, ?resource $context = null): bool

`unlink()` 函式的必需字串引數是一個指向要刪除檔案的字串。

示例

以下程式碼演示了 `unlink()` 函式的簡單用法:

<?php
   $file = "my_file.txt";

   if (unlink($file)) {
      echo "The file was deleted successfully.";
   } else {
      echo "The file could not be deleted.";
   }
?>

刪除指向檔案的符號連結

`unlink()` 函式還可以刪除指向檔案的符號連結。但是,刪除符號連結不會刪除原始檔案。符號連結是現有檔案的快捷方式。

在 Windows 中,以管理員許可權開啟命令提示符,並使用 `/h` 開關和 `mlink` 命令建立指向檔案的符號連結。(`/j` 開關用於指向資料夾的符號連結)

mklink /h hellolink.lnk hello.txt
Hardlink created for hellolink.lnk <<===>> hello.txt

在 Ubuntu Linux 中,要建立指向檔案的符號連結,可以使用以下命令:

ln -s /path/to/original_file /path/to/symlink

要建立指向目錄的符號連結,可以使用以下命令:

ln -s /path/to/original_directory /path/to/symlink

在 PHP 中,還有一個 `symlink()` 函式用於此目的。

symlink(string $target, string $link): bool

示例

使用以下程式碼建立一個符號連結:

<?php
   $target = 'hello.txt';
   $link = 'hellolink.lnk';
   symlink($target, $link);

   echo readlink($link);
?>

現在刪除上面建立的符號連結:

unlink("hellolink.lnk");

如果檢查當前工作目錄,符號連結將被刪除,而原始檔案保持不變。

如何在 PHP 中重新命名檔案

您可以使用作業系統控制檯中的相應命令來更改現有檔案的名稱。例如,Linux 終端中的“`mv` 命令”或 Windows 命令提示符中的“`rename` 命令”可以幫助您更改檔案的名稱。

但是,要以程式設計方式重新命名檔案,PHP 的內建庫包含一個 `rename()` 函式。

以下是 `rename()` 函式的語法:

rename(string $from, string $to, ?resource $context = null): bool

`$from` 和 `$to` 字串分別是現有檔案和新檔案的名稱。`rename()` 函式嘗試將 `$from` 重新命名為 `$to`,必要時在目錄之間移動它。

如果您正在重新命名一個檔案並且 `$to` 已存在,則它將被覆蓋。如果您正在重新命名一個目錄並且 `$to` 存在,則此函式將發出警告。

要將“hello.txt”的名稱更改為“test.txt”:

<?php
   rename("hello.txt", "test.txt");
?>

您還可以採用一種稍微間接的方法來重新命名檔案。複製現有檔案並刪除原始檔案。這也將“hello.txt”重新命名為“test.txt”:

copy("hello.txt", "test.txt");
unlink("hello.txt");

PHP – 處理 CSV 檔案

流行的電子表格程式使用 CSV 檔案格式(代表逗號分隔值)以純文字格式匯出工作表資料。檔案中的每一行代表工作表的一行,每列中的值用逗號分隔。

PHP 的檔案系統函式庫提供了兩個函式——`fgetcsv()` 和 `fputcsv()`——分別用於將 CSV 檔案中的資料讀取到陣列中並將陣列元素放入 CSV 檔案中。

`fgetcsv()` 函式

`fgetcsv()` 函式從檔案指標讀取行,並將其解析為 CSV 欄位。

fgetcsv(
   resource $stream,
   ?int $length = null,
   string $separator = ",",
   string $enclosure = "\"",
   string $escape = "\\"
): array|false

`$stream` 引數是檔案資源的控制代碼,以讀取模式開啟。解析欄位的預設分隔符是逗號,如果需要,您可以指定任何其他符號。

`fgetcsv()` 函式返回一個包含欄位的索引陣列。如果函式遇到任何錯誤,它將返回 `false`。

為了演示 `fgetcsv()` 函式的用法,請將以下文字儲存為當前工作目錄中的“hello.txt”。

Name, Email, Post, Salary
Ravishankar, ravi@gmail.com, Manager, 40000
Kavita, kavita@hotmail.com, Assistant, 25000
Nandkumar, nandu@example.com, Programmer, 30000

示例

以下 PHP 程式碼從該檔案讀取 CSV 資料,並返回一個數組。然後在 HTML 表格中呈現陣列中的欄位:

<?php
   $filename = 'hello.csv';
   $data = [];

   // open the file
   $f = fopen($filename, 'r');

   if ($f === false) {
      die('Cannot open the file ' . $filename);
   }

   // read each line in CSV file at a time
   while (($row = fgetcsv($f)) !== false) {
      $data[] = $row;
   }

   // close the file
   fclose($f);
   echo "<table border=1>";
   foreach ($data as $row) {
      echo "<tr>";
      foreach($row as $val) {
         echo "<td>$val</td>"; 
      }
      echo "</tr>";
   }
   echo "</table>";
?>

它將產生以下輸出

名稱 郵箱 職位 薪水
Ravishankar ravi@gmail.com 經理 40000
Kavita kavita@hotmail.com 助理 25000
Nandkumar nandu@example.com 程式設計師 30000

`fputcsv()` 函式

`fputcsv()` 函式將一個索引陣列及其元素用逗號分隔,放在 CSV 檔案的當前檔案指標位置。

fputcsv(
   resource $stream,
   array $fields,
   string $separator = ",",
   string $enclosure = "\"",
   string $escape = "\\",
   string $eol = "\n"
): int|false

目標檔案必須以寫入模式開啟。第二個必填引數是一個由逗號分隔的欄位組成的陣列。與fgetcsv()函式一樣,預設分隔符為逗號。

示例

在下面的程式碼中,一個二維的逗號分隔值陣列被寫入到一個CSV檔案中。

<?php
   $data = [
      ["Name", "Email", "Post", "Salary"],
      ["Ravishankar", "ravi@gmail.com", "Manager", "40000"],
      ["Kavita", "kavita@hotmail.com", "Assistant", "25000"],
      ["Nandkumar", "nandu@example.com", "Programmer", "30000"],
   ];
   $filename = 'employee.csv';

   // open csv file for writing
   $f = fopen($filename, 'w');

   if ($f === false) {
      die('Error opening the file ' . $filename);
   }

   // write each row at a time to a file
   foreach ($data as $row) {
      fputcsv($f, $row);
   }

   // close the file
   fclose($f);
?>

執行上述程式後,應該在當前工作目錄中建立“employee.csv”檔案。

PHP – 檔案許可權

許可權的概念是Unix/Linux檔案系統的核心。許可權決定了誰能訪問檔案以及如何訪問檔案。Linux中的檔案許可權由**chmod命令**操作,該命令可以在Linux終端內執行。PHP提供了**chmod()函式**,您可以用它以程式設計方式處理檔案許可權。

只有在Linux作業系統上工作時,PHP的chmod()函式才有效。它在Windows上不起作用,因為Windows作業系統有不同的檔案許可權控制機制。

要檢視檔案中啟用的許可權,請使用“**ls -l**”命令(長列表)獲取檔案列表。

mvl@GNVBGL3:~$ ls -l

-rwxr-xr-x 1 mvl mvl 16376 May  5 21:52 a.out
-rw-r--r-- 1 mvl mvl    83 May  5 21:52 hello.cpp
-rwxr-xr-x 1 mvl mvl    43 Oct 11 14:50 hello.php
-rwxr-xr-x 1 mvl mvl    43 May  8 10:01 hello.py
drwxr-xr-x 5 mvl mvl  4096 Apr 20 21:52 myenv

第一列包含每個檔案的許可權標誌。第三列和第四列分別指示每個檔案的擁有者和組,後面跟著大小、日期和時間以及檔名。

許可權字串有十個字元,其含義如下:

位置 含義
1 如果是目錄則為“d”,如果是普通檔案則為“-”
2, 3, 4 檔案擁有者(使用者)的讀、寫、執行許可權
5, 6, 7 組的讀、寫、執行許可權
8, 9, 10 其他使用者的讀、寫、執行許可權

許可權字串中的字元具有以下含義:

含義
- 標誌未設定。
r 檔案可讀。
w 檔案可寫。對於目錄,可以建立或刪除檔案。
x 檔案可執行。對於目錄,可以列出檔案。

如果您考慮上述列表中的第一個條目:

-rwxr-xr-x 1 mvl mvl 16376 May  5 21:52 a.out

“a.out”檔案由使用者“mvl”和組“mvl”擁有。它是一個普通檔案,擁有者具有“讀/寫/執行”許可權,組和其他使用者具有“讀/執行”許可權。

許可權標誌的二進位制和八進位制表示可以透過下表理解:

八進位制數字 二進位制表示 (rwx) 許可權
0 000
1 001 僅執行
2 010 僅寫入
3 011 寫入和執行
4 100 僅讀取
5 101 讀取和執行
6 110 讀取和寫入
7 111 讀取、寫入和執行(完全許可權)

chmod() 函式

chmod()函式可以更改指定檔案的許可權。成功時返回**true**,失敗時返回**false**。

chmod(string $filename, int $permissions): bool

chmod()函式嘗試將指定檔案(**$filename**)的模式更改為許可權中給定的模式。

第二個引數**$permissions**是一個具有四個八進位制數字的八進位制數。第一位始終為零,第二位指定擁有者的許可權,第三位指定擁有者的使用者組的許可權,第四位指定其他所有人的許可權。每一位都是每種許可權值的總和。

1 執行許可權
2 寫入許可權
4 讀取許可權

**$permissions**引數的預設值為**0777**,這意味著目錄的建立啟用了執行、寫入和讀取許可權。

示例

請看以下示例:

<?php

   // Read and write for owner, nothing for everybody else
   chmod("/PhpProject/sample.txt", 0600);

   // Read and write for owner, read for everybody else
   chmod("/PhpProject/sample.txt", 0644);

   // Everything for owner, read and execute for everybody else
   chmod("/PhpProject/sample.txt", 0755);

   // Everything for owner, read for owner's group
   chmod("/PhpProject/sample.txt", 0740);
?>

chown() 函式

chown()函式嘗試將檔案filename的所有者更改為新使用者。請注意,只有超級使用者才能更改檔案的所有者。

chown(string $filename, string|int $user): bool

示例

請看以下示例:

<?php

   // File name and username to use
   $file_name= "index.php";
   $path = "/PhpProject/backup: " . $file_name ;
   $user_name = "root";

   // Set the user
   chown($path, $user_name);

   // Check the result
   $stat = stat($path);
   print_r(posix_getpwuid(fileowner($path)));
?>

chgrp() 函式

chgrp()函式嘗試將檔案filename的組更改為group。

chgrp(string $filename, string|int $group): bool

只有**超級使用者**可以隨意更改檔案的組;其他使用者可以將檔案的組更改為該使用者所屬的任何組。

示例

請看以下示例:

<?php
   $filename = "/PhpProject/sample.txt";
   $format = "%s's Group ID @ %s: %d\n";
   printf($format, $filename, date('r'), filegroup($filename));
   chgrp($filename, "admin");
   clearstatcache();  	// do not cache filegroup() results
   printf($format, $filename, date('r'), filegroup($filename));
?>

它將產生以下輸出

/PhpProject/sample.txt's Group ID @ Fri, 13 Oct 2023 07:42:21 +0200: 0
/PhpProject/sample.txt's Group ID @ Fri, 13 Oct 2023 07:42:21 +0200: 0

PHP – 建立目錄

計算機檔案儲存在本地儲存裝置(稱為**驅動器**)中,採用分層順序,其中一個目錄包含一個或多個檔案以及子目錄。作業系統Windows、Linux等中定義的相應DOS命令用於建立和管理目錄。

PHP提供目錄管理函式來建立目錄、更改當前目錄和刪除某個目錄。

本章討論在PHP中使用以下目錄函式:

mkdir() 函式

mkdir()函式建立一個新目錄,其路徑作為函式的引數之一給出。

mkdir(
   string $directory,
   int $permissions = 0777,
   bool $recursive = false,
   ?resource $context = null
): bool

引數

  • **$directory** – 第一個引數$directory是必需的。它是一個字串,包含要建立的新目錄的絕對路徑或相對路徑。

  • **$permissions** – 第二個引數$permissions是一個具有四個八進位制數字的八進位制數。第一位始終為零,第二位指定擁有者的許可權,第三位指定擁有者的使用者組的許可權,第四位指定其他所有人的許可權。

每一位都是每種許可權值的總和:

  • 1 = 執行許可權

  • 2 = 寫入許可權

  • 4 = 讀取許可權

$permissions引數的預設值為**0777**,這意味著目錄的建立啟用了執行、寫入和讀取許可權。

請注意,在Windows作業系統上工作時會忽略$permissions引數。

  • **$recursive** – 如果為true,則還會建立指定目錄的任何父目錄,並使用相同的許可權。

  • **$context** – 此可選引數是流資源。

mkdir()函式返回true或false,指示函式是否已成功執行。

示例

以下是一些mkdir()函式的示例。

以下對mkdir()的呼叫會在當前工作目錄內建立一個子目錄。點表示路徑是相對的。

$dir = "./mydir/";
mkdir($dir);

我們可以提供包含要建立的目錄的絕對路徑的字串引數。

$dir = "c:/newdir/";
mkdir($dir);

以下對mkdir()的呼叫包含當前目錄內的巢狀目錄結構,因為$recursive引數設定為true。

$dirs = "./dir1/dir2/dir3/";
mkdir($dirs, 0777, true);

Windows資源管理器將顯示巢狀目錄結構如下:

Create Directory

chdir() 函式

PHP中的chdir()函式對應於Linux/Windows中的**chdir**或**cd**命令。它會根據需要更改當前目錄。

chdir(string $directory): bool

此函式的字串引數是需要將當前目錄更改到的目錄的絕對路徑或相對路徑。它返回true或false。

getcwd() 函式

getcwd()函式的工作方式類似於Ubuntu Linux中的pwd命令,並返回當前工作目錄的路徑。

示例

使用以下程式碼片段,PHP在更改當前工作目錄之前和之後顯示當前工作目錄。在新當前目錄中建立了幾個檔案。使用scandir()函式列出這些檔案。

<?php
   echo "current directory: ". getcwd() . PHP_EOL;
   $dir = "./mydir";
   chdir($dir);
   echo "current directory changed to: ". getcwd() .PHP_EOL;

   $fp = fopen("a.txt", "w");
   fwrite($fp, "Hello World");
   fclose($fp);

   copy("a.txt", "b.txt");
   $dir = getcwd();
   foreach(scandir($dir) as $file)
   echo $file . PHP_EOL;
?>

它將產生以下輸出

current directory: C:\xampp\php
current directory changed to: C:\xampp\php\mydir
.
..
a.txt
b.txt

rmdir() 函式

rmdir()函式刪除路徑作為引數給出的某個目錄。要刪除的目錄必須為空。

$dir = "c:/newdir/";
rmdir($dir) or die("The directory is not present or not empty");

PHP – 列出檔案

Windows命令DIR和Linux命令ls都顯示當前目錄中的檔案列表。這些命令可以與不同的開關一起操作,以便對顯示的檔案列表應用條件。PHP提供了一些選項,可以透過程式設計方式列出給定目錄中的檔案。

readdir() 函式

PHP中的opendir()函式類似於fopen()函式。它返回目錄的控制代碼,以便可以以序列化方式讀取目錄的內容。

opendir(string $directory, ?resource $context = null): resource|false

此函式開啟一個目錄控制代碼,供後續的closedir()、readdir()和rewinddir()呼叫使用。

**readdir()**函式從**opendir()**函式返回的流控制代碼讀取下一個可用條目。

readdir(?resource $dir_handle = null): string|false

這裡,**dir_handle**是之前用opendir()開啟的目錄控制代碼。如果沒有指定,則假定為opendir()開啟的最後一個連結。

**closedir()**函式類似於**fclose()**函式。它關閉目錄控制代碼。

closedir(?resource $dir_handle = null): void

該函式關閉dir_handle指示的目錄流。該流必須先前已由opendir()開啟。

示例

以下PHP程式碼一次讀取當前登入目錄中的一個檔案。

<?php
   $dir = getcwd();
   
   // Open a known directory, and proceed to read its contents
   if (is_dir($dir)) {
      if ($dh = opendir($dir)) {
         while (($file = readdir($dh)) !== false) {
            echo "filename:" . $file . "\n";
         }
         closedir($dh);
      }
   }
?>

scandir() 函式

scandir()函式檢索給定目錄內的檔案和子目錄。

scandir(string $directory, 
int $sorting_order = SCANDIR_SORT_ASCENDING, 
?resource $context = null): array|false

預設情況下,“排序順序”為按字母順序升序排列。如果此可選引數設定為SCANDIR_SORT_DESCENDING,則排序順序變為按字母順序降序排列。如果將其設定為SCANDIR_SORT_NONE,則結果將未排序。

示例

使用以下PHP程式碼,scandir()函式返回給定目錄中檔案的陣列。

<?php
   $dir = "c:/xampp/php/mydir/";

   $files = scandir($dir);
   var_dump($files);
?>

它將產生以下輸出

array(4) {
   [0]=>
   string(1) "."
   [1]=>
   string(2) ".."
   [2]=>
   string(5) "a.txt"
   [3]=>
   string(5) "b.txt"
}

您可以使用**foreach**迴圈遍歷scandir()函式返回的陣列。

<?php
   $dir = "c:/xampp/php/mydir/";

   $files = scandir($dir);
   foreach ($files as $file)
   echo $file . PHP_EOL;
?>

它將產生以下輸出

.
..
a.txt
b.txt

PHP中的面向物件程式設計

我們可以想象我們的宇宙是由不同的物體組成的,例如太陽、地球、月亮等。同樣,我們可以想象我們的汽車是由不同的物體組成的,例如車輪、方向盤、齒輪等。同樣,面向物件程式設計的概念假設一切都是一個物件,並使用不同的物件實現軟體。

面向物件的概念

在詳細介紹之前,讓我們定義與面向物件程式設計相關的術語。

  • **類** – 這是程式設計師定義的資料型別,它包括區域性函式和區域性資料。您可以將類視為製作許多相同型別(或類)物件的模板。

  • **物件** – 類定義的資料結構的單個例項。您只定義一次類,然後建立屬於該類的許多物件。物件也稱為例項。

  • **成員變數** – 這些是在類中定義的變數。此資料對類外部不可見,可以透過成員函式訪問。建立物件後,這些變數稱為物件的屬性。

  • **成員函式** – 這些是在類中定義的函式,用於訪問物件資料。

  • **繼承** – 當一個類透過繼承父類的現有函式來定義時,這稱為繼承。子類將繼承父類所有或部分成員函式和變數。

  • **父類** – 被另一個類繼承的類。這也被稱為基類或超類。

  • **子類** – 從另一個類繼承的類。這也被稱為子類或派生類。

  • **多型性** – 這是一個面向物件的概念,其中相同的函式可以用於不同的目的。例如,函式名將保持不變,但它採用不同數量的引數,並且可以執行不同的任務。

  • **過載** – 一種多型性,其中某些或所有運算子根據其引數的型別具有不同的實現。類似地,函式也可以用不同的實現來過載。

  • **資料抽象** – 任何隱藏(抽象)實現細節的資料表示。

  • **封裝** – 指的是將所有資料和成員函式封裝在一起形成一個物件的概念。

  • **建構函式** – 指的是一種特殊的函式,每當從類中形成物件時,都會自動呼叫該函式。

  • **解構函式** – 指的是一種特殊的函式,每當物件被刪除或超出範圍時,都會自動呼叫該函式。

定義PHP類

在PHP中定義新類的通用形式如下:

<?php
   class phpClass {
      var $var1;
      var $var2 = "constant string";
      
      function myfunc ($arg1, $arg2) {
         [..]
      }
      [..]
   }
?>

以下是每一行的描述:

  • 特殊的形式**class**,後跟要定義的類的名稱。

  • 一組大括號,包含任意數量的變數宣告和函式定義。

  • 變數宣告以特殊的形式**var**開頭,後跟常規的$變數名;它們也可能具有對常值的初始賦值。

  • 函式定義看起來很像獨立的PHP函式,但它們是區域性於類的,將用於設定和訪問物件資料。

示例

這是一個定義Books型別類的示例:

<?php
   class Books {
      /* Member variables */
      var $price;
      var $title;
      
      /* Member functions */
      function setPrice($par){
         $this->price = $par;
      }
      
      function getPrice(){
         echo $this->price ."<br/>";
      }
      
      function setTitle($par){
         $this->title = $par;
      }
      
      function getTitle(){
         echo $this->title ." <br/>";
      }
   }
?>

變數**$this**是一個特殊變數,它指的是同一個物件,即自身。

在PHP中建立物件

定義好類之後,就可以建立任意數量的該類型別的物件。下面是一個使用new運算子建立物件的示例。

$physics = new Books;
$maths = new Books;
$chemistry = new Books;

這裡我們建立了三個物件,這些物件彼此獨立,各自存在。接下來我們將看到如何訪問成員函式和處理成員變數。

呼叫成員函式

建立物件後,就可以呼叫與該物件相關的成員函式。一個成員函式只能處理相關物件的成員變數。

下面的示例演示瞭如何透過呼叫成員函式來設定三本書的標題和價格。

$physics->setTitle( "Physics for High School" );
$chemistry->setTitle( "Advanced Chemistry" );
$maths->setTitle( "Algebra" );

$physics->setPrice( 10 );
$chemistry->setPrice( 15 );
$maths->setPrice( 7 );

現在,您可以呼叫另一個成員函式來獲取上面示例中設定的值。

$physics->getTitle();
$chemistry->getTitle();
$maths->getTitle();
$physics->getPrice();
$chemistry->getPrice();
$maths->getPrice();

這將產生以下結果:

Physics for High School
Advanced Chemistry
Algebra
10
15
7

建構函式

建構函式是一種特殊的函式,每當建立物件時都會自動呼叫。因此,我們可以充分利用這種特性,透過建構函式初始化許多內容。

PHP 提供了一個名為__construct()的特殊函式來定義建構函式。您可以向建構函式傳遞任意數量的引數。

下面的示例將為 Books 類建立一個建構函式,並在物件建立時初始化書籍的價格和標題。

function __construct( $par1, $par2 ) {
   $this->title = $par1;
   $this->price = $par2;
}

現在,我們不需要單獨呼叫 set 函式來設定價格和標題。我們只需要在物件建立時初始化這兩個成員變數。請檢視下面的示例:

$physics = new Books( "Physics for High School", 10 );
$maths = new Books ( "Advanced Chemistry", 15 );
$chemistry = new Books ("Algebra", 7 );

/* Get those set values */
$physics->getTitle();
$chemistry->getTitle();
$maths->getTitle();

$physics->getPrice();
$chemistry->getPrice();
$maths->getPrice();

這將產生以下結果:

Physics for High School
Advanced Chemistry
Algebra
10
15
7

解構函式

像建構函式一樣,您可以使用函式__destruct()定義解構函式。您可以在解構函式中釋放所有資源。

繼承

PHP 類定義可以使用 extends 子句從父類定義繼承。語法如下:

class Child extends Parent {
   <definition body>
}

繼承的效果是子類(或子類或派生類)具有以下特性:

  • 自動擁有父類所有成員變數宣告。

  • 自動擁有與父類相同的成員函式,這些函式(預設情況下)的工作方式與父類中的函式相同。

下面的示例繼承 Books 類,並根據需求新增更多功能。

class Novel extends Books {
   var $publisher;
   
   function setPublisher($par){
      $this->publisher = $par;
   }
   
   function getPublisher(){
      echo $this->publisher. "<br />";
   }
}

現在,除了繼承的函式外,Novel 類還保留了兩個額外的成員函式。

函式重寫

子類中的函式定義會覆蓋父類中同名函式的定義。在子類中,我們可以修改從父類繼承的函式的定義。

在下面的示例中,getPrice 和 getTitle 函式被重寫以返回一些值。

function getPrice() {
   echo $this->price . "<br/>";
   return $this->price;
}
   
function getTitle(){
   echo $this->title . "<br/>";
   return $this->title;
}

公共成員

除非另行指定,否則類的屬性和方法都是公共的。也就是說,它們可以在三種情況下訪問:

  • 從宣告它的類之外

  • 從宣告它的類內部

  • 從實現宣告它的類的另一個類內部

到目前為止,我們看到的所有成員都是公共成員。如果要限制類的成員的可訪問性,則可以將類成員定義為privateprotected

私有成員

透過將成員指定為私有,您可以將其可訪問性限制在宣告它的類中。私有成員不能從繼承宣告它的類的類中引用,也不能從類外部訪問。

可以使用成員前面的private關鍵字將類成員設為私有。

class MyClass {
   private $car = "skoda";
   $driver = "SRK";
   
   function __construct($par) {
   
      // Statements here run every time
      // an instance of the class
      // is created.
   }
   
   function myPublicFunction() {
      return("I'm visible!");
   }
   
   private function myPrivateFunction() {
      return("I'm  not visible outside!");
   }
}

當另一個類使用 extends 繼承MyClass類時,myPublicFunction() 將可見,$driver 也將可見。擴充套件類將無法感知或訪問 myPrivateFunction 和 $car,因為它們被宣告為私有的。

受保護成員

受保護的屬性或方法可在宣告它的類中訪問,也可在擴充套件該類的類中訪問。受保護的成員在這兩種類之外不可用。可以使用成員前面的protected關鍵字將類成員設為受保護。

這是 MyClass 的不同版本:

class MyClass {
   protected $car = "skoda";
   $driver = "SRK";

   function __construct($par) {
      // Statements here run every time
      // an instance of the class
      // is created.
   }
   
   function myPublicFunction() {
      return("I'm visible!");
   }
   
   protected function myPrivateFunction() {
      return("I'm  visible in child class!");
   }
}

介面

介面的定義是為了為實現者提供通用的函式名稱。不同的實現者可以根據自己的需求實現這些介面。可以說,介面是由開發人員實現的骨架。

從 PHP5 開始,可以像這樣定義介面:

interface Mail {
   public function sendMail();
}

然後,如果另一個類實現了該介面,則如下所示:

class Report implements Mail {
   // sendMail() Definition goes here
}

常量

常量有點像變數,因為它儲存一個值,但實際上更像一個函式,因為常量是不可變的。一旦聲明瞭常量,它就不會改變。

宣告一個常量很容易,就像在這個版本的 MyClass 中一樣:

class MyClass {
   const requiredMargin = 1.7;
   
   function __construct($incomingValue) {
   
      // Statements here run every time
      // an instance of the class
      // is created.
   }
}

在這個類中,requiredMargin 是一個常量。它使用關鍵字 const 宣告,在任何情況下都不能將其更改為 1.7 以外的任何值。請注意,常量的名稱前面沒有 $ 符號,變數名則有。

抽象類

抽象類是不能例項化,只能繼承的類。您可以使用關鍵字abstract宣告抽象類,如下所示:

從抽象類繼承時,必須透過子類定義父類宣告中標記為抽象的所有方法;此外,這些方法必須使用相同可見性定義。

abstract class MyAbstractClass {
   abstract function myAbstractFunction() {
   }
}

請注意,抽象類中的函式定義也必須以關鍵字 abstract 開頭。在非抽象類中擁有抽象函式定義是非法的。

static 關鍵字

將類成員或方法宣告為靜態,可以無需例項化類即可訪問它們。宣告為靜態的成員不能使用例項化類物件訪問(儘管可以使用靜態方法)。

試試下面的例子:

<?php
   class Foo {
      public static $my_static = 'foo';
      
      public function staticValue() {
         return self::$my_static;
      }
   }
	
   print Foo::$my_static . "\n";
   $foo = new Foo();
   
   print $foo->staticValue() . "\n";
?>	

final 關鍵字

PHP 5 引入了 final 關鍵字,它透過在定義前新增 final 來阻止子類覆蓋方法。如果類本身被定義為 final,則它不能被擴充套件。

下面的示例將導致致命錯誤:無法覆蓋最終方法 BaseClass::moreTesting()

<?php

   class BaseClass {
      public function test() {
         echo "BaseClass::test() called<br>";
      }
      
      final public function moreTesting() {
         echo "BaseClass::moreTesting() called<br>";
      }
   }
   
   class ChildClass extends BaseClass {
      public function moreTesting() {
         echo "ChildClass::moreTesting() called<br>";
      }
   }
?>

呼叫父建構函式

與其為子類編寫一個全新的建構函式,不如透過顯式呼叫父建構函式,然後執行子類例項化所需的任何操作來編寫它。這是一個簡單的例子:

class Name {
   var $_firstName;
   var $_lastName;
   
   function Name($first_name, $last_name) {
      $this->_firstName = $first_name;
      $this->_lastName = $last_name;
   }
   
   function toString() {
      return($this->_lastName .", " .$this->_firstName);
   }
}
class NameSub1 extends Name {
   var $_middleInitial;
   
   function NameSub1($first_name, $middle_initial, $last_name) {
      Name::Name($first_name, $last_name);
      $this->_middleInitial = $middle_initial;
   }
   
   function toString() {
      return(Name::toString() . " " . $this->_middleInitial);
   }
}

在這個例子中,我們有一個父類(Name),它有一個帶兩個引數的建構函式,還有一個子類(NameSub1),它有一個帶三個引數的建構函式。NameSub1 的建構函式透過使用 :: 語法顯式呼叫其父建構函式(傳遞其中兩個引數),然後設定一個附加欄位來工作。類似地,NameSub1 根據它覆蓋的父函式定義其非建構函式 toString() 函式。

注意 - 建構函式可以與類名相同。在上面的示例中已定義。

PHP – 類和物件

類和物件的概念是 PHP 面向物件程式設計方法的核心。是其物件的模板描述。它包括處理屬性的屬性和函式。物件是其類的例項。它以類中定義的屬性和函式為特徵。

Classes and Objects

在 PHP 中定義類

要定義類,PHP 有一個關鍵字“class”。同樣,PHP 提供關鍵字“new”來宣告任何給定類的物件。

在PHP中定義新類的通用形式如下:

<?php
   class phpClass {
      var $var1;
      var $var2 = "constant string";

      function myfunc ($arg1, $arg2) {
         [..]
      }
      [..]
   }
?>

關鍵字class後面是您要定義的類的名稱。類名遵循與 PHP 變數相同的命名約定。後面是一對大括號,包含任意數量的變數宣告(屬性)和函式定義。

變數宣告以另一個保留關鍵字var開頭,後面跟著傳統的$variable名稱;它們也可能具有對常量的初始賦值。

函式定義看起來很像獨立的 PHP 函式,但它們是區域性的類,將用於設定和訪問物件資料。類中的函式也稱為方法。

示例

這是一個定義 Book 型別的類的示例:

class Book {

   /* Member variables */
   var $price;
   var $title;

   /* Member functions */
   function setPrice($par){
      $this->price = $par;
   }

   function getPrice(){
      echo $this->price ."<br/>";
   }

   function setTitle($par){
      $this->title = $par;
   }

   function getTitle(){
      echo $this->title ." <br/>";
   }
}

偽變數$this在從物件上下文中呼叫方法時可用。$this引用呼叫物件。

Book 類有兩個成員變數(或屬性) - $title$price。成員變數(有時也稱為例項變數)通常每個物件的取值不同;例如,每本書的標題和價格都與其他書籍不同。

Book 類具有函式(在類中定義的函式稱為方法)setTitle() 和 setPrice()。這些函式是透過引用物件和引數呼叫的,用於分別設定標題和價格成員變數的值。

Book 類還具有getTitle()getPrice()方法。呼叫時,它們返回傳遞引用的物件的標題和價格。

定義類後,可以使用 new 運算子宣告一個或多個物件。

$b1 = new Book;
$b2 = new Book;

new運算子分配每個物件成員變數和方法所需的記憶體。這裡我們建立了兩個物件,這些物件彼此獨立,各自存在。

每個物件都可以使用“->”運算子訪問其成員變數和方法。例如,b1物件的$title屬性是“$b1->title”,要呼叫setTitle()方法,請使用“$b1->setTitle()”語句。

要設定b1物件的標題和價格,

$b1->setTitle("PHP Programming");
$b1->setPrice(450);

類似地,以下語句獲取b1書的標題和價格:

echo $b1->getPrice();
echo $b1->getTitle();

示例

下面是定義 Book 類、宣告兩個物件並呼叫成員函式的完整 PHP 指令碼。

<?php
   class Book {
   
      /* Member variables */
      var $price;
      var $title;

      /* Member functions */
      function setPrice($par){
         $this->price = $par;
      }

      function getPrice(){
         echo $this->price ."\n";
      }

      function setTitle($par){
         $this->title = $par;
      }

      function getTitle(){
         echo $this->title ."\n";
      }
   }

   $b1 = new Book;
   $b2 =new Book;

   $b1->setTitle("PHP Programming");
   $b1->setPrice(450);
   $b2->setTitle("PHP Fundamentals");
   $b2->setPrice(275);
   $b1->getTitle();
   $b1->getPrice();
   $b2->getTitle();
   $b2->getPrice();
?>

它將產生以下輸出

PHP Programming
450
PHP Fundamentals
275

PHP – 建構函式和解構函式

與大多數面向物件的語言一樣,您也可以在 PHP 中的類中定義建構函式。當您使用 new 運算子宣告物件時,其成員變數不會被賦值。建構函式用於在宣告時初始化每個新物件。PHP 還支援使用解構函式,該函式會在物件不再有任何引用時將其從記憶體中銷燬。

__construct() 函式

PHP 提供了一個 __construct() 函式來初始化物件。

__construct(mixed ...$values = ""): void

類中的構造方法會在每個新建立的物件上自動呼叫。請注意,定義建構函式不是強制性的。但是,如果存在,它適合物件在使用前可能需要的任何初始化。

您可以向建構函式傳遞任意數量的引數。__construct() 函式沒有任何返回值。

讓我們在上一章中使用的 Book 類中定義一個建構函式

<?php
   class Book {
   
      /* Member variables */
      var $price;
      var $title;

      /*Constructor*/
      function __construct(){
         $this->title = "PHP Fundamentals";
         $this->price = 275;
      }
	  
      /* Member functions */
      function getPrice() {
         echo "Price: $this->price \n";
      }

      function getTitle(){
         echo "Title: $this->title \n";
      }    
   }

   $b1 = new Book;
   $b1->getTitle();
   $b1->getPrice();
?>

它將產生以下輸出

Title: PHP Fundamentals
Price: 275

引數化建構函式

由於建構函式在物件聲明後立即被呼叫,因此 $b1 的成員變數已初始化,而無需呼叫 setTitle() 和 setPrice() 方法。但是,此建構函式將為每個物件呼叫,因此每個物件都具有相同標題和價格屬性值。

要使用不同的值初始化每個物件,請使用引數定義__construct()函式。

__construct()函式的定義更改為:

function __construct($param1, $param2) {
   $this->title = $param1;
   $this->price = $param2;
}

要初始化物件,請在宣告中將值傳遞給括號內的引數。

$b1 = new Book("PHP Fundamentals", 375);

示例

現在,您可以使每個物件的成員變數具有不同的值。

<?php
   class Book {
   
      /* Member variables */
      var $price;
      var $title;

      /*Constructor*/
      function __construct($param1, $param2) {
         $this->title = $param1;
         $this->price = $param2;
      }

      /* Member functions */
      function getPrice(){
         echo "Price: $this->price \n";
      }

      function getTitle(){
         echo "Title: $this->title \n";
      }
   }

   $b1 = new Book("PHP Fundamentals", 375);
   $b2 = new Book("PHP Programming", 450);

   $b1->getTitle();
   $b1->getPrice();
   $b2->getTitle();
   $b2->getPrice();
?>

它將產生以下輸出

Title: PHP Fundamentals
Price: 375
Title: PHP Programming
Price: 450

建構函式過載

方法過載是面向物件程式設計中的一個重要概念,其中一個類可能有多個建構函式定義,每個建構函式具有不同數量的引數。但是,PHP 不支援方法過載。可以透過在建構函式中使用具有預設值的引數來克服此限制。

將 __construct() 函式更改為:

function __construct($param1="PHP Basics", $param2=380) {
   $this->title = $param1;
   $this->price = $param2;
}

現在,宣告一個物件而不傳遞引數,另一個物件傳遞引數。一個不帶引數的物件將使用預設引數初始化,另一個物件將使用傳遞的值初始化。

$b1 = new Book();
$b2 = new Book("PHP Programming", 450);

它將產生以下輸出

Title: PHP Basics
Price: 380
Title: PHP Programming
Price: 450

建構函式中的型別宣告

PHP 7.0 及以後版本允許為函式引數宣告標量型別,因此建構函式 `__construct()` 可以定義為:

function __construct(string $param1="PHP Basics", int $param2=380) {
   $this->title = $param1;
   $this->price = $param2;
}

在 PHP 的早期版本中,允許使用類名來定義建構函式,但是自 PHP 8.0 起,此特性已被棄用。

__destruct() 函式

PHP 也具有 `__destruct()` 函式。它實現了類似於其他面嚮物件語言(如 C++)中的解構函式的概念。一旦沒有其他對特定物件的引用,就會呼叫析構方法。

__destruct(): void

__destruct() 函式沒有任何引數,也沒有任何返回值。可以透過在函式內部放置 `var_dump($this)` 來驗證 `__destruct()` 函式在任何物件超出作用域時自動呼叫的事實。

如上所述,**$this** 攜帶對呼叫物件的引用,轉儲顯示成員變數被設定為 NULL。

在 Book 類中新增解構函式如下:

function __destruct() {
   var_dump($this);
   echo "object destroyed";
}

程式退出時,將顯示以下**輸出**:

object(Book)#1 (2) {
   ["price"]=>
   NULL
   ["title"]=>
   NULL
}
object destroyed

PHP – 訪問修飾符

在 PHP 中,關鍵字 **public、private** 和 **protected** 被稱為**訪問修飾符**。這些關鍵字控制類屬性和方法的可訪問性或可見性範圍。在宣告成員變數和定義成員函式時,會在前面加上這些關鍵字中的一個。

PHP 程式碼是否可以自由訪問類成員,或者是否限制其訪問,或者是否有條件訪問,取決於這些關鍵字:

  • **public** – 類成員可以從任何地方訪問,即使是從類的作用域之外,但只能透過物件引用。

  • **private** – 類成員只能在類本身內部訪問。它阻止外部類訪問成員,即使使用類例項的引用也不行。

  • **protected** – 成員只能在類及其子類內部訪問,其他地方都不能訪問。

資料封裝的原則的面向物件程式設計方法學的基石。它指的是將物件的成員變數或屬性與類外部的環境隔離開來的機制,只允許透過類中可用的方法或函式進行受控訪問。

為了實現封裝,類的成員變數被設定為**private**,而方法被設定為**public**。

Access Modifiers 1

公共成員

在 PHP 中,類成員(成員變數和成員函式)預設為 public。

示例

在下面的程式中,物件的成員變數 title 和 price 可以自由地從類外部訪問,因為它們預設為 public,除非另有指定。

<?php
   class Book {
      /* Member variables */
      var $price;
      var $title;

      /*Constructor*/
      function __construct(string $param1="PHP Basics", int $param2=380) {
         $this->title = $param1;
         $this->price = $param2;
      }

      function getPrice() {
         echo "Title: $this->price \n";
      }

      function getTitle() {
         echo "Price: $this->title \n";
      }
   }
   $b1 = new Book();
   echo "Title : $b1->title Price: $b1->price";
?>

它將產生以下輸出

Title : PHP Basics Price: 380

私有成員

如上所述,封裝的原則要求不應該直接訪問成員變數。只有方法才能訪問資料成員。因此,我們需要將成員變數設定為 private,並將方法設定為 public。

<?php
   class Book {
      /* Member variables */
      private $price;
      private $title;

      /*Constructor*/
      function __construct(string $param1="PHP Basics", int $param2=380) {
         $this->title = $param1;
         $this->price = $param2;
      }

      public function getPrice() {
         echo "Price: $this->price \n";
      }

      public function getTitle() {
         echo "Title: $this->title \n;";
      }
   }
   $b1 = new Book();
   $b1->getTitle();
   $b1->getPrice(); 
   echo "Title : $b1->title Price: $b1->price";
?>

輸出

現在,`getTitle()` 和 `getPrice()` 函式是 public 的,可以訪問私有成員變數 title 和 price。但是,在嘗試直接顯示 title 和 price 時,會遇到錯誤,因為它們不是 public 的。

Title: PHP Basics
Price: 380
Fatal error: Uncaught Error: Cannot access private property 
Book::$title in hello.php:31

受保護成員

指定對類成員的受保護訪問的效果在類繼承的情況下是有效的。我們知道,public 成員可以從類外部的任何地方訪問,而 private 成員則不允許從類外部的任何地方訪問。

**protected** 關鍵字允許訪問同一類的物件及其繼承類的物件,而拒絕任何其他環境訪問。

讓我們將 Book 類示例中的 title 成員設定為 protected,並將 price 保持為 private。

class Book {
   /* Member variables */
   private $price;
   protected $title;
   # rest of the code kept as it is
}
$b1 = new Book();
$b1->getTitle();
$b1->getPrice();

PHP 允許訪問這兩個成員變數,因為物件屬於同一類。

讓我們新增一個繼承 Book 類的 **mybook** 類:

class mybook extends Book {
   # no additional members defined
}

其物件仍然能夠訪問成員變數,因為子類繼承了父類的 public 和 protected 成員。

但是,將 **mybook** 類作為一個獨立的類(不擴充套件 Book 類),並定義一個 `getmytitle()` 函式,該函式嘗試訪問 Book 類的受保護的 title 成員變數。

class mybook {
   public function getmytitle($b) {
      echo "Title: $b->title <br/>";
   }
}
$b1 = new mybook();
$b = new Book();
$b1->getmytitle($b);

由於 `getmytitle()` 函式試圖列印 Book 物件的 title,因此會引發顯示 **Cannot access protected property Book::$title** 的錯誤訊息。

示例

嘗試執行以下程式碼:

<?php
   class Book {
      private $price;
      protected $title;
      function __construct(string $param1="PHP Basics", int $param2=380) {
         $this->title = $param1;
         $this->price = $param2;
      }
      public function getPrice(){
         echo "Price: $this->price <br/>";
      }
      public function getTitle(){
         echo "Title: $this->title <br/>";
      }
   }
   class mybook {
      public function getmytitle($b) {
         echo "Title: $b->title <br/>";
      }
   }
   $b1 = new mybook();
   $b = new Book();
   $b1->getmytitle($b);
?>

它將產生以下輸出

PHP Fatal error:  Uncaught Error: Cannot access protected property 
   Book::$title in /home/cg/root/97848/main.php:18

因此,可以看出,受保護的成員只能被同一類和繼承類的物件訪問。對於所有其他環境,受保護的成員都是不可訪問的。

可訪問性規則可以由下表概括:

Access Modifiers 2

PHP – 繼承

繼承是面向物件程式設計方法學的基石之一。繼承是一種軟體建模方法,它能夠擴充套件現有類的功能來構建新類,而不是從頭開始構建。

PHP 提供了在其物件模型中實現繼承的所有功能。在 PHP 軟體開發中加入繼承可以重用程式碼,消除冗餘程式碼重複,並實現邏輯組織。

假設您需要設計一個新類,其大部分功能已經在現有類中定義好了。繼承允許您擴充套件現有類,新增或刪除其功能並開發新類。事實上,PHP 有 "extends" 關鍵字來建立現有類和新類之間的繼承關係。

class newclass extends oldclass {
   ...
   ...
}

當一個新類(以下稱為繼承類、子類、子類等)與現有類(稱為基類、超類、父類等)具有 "IS A" 關係時,繼承就會出現。

PHP Inheritence

在 PHP 中,當透過擴充套件另一個類來定義一個新類時,子類會繼承父類的 public 和 protected 方法、屬性和常量。您可以自由地覆蓋繼承方法的功能,否則它將保留在父類中定義的功能。

示例

請看以下示例:

<?php
   class myclass {
      public function hello() {
         echo "Hello from the parent class" . PHP_EOL;      
      }
      public  function thanks() {
         echo "Thank you from parent class" . PHP_EOL;
      }
   }
   class newclass extends myclass {
      public function thanks() {
         echo "Thank you from the child class" . PHP_EOL;
      }
   }

   # object of parent class
   $obj1 = new myclass;
   $obj1->hello();
   $obj1->thanks();

   # object of child class
   $obj2 = new newclass;
   $obj2->hello();
   $obj2->thanks();
?>

它將產生以下輸出

Hello from the parent class
Thank you from parent class
Hello from the parent class
Thank you from the child class

如前所述,子類繼承父類的 public 和 protected 成員(屬性和方法)。子類可以引入額外的屬性或方法。

在下面的示例中,我們使用 **Book 類**作為父類。在這裡,我們建立一個擴充套件 Book 類的 **ebook 類**。新類有一個額外的屬性 - **format**(指示電子書的檔案格式 - EPUB、PDF、MOBI 等)。ebook 類定義了兩個新方法來初始化和輸出電子書資料 - **getebook()** 和 **dispebook()**。

示例

繼承示例的完整程式碼如下:

<?php
   class Book {
   
      /* Member variables */
      protected int $price;
      protected string $title;

      public function getbook(string $param1, int $param2) {
         $this->title = $param1;
         $this->price = $param2;
      }
      public function dispbook() {
         echo "Title: $this->title Price: $this->price \n";
      }
   }

   class ebook extends Book {
      private string $format;
      public function getebook(string $param1, int $param2, string $param3) {
         $this->title = $param1;
         $this->price = $param2;
         $this->format = $param3;
      }
      public function dispebook() {
         echo "Title: $this->title Price: $this->price\n";
         echo "Format: $this->format \n";
      }
   }
   $eb = new ebook;
   $eb->getebook("PHP Fundamentals", 450, "EPUB");
   $eb->dispebook();
?>

瀏覽器**輸出**如下所示:

Title: PHP Fundamentals Price: 450
Format: EPUB

如果您仔細檢視 `getebook()` 函式,前兩個賦值語句實際上是 `getbook()` 函式,`ebook` 類繼承了該函式。因此,我們可以使用 `parent` 關鍵字和作用域解析運算子來呼叫它。

將 `getebook()` 函式程式碼更改為以下內容:

public function getebook(string $param1, int $param2, string $param3) {
   parent::getbook($param1, $param2);
   $this->format = $param3;
}

類似地,`dispebook()` 函式中的第一個 `echo` 語句被對父類中 `dispbook()` 函式的呼叫所取代:

public function dispebook() {
   parent::dispbook();
   echo "Format: $this->format<br/>";
}

繼承中的建構函式

父類的建構函式會被子類繼承,但是如果子類定義了建構函式,則不能直接在子類中呼叫它。

為了執行父建構函式,需要在子建構函式中呼叫 `parent::__construct()`。

示例

請看以下示例:

<?php
   class myclass{
      public function __construct(){
         echo "This is parent constructor". PHP_EOL;
      }
   }
   class newclass extends myclass {
      public function __construct(){
         parent::__construct();
         echo "This is child class destructor" . PHP_EOL;
      }
   }
   $obj = new newclass();
?>

它將產生以下輸出

This is parent constructor
This is child class destructor

但是,如果子類沒有建構函式,那麼它可以像普通的類方法一樣從父類繼承(如果它沒有宣告為 private)。

示例

請看以下示例:

<?php
   class myclass{
      public function __construct(){
         echo "This is parent constructor". PHP_EOL;
      }
   }
   class newclass extends myclass{ }
   $obj = new newclass();
?>

它將產生以下輸出

This is parent constructor

PHP 不允許透過擴充套件多個父類來開發類。您可以進行**層次繼承**,其中類 B 擴充套件類 A,類 C 擴充套件類 B,依此類推。但是 PHP 不支援**多重繼承**,其中類 C 試圖同時擴充套件類 A 和類 B。但是,我們可以擴充套件一個類並實現一個或多個**介面**。我們將在後續章節中學習介面。

PHP – 類常量

PHP 允許在類中定義一個識別符號為“類常量”,其值為常量值,該值在每個類中保持不變。為了與類中的變數或屬性區分開來,常量的名稱前面不加通常的“$”符號,而是用“const”限定符定義。請注意,PHP 程式還可以使用 `define()` 函式建立全域性常量。

常量的預設可見性是 public,儘管可以在定義中使用其他修飾符。常量的值必須是一個表示式,而不是一個變數,也不是一個函式呼叫/屬性。常量的值可以透過類名使用作用域解析運算子來訪問。但在方法內部,可以透過 `self` 變數來引用它。

class SomeClass {
   const CONSTANT = 'constant value';
}
echo SomeClass::CONSTANT;

**常量名稱區分大小寫**。按照慣例,常量的名稱使用大寫字母。

示例

此示例演示瞭如何定義和訪問類常量:

<?php
   class square {
      const PI=M_PI;
      var $side=5;
      function area() {
         $area=$this->side**2*self::PI;
         return $area;
      }
   }
   $s1=new square();
   echo "PI=". square::PI . "\n";
   echo "area=" . $s1->area();
?>

它將產生以下輸出

PI=3.1415926535898
area=78.539816339745

類常量作為表示式

在此示例中,類常量被賦值一個表示式:

<?php
   const X = 22;
   const Y=7;

   class square {
      const PI=X/Y;
      var $side=5;
      function area() {
         $area=$this->side**2*self::PI;
         return $area;
      }
   }
   $s1=new square();
   echo "PI=". square::PI . "\n";
   echo "area=" . $s1->area();
?>

它將產生以下輸出

PI=3.1428571428571
area=78.571428571429

類常量可見性修飾符

請看以下示例:

<?php
   class example {
      const X=10;
      private const Y=20;
   }
   $s1=new example();
   echo "public=". example::X. "\n";
   echo "private=" . $s1->Y ."\n";
   echo "private=" . $example::Y ."\n";
?>

它將產生以下輸出

public=10
PHP Notice:  Undefined property: example::$Y in  line 11

private=
PHP Fatal error:  Uncaught Error: Cannot access private const example::Y

PHP – 抽象類

PHP 的保留字列表包括 "abstract" 關鍵字。當用 "abstract" 關鍵字定義一個類時,它不能被例項化,也就是說,您不能宣告該類的新的物件。抽象類可以被另一個類擴充套件。

abstract class myclass {
   // class body
}

如上所述,**您不能宣告此類的物件**。因此,以下語句:

$obj = new myclass;

將導致如下所示的**錯誤**訊息:

PHP Fatal error:  Uncaught Error: Cannot instantiate abstract class myclass

抽象類可以包含屬性、常量或方法。類成員可以是 public、private 或 protected 型別。類中的一個或多個方法也可以定義為 abstract。

如果類中的任何方法是 abstract 的,則類本身必須是抽象類。換句話說,普通類不能包含抽象方法。

這將引發**錯誤**:

class myclass {
   abstract function myabsmethod($arg1, $arg2);
   function mymethod() #this is a normal method {
      echo "Hello";
   }
}

**錯誤訊息**將顯示為:

PHP Fatal error:  Class myclass contains 1 abstract method 
and must therefore be declared abstract

您可以使用抽象類作為父類,並用子類擴充套件它。但是,子類必須為父類中的每個抽象方法提供具體的實現,否則將遇到錯誤。

示例

在下面的程式碼中,**myclass** 是一個帶有 **myabsmethod()** 作為抽象方法的**抽象類**。它的派生類是 **mynewclass**,但是它沒有在其父類中實現抽象方法。

<?php
   abstract class myclass {
      abstract function myabsmethod($arg1, $arg2);
      function mymethod() {
         echo "Hello";
      }
   }
   class newclass extends myclass {
      function newmethod() {
         echo "World";
      }
   }
   $m1 = new newclass;
   $m1->mymethod();
?>

在這種情況下,**錯誤訊息**是:

PHP Fatal error:  Class newclass contains 1 abstract method and must 
therefore be declared abstract or implement the remaining 
methods (myclass::myabsmethod) 

這表明 newclass 應該實現抽象方法,或者應該宣告為抽象類。

示例

在下面的 PHP 指令碼中,我們有一個名為 marks 的抽象類,其中包含一個抽象方法 percent()。另一個名為 student 的類擴充套件了 marks 類並實現了它的 percent() 方法。

<?php
   abstract class marks {
      protected int $m1, $m2, $m3;
      abstract public function percent(): float;
   }

   class student extends marks {
      public function __construct($x, $y, $z) {
         $this->m1 = $x;
         $this->m2 = $y;
         $this->m3 = $z;
      }
      public function percent(): float {
         return ($this->m1+$this->m2+$this->m3)*100/300;
      }
   }

   $s1 = new student(50, 60, 70);
   echo "Percentage of marks: ". $s1->percent() . PHP_EOL;
?>

它將產生以下輸出

Percentage of marks: 60

PHP 中介面和抽象類的區別

PHP 中抽象類的概念與介面非常相似。但是,介面和抽象類之間存在一些區別。

抽象類 介面
使用 abstract 關鍵字定義抽象類 使用 interface 關鍵字定義介面
抽象類不能被例項化 介面不能被例項化。
抽象類可以包含普通方法和抽象方法 介面必須僅宣告帶引數和返回型別的方法,而不能包含任何方法體。
子類擴充套件抽象類,必須實現所有抽象方法 另一個類必須實現介面,並且必須提供介面中所有方法的功能。
可以具有公共、私有或受保護的屬性 介面中不能宣告屬性

PHP – 介面

正如類是其物件的模板一樣,PHP 中的介面可以稱為類的模板。我們知道,當例項化一個類時,類中定義的屬性和方法都可用。類似地,PHP 中的介面宣告方法及其引數和返回值。這些方法沒有任何方法體,即介面中未定義任何功能。

具體類必須實現介面中的方法。換句話說,當一個類實現一個介面時,它必須為介面中的所有方法提供功能。

介面的定義方式與類的定義方式相同,只是使用關鍵字“interface”代替 class。

interface myinterface {
   public function myfunction(int $arg1, int $arg2);
   public function mymethod(string $arg1, int $arg2);
}

請注意,介面內部的方法沒有提供任何功能。這些方法的定義必須由實現此介面的類提供。

當我們定義子類時,我們使用關鍵字“extends”。在這種情況下,該類必須使用關鍵字“implements”。

介面中宣告的所有方法都必須定義,並且引數和返回值的數量和型別必須相同。

class myclass implements myinterface {
   public function myfunction(int $arg1, int $arg2) {
      ## implementation of myfunction;
   }
   public function mymethod(string $arg1, int $arg2) {
      # implementation of mymethod;
   }
}

注意,介面中宣告的所有方法都必須是公共的。

示例

讓我們定義一個名為 shape 的介面。形狀具有一定的面積。您有不同幾何形狀的形狀,例如矩形、圓形等,每個形狀都有一個面積,用不同的公式計算。因此,shape 介面宣告一個返回浮點值的方法 area()。

interface shape {
   public function area(): float;
}

接下來,我們將定義一個實現 shape 介面的 circle 類,要實現該介面,類必須提供介面中函式的具體實現。這裡,circle 類中的 area() 函式計算給定半徑的圓的面積。

class circle implements shape {
   var $radius;
   public function __construct($arg1) {
      $this->radius = $arg1;
   }
   public function area(): float {
      return pow($this->radius,2)*pi();
   }
}

現在我們可以宣告一個 circle 類的物件,並呼叫 area() 方法。

$cir = new circle(5);
echo "Radius : " . $cir->radius .  " Area of Circle: " . $cir->area(). PHP_EOL;

只要實現類提供了介面中每個方法的功能,任何數量的類(可能彼此無關)都可以實現一個介面。

這是一個實現 shape 介面的 Square 類。area() 方法返回 side 屬性的平方。

class square implements shape {
   var $side;
   public function __construct($arg1) {
      $this->side = $arg1; 
   }
   public function area(): float {
      return pow($this->side, 2);
   }
}

同樣,建立一個 Square 物件並呼叫 area() 方法。

示例

以下是 shape 介面的完整程式碼,由 circle 和 Square 類實現:

<?php
   interface shape {
      public function area(): float;
   }

   class square implements shape {
      var $side;
      public function __construct($arg1) {
         $this->side = $arg1; 
      }
      public function area(): float {
         return pow($this->side, 2);
      }
   }
   class circle implements shape {
      var $radius;
      public function __construct($arg1) {
         $this->radius = $arg1;
      }
      public function area(): float {
         return pow($this->radius,2)*pi();
      }
   }

   $sq = new square(5);
   echo "Side: " . $sq->side .  " Area of Square: ". $sq->area() . PHP_EOL;

   $cir = new circle(5);
   echo "Radius: " . $cir->radius .  " Area of Circle: " . $cir->area(). PHP_EOL;
?>

它將產生以下輸出

Side: 5 Area of Square: 25
Radius: 5 Area of Circle: 78.539816339745

PHP 中的多重繼承

PHP 沒有提供構建擴充套件兩個父類的子類的功能。換句話說,語句:

class child extends parent1, parent2 

不被接受。但是,PHP 確實支援具有擴充套件一個父類並實現一個或多個介面的子類。

讓我們來看下面的例子,它展示了一個擴充套件另一個類並實現介面的類。

首先是父類 marks。它有三個例項變數或屬性 $m1、$m2、$m3,分別代表三個科目的分數。提供了一個建構函式來初始化物件。

class marks {
   protected int $m1, $m2, $m3;
   public function __construct($x, $y, $z) {
      $this->m1 = $x;
      $this->m2 = $y;
      $this->m3 = $z;
   }
}

現在我們提供一個名為 percent 的介面,它宣告一個方法 percent(),該方法應該返回一個浮點數,但沒有函式體。

interface percent {
   public function percent(): float;
}

現在我們開發一個擴充套件 marks 類併為介面中的 percent() 方法提供實現的類。

class student extends marks implements percent {
   public function percent(): float {
      return ($this->m1+$this->m2+$this->m3)*100/300;
   }
}

student 類繼承了父建構函式,但提供了 parent() 方法的實現,該方法返回分數的百分比。

示例

完整的程式碼如下:

<?php
   class marks {
      protected int $m1, $m2, $m3;
      public function __construct($x, $y, $z) {
         $this->m1 = $x;
         $this->m2 = $y;
         $this->m3 = $z;
      }
   }
   interface percent {
      public function percent(): float;
   }

   class student extends marks implements percent {
      public function percent(): float {
         return ($this->m1+$this->m2+$this->m3)*100/300;
      }
   }

   $s1 = new student(50, 60, 70);
   echo "Percentage of marks: ". $s1->percent() . PHP_EOL;
?>

它將產生以下輸出

Percentage of marks: 60

PHP 中的介面定義了一個方法框架,類使用該框架來提供自己不同的但具體的實現。

PHP – 特性 (Traits)

在 PHP 中,一個類只能繼承自一個父類,PHP 中未定義多重繼承。PHP 中的特性是為了克服這個限制而引入的。您可以在特性中定義一個或多個方法,這些方法可以在各種獨立的類中自由重用。

語法

使用以下語法使用“trait”關鍵字:

trait mytrait {
   function method1() {
      /*function body*/
   }

   function method2() {
      /*function body*/
   }
}

為了能夠呼叫特性中的方法,需要使用 use 關鍵字將其提供給另一個類。

示例

特性類似於類,但僅用於以細粒度和一致的方式組合功能。無法自行例項化特性。

<?php
   trait mytrait {
      public function hello() {
         echo "Hello World from " . __TRAIT__ . "";
      }
   }
   class myclass {
      use mytrait;
   }
   $obj = new myclass();
   $obj->hello();
?>

它將產生以下輸出

Hello World from mytrait

示例

一個特性可以在多個類中使用。下面的例子有一個包含 avg() 函式的 mytrait。它在 marks 類中使用。percent() 方法內部呼叫特性中的 avg() 函式。

請看以下示例:

<?php
   trait mytrait {
      function avg($x, $y) {
         return ($x+$y)/2;
      }
   }
   class marks {
      use mytrait;
      private int $m1, $m2;
      function __construct($x, $y) {
         $this->m1 = $x;
         $this->m2 = $y;
      }
      function percent():float {
         return $this->avg($this->m1, $this->m2);
      }
   }
   $obj = new marks(50, 60);
   echo "percentage: " . $obj->percent();
?>

它將產生以下輸出

percentage: 55

使用多個特性

一個類可以使用多個特性。這裡我們有兩個特性,每個特性都有一個函式,分別執行兩個數字的加法和乘法。兩者都在第三個類中使用。

<?php
   trait addition {
      function add($x, $y) {
         return $x+$y;
      }
   }

   trait multiplication {
      function multiply($x, $y) {
         return $x*$y;
      }
   }

   class numbers {
      use addition, multiplication;
      private int $m1, $m2;
      function __construct($x, $y) {
         $this->m1 = $x;
         $this->m2 = $y;
      }
      function calculate():array {
         $arr = [$this->add($this->m1, $this->m2), $this->multiply($this->m1, $this->m2)];
         return $arr;
      }
   }

   $obj = new numbers(50, 60);
   $res = $obj->calculate();
   echo "Addition: " . $res[0] . PHP_EOL;
   echo "Multiplication: " . $res[1] . PHP_EOL;
?>

它將產生以下輸出

Addition: 110
Multiplication: 3000

覆蓋特性函式

當一個類使用某個特性時,它的函式就像子類繼承父方法一樣可用。特性函式也可以被重寫。

<?php
   trait mytrait {
      public function sayHello() {
         echo 'Hello World!';
      }
   }

   class myclass {
      use mytrait;
      public function sayHello() {
         echo 'Hello PHP!';
      }
   }

   $o = new myclass();
   $o->sayHello();
?>

它將產生以下輸出

Hello PHP!

“insteadof”關鍵字

有時,兩個或更多特性可能具有相同名稱的函式。因此,在類中使用它們會產生歧義的情況。PHP 提供 insteadof 關鍵字來告訴解析器您打算使用哪個特性的函式。

<?php
   trait mytrait {
      public function sayHello() {
         echo 'Hello World!';
      }
   }

   trait newtrait {
      public function sayHello() {
         echo 'Hello PHP!';
      }
   }

   class myclass {
      use mytrait, newtrait{
         newtrait::sayHello insteadof mytrait;
      }
   }

   $o = new myclass();
   $o->sayHello();
?>

它將產生以下輸出

Hello PHP!

特性函式的別名

如果您希望能夠呼叫來自兩個特性的函式,即使它們具有相同名稱的函式,一種解決方法是對其中一個函式指定別名。

示例

在下面的示例中,我們將 mytrait 中的 sayHello() 稱為 hello():

<?php
   trait mytrait {
      public function sayHello() {
         echo 'Hello World!' . PHP_EOL;
      }
   }

   trait newtrait {
      public function sayHello() {
         echo 'Hello PHP!' . PHP_EOL;
      }
   }

   class myclass {
      use mytrait, newtrait{
         mytrait::sayHello as hello;
         newtrait::sayHello insteadof mytrait;
      }
   }

   $o = new myclass();
   $o->hello();
   $o->sayHello();
?>

它將產生以下輸出

Hello World!
Hello PHP!

PHP – 靜態方法

PHP 中的“static”關鍵字用於在 PHP 類中定義靜態屬性和靜態方法。需要注意的是,static 關鍵字也用於定義靜態變數和靜態匿名函式。本章討論 PHP 類中的靜態方法。

在類定義中,用 static 修飾符宣告的函式成為其靜態方法。

class myclass {
   public static function myStaticMethod() {
      // ...
}

您不需要建立類的例項即可呼叫其靜態方法。靜態方法透過類名和作用域解析運算子來呼叫。靜態方法呼叫的語法為:

myclass::myStaticMethod();

由於靜態方法無需建立類的例項即可呼叫,因此偽變數 $this 在靜態方法內部不可用。靜態方法允許被物件呼叫,儘管將例項方法作為靜態方法呼叫會引發錯誤。

示例

請看以下示例:

<?php
   class myclass {
   
      /* Member variables */
      static int $var1 = 0;
      public static function mystaticmethod() {
         echo "This is a static method".  PHP_EOL;
      }
      public function myinstancemethod() {
         echo "This is an instance method".  PHP_EOL;
      }
   }

   myclass::mystaticmethod();
   $obj = new myclass;
   $obj->myinstancemethod();
   $obj->mystaticmethod();
   myclass::myinstancemethod();
?>

它將產生以下輸出

This is a static method
This is an instance method
This is a static method
PHP Fatal error:  Uncaught Error: Non-static method 
myclass::myinstancemethod() cannot be called statically

靜態方法中的“self”關鍵字

如果您需要從同一類中定義的例項方法內部呼叫靜態方法,則必須使用 self 關鍵字引用類名,後跟作用域解析運算子(例如 self::mystaticmethod)

<?php
   class myclass {
   
      /* Member variables */
      static int $var1 = 0;
      public static function mystaticmethod() {
         echo "This is a static method".  PHP_EOL;
      }
      public function myinstancemethod() {
         echo "This is an instance method".  PHP_EOL;  
         echo "calling static method from instance method" . PHP_EOL;
         self::mystaticmethod();
      }
   }

   $obj = new myclass;
   $obj->myinstancemethod();
?>

它將產生以下輸出

This is an instance method
calling static method from instance method
This is a static method

使用“parent”關鍵字

在繼承的情況下,基類中定義的靜態方法可以透過派生類的物件或從派生類的例項方法內部呼叫,方法是使用“parent”關鍵字引用它。

示例

請看以下示例:

<?php
   class myclass {
   
      /* Member variables */
      static int $var1 = 0;
      public static function mystaticmethod() {
         echo "This is a static method".  PHP_EOL;
      }
      public function myinstancemethod() {
         echo "This is an instance method".  PHP_EOL;
         echo "calling static method from instance method" . PHP_EOL;
         self::mystaticmethod();
      }
   }

   class mynewclass extends myclass {
      public function myfunction() {
         echo "This an instance method of the derived class" . PHP_EOL;
         echo "Calling static method of the parent class" . PHP_EOL;
         parent::mystaticmethod();
      }
   }
   $obj = new mynewclass;
   mynewclass::mystaticmethod();
   $obj->myfunction();
?>

它將產生以下輸出

This is a static method
This an instance method of the derived class
Calling static method of the parent class
This is a static method

另一個類中的靜態方法

完全可以在一個類中呼叫另一個類的靜態方法。您必須使用其類名字首其名稱,後跟作用域解析運算子。

示例

請看以下示例:

<?php
   class myclass {
   
      /* Member variables */
      static int $var1 = 0;
      public static function mystaticmethod() {
         echo "This is a static method".  PHP_EOL;
      }
   }
   
   #this is not a derived class
   class mynewclass {
      public function myfunction() {
         echo "This an instance method" . PHP_EOL;
         echo "Calling static method of the another class" . PHP_EOL;
         myclass::mystaticmethod();
      }
   }
   $obj = new mynewclass;
   $obj->myfunction();
?>

它將產生以下輸出

This an instance method
Calling static method of another class
This is a static method

由於$this偽變數對靜態方法不可用,因此無法在靜態方法內部訪問物件的例項變數。它只能處理類的靜態屬性。

示例

請看以下示例:

<?php
   class myclass {
   
      /* Member variables */
      static int $var1 = 0;
      function __construct() {
         self::$var1++;
         echo "object number ". self::$var1 . PHP_EOL;      
      }
      public static function mystaticmethod() {
         echo "Number of objects available: " . self::$var1 . PHP_EOL;
      }
   }

   for ($i=1; $i<=3; $i++) {
      $obj = new myclass;
   }
   myclass::mystaticmethod();
?>

它將產生以下輸出

object number 1
object number 2
object number 3
Number of objects available: 3

PHP – 靜態屬性

PHP 中的“static”關鍵字用於在 PHP 類中定義靜態屬性和靜態方法。需要注意的是,static 關鍵字也用於定義靜態變數和靜態匿名函式。閱讀本章以瞭解 PHP 類中的靜態屬性。

在類定義中,用 static 修飾符宣告的變數成為其靜態屬性。static 關鍵字可以出現在訪問修飾符之前或之後。

static private $var1;
public static $var2;

如果您想使用型別提示,則型別不能在 static 關鍵字之前。

static private string $var1;
public static float $var2;

類的靜態屬性的值無法透過其物件(使用 -> 運算子)訪問。這樣做會導致一條通知,指出將靜態屬性 myclass::$var1 作為非靜態屬性訪問。相反,靜態屬性是使用作用域解析運算子(由“::”符號表示)訪問的。

示例

請看以下示例:

<?php
   class myclass {
      static string $var1 = "My Class";
      function __construct() {
         echo "New object declared" . PHP_EOL;
      }
   }
   $obj = new myclass;
   echo "accessing static property with scope resolution operator: " . myclass::$var1 . PHP_EOL;
   echo "accessing static property with -> operator: ". $obj->var1 . PHP_EOL;
?>

它將產生以下輸出

New object declared
accessing static property with scope resolution operator: My Class
PHP Notice:  Accessing static property myclass::$var1 as non static in hello.php on line 14

“self”關鍵字

要從方法內部訪問靜態屬性,請使用 self 關鍵字引用當前類。在下面的示例中,類具有一個整數靜態屬性,每次宣告新物件時都會遞增。

<?php
   class myclass {
   
      /* Member variables */
      static int $var1 = 0;
      function __construct(){
         self::$var1++;
         echo "object number ". self::$var1 . PHP_EOL;
      }
   }
   for ($i=1; $i<=3; $i++) {
      $obj = new myclass;
   }
?>

它將產生以下輸出

object number 1
object number 2
object number 3

“parent”關鍵字

可以透過使用 parent 關鍵字引用基類來在繼承類的函式內部使用基類的靜態屬性。您需要使用“parent::static_property”語法。

示例

請看下面的例子:

<?php
   class myclass {
   
      /* Member variables */
      static int $var1 = 0;
      function __construct() {
         self::$var1++;
         echo "object number ". self::$var1 . PHP_EOL;
      }
   }

   class newclass extends myclass{
      function getstatic() {
         echo "Static property in parent class: " . parent::$var1 . PHP_EOL;
      }
   }
   $obj = new newclass;
   $obj->getstatic();
?>

它將產生以下輸出

object number 1
Static property in parent class: 1

PHP 名稱空間

我們經常將檔案組織在不同的資料夾中。通常,一個資料夾包含與特定目標、應用程式或類別相關的檔案。一個資料夾不能包含兩個同名的檔案,儘管不同的資料夾可能有同名的檔案,以便每個檔案的路徑不同。

PHP 中名稱空間的概念與此有些類似。在 PHP 中,名稱空間允許在不同的上下文中使用同名的類、函式或常量,而不會發生任何衝突,從而封裝這些專案。

PHP 名稱空間是類/函式等的邏輯分組,取決於它們的關聯性。正如同名檔案可以存在於兩個不同的資料夾中一樣,特定名稱的類也可以在兩個名稱空間中定義。此外,正如我們指定檔案的完整路徑以訪問一樣,我們需要指定類的全名以及名稱空間。

隨著應用程式規模的擴大,涉及許多類和函式定義,為每個類/函式賦予唯一的名稱可能會變得繁瑣且不優雅。使用名稱空間可以讓您以整潔的方式組織這些程式碼塊。例如,如果我們需要宣告一個 calculate() 函式來計算面積和稅,而不是將它們定義為 calculate_area() 和 calculate_tax() 之類的東西,我們可以建立兩個名稱空間 area 和 tax,並在其中使用 calculate()。

名稱空間的優點

以下是使用 PHP 名稱空間的一些優點:

  • 名稱空間有助於避免由某人定義的類/函式/常量與第三方類/函式/常量之間的名稱衝突。

  • 名稱空間提供了一種為 Extra_Long_Names 設定別名(或縮寫)的功能,從而提高了原始碼的可讀性。

  • PHP 名稱空間提供了一種對相關的類、介面、函式和常量進行分組的方法。名稱空間名稱不區分大小寫。

定義名稱空間

PHP 的 `namespace` 關鍵字用於定義新的名稱空間。

namespace myspace;

包含名稱空間的“.php”檔案必須在任何其他程式碼(除了 `declare` 指令)之前在檔案的頂部宣告名稱空間。在名稱空間內宣告類、函式和常量會影響其訪問許可權。

PHP 指令碼可能包含除名稱空間定義之外的其他程式碼。要載入在同一程式碼中定義的名稱空間,PHP 使用 “use” 關鍵字。

use myspace;

示例

在下面的 “hello.php” 指令碼中,我們在 `myspace` 名稱空間內定義了一個 `hello()` 函式,並在當前指令碼中載入名稱空間後呼叫它。

<?php
   namespace myspace;
   function hello() {
      echo "Hello World";
   }
   use myspace;
   myspace\hello();
?>

它將產生以下輸出

Hello World

請注意,必須使用包含名稱空間的完整名稱(`myspace\hello()`)限定 `hello()` 函式。

包含名稱空間

一個指令碼可以包含名稱空間宣告,另一個指令碼使用 `include` 語句載入該名稱空間。

a.php

<?php
   namespace myspace {
      function hello() {
         echo "Hello World in myspace";
      }
   }
?>

b.php

<?php
   include 'a.php';
   myspace\hello();
?>

它將產生以下輸出

Hello World in myspace

可能出現這種情況:當前指令碼(如上面的 “b.php”)也包含與包含檔案中同名的函式。在函式名前新增名稱空間的限定名有助於解析器解決名稱衝突。

示例

請看以下示例:

<?php
   include 'a.php';
   function hello() {
      echo "Hello World from current namespace";
   }
   hello();
   myspace\hello();
?>

它將產生以下輸出

Hello World from current namespace
Hello World in myspace

示例

如上所述,名稱空間宣告必須位於頂部,緊跟在起始 `< ?php` 標記之後。否則,解析器將丟擲致命錯誤。

<?php
   echo "hello"
   namespace myspace;
   function hello() {
      echo "Hello World";
   }
   use myspace;
   myspace\hello();
?>

它將產生以下輸出

PHP Parse error:  syntax error, unexpected token "namespace", 
expecting "," or ";" in /home/cg/root/67771/main.php on line 4

上述錯誤訊息清楚地表明,只有 “declare 語句” 允許出現在名稱空間宣告之前。

<?php
   declare (strict_types=1);
   namespace myspace;
   function hello() {
      echo "Hello World";
   }
   use myspace;
   myspace\hello();
?>

相對名稱空間

可以透過引用相對名稱空間路徑來訪問當前名稱空間中的物件,例如函式、類和常量。

在下面的示例中,“b.php”包含一個 `space1\myspace` 名稱空間,其中包含 `hello()` 函式和 `TEMP` 常量。“a.php”中也定義了相同空間下的物件。

顯然,當 “b.php” 包含在 “a.php” 中時,“myspace” 是 “space1” 的子空間。因此,透過在其前面新增其相對名稱空間(以及 `TEMP` 常量)來呼叫 “myspace” 中的 `hello()`。

b.php

<?php
   namespace space1\myspace;
   const TEMP = 10;
   function hello() {
      echo "Hello from current namespace:" . __NAMESPACE__ . ;
   }
?>

a.php

<?php
   namespace space1;
   include 'b.php';
   function hello() {
      echo "Hello from current namespace:" . __NAMESPACE__ . ;
   }
   const TEMP = 100;
   hello();            // current namespace
   myspace\hello();   // sub namespace

   echo "TEMP : " . TEMP . " in " . __NAMESPACE__ . ;
   echo "TEMP : " . myspace\TEMP  . " \\in space1\\myspace\n";
?>

它將產生以下輸出

Hello from current namespace:space1
Hello from current namespace:space1\myspace
TEMP : 100 in space1
TEMP : 10 in space1\myspace

絕對名稱空間

您還可以透過新增絕對名稱空間路徑來訪問任何名稱空間中的函式/常量。例如,“b.php”中的 `hello()` 是 `\space\myspace\hello()`。

a.php

<?php
   namespace space1;
   include 'b.php';
   function hello() {
      echo "Hello from current namespace:" . __NAMESPACE__ . ;
   }
   const TEMP = 100;
   \space1\hello();	             //current namespace
   \space1\myspace\hello();	    //sub namespace

   echo "TEMP: " . \space1\TEMP . " in " . __NAMESPACE__ . ;
   echo "TEMP: " . \space1\myspace\TEMP  . " in space1\\myspace\n";
?>

`__NAMESPACE__` 是 PHP 中一個預定義的常量,它返回當前名稱空間的名稱。

名稱空間規則

不同名稱空間中出現的函式/類/常量名稱的任何衝突都將按照以下規則解決:

  • 沒有名稱空間分隔符(/)的名稱空間識別符號表示它指的是當前名稱空間。這是一個非限定名稱。

  • 如果它包含分隔符,例如 `myspace\space1`,則它解析為 `myspace` 下的子名稱空間 `space1`。這種型別的命名是相對名稱空間。

  • 完全限定名稱空間的名稱以 “\” 字元開頭。例如,`\myspace` 或 `\myspace\space1`。

  • 完全限定名稱解析為絕對名稱空間。例如 `\myspace\space1` 解析為 `myspace\space1` 名稱空間。

  • 如果名稱出現在全域性名稱空間中,則會刪除 “namespace\” 字首。例如,“namespace\space1” 解析為 `space1`。

  • 但是,如果它出現在另一個名稱空間中,則處理方式不同。例如,如果 `namespace\space1` 在 `myspace` 中,則它等效於 “myspace\space1”。

  • 限定名稱中的第一段根據當前類/名稱空間匯入表進行轉換。

  • 如果沒有應用匯入規則,則將當前名稱空間新增到名稱前面。

  • 類名根據類/名稱空間匯入表進行轉換,函式名根據函式匯入表進行轉換,常量根據常量匯入表進行轉換。

  • 對於非限定名稱,如果沒有應用匯入規則並且名稱指的是函式或常量並且程式碼不在全域性名稱空間中,則在執行時解析名稱。它首先查詢當前名稱空間中的函式,然後嘗試查詢並呼叫全域性函式。

PHP 物件迭代

可以使用 `foreach` 迴圈迭代 PHP 類物件的公開可見的所有成員。此功能在 PHP 5 及更高版本中可用。當然,您可以在例項方法內訪問私有屬性列表。PHP 還定義了 `Iterator` 介面,可用於此目的。

使用 foreach 迴圈

在下面的示例中,使用 `foreach` 迴圈列出了類的公共屬性。

示例

<?php
   class myclass {
      private $var;
      protected $var1;
      public $x, $y, $z;
      public function __construct() {
         $this->var="Hello World";
         $this->var1=array(1,2,3);
         $this->x=100;
         $this->y=200;
         $this->z=300;
      }
   }
   $obj = new myclass();
   foreach($obj as $key => $value) {
      print "$key => $value\n";
   }
?>

它將產生以下輸出

x => 100
y => 200
z => 300

請注意,只有公共成員才能在類外部訪問。如果類包含方法,則可以使用 `foreach` 迴圈從內部遍歷所有成員(公共、私有或受保護)。

讓我們在上面的 `myclass` 中新增一個迭代方法。

public function iterate() {
   foreach ($this as $k=>$v) {
      if (is_array($v)) {
         var_dump($v);
         echo PHP_EOL;
      } else {
         echo "$k : $v". PHP_EOL;
      }
   }	 
}

呼叫此例項方法以獲取所有成員的列表。

它將產生以下輸出

var : Hello World
array(3) {
   [0]=>
   int(1)
   [1]=>
   int(2)
   [2]=>
   int(3)
}
x : 100
y : 200
z : 300

使用 Iterator 介面

PHP 提供 `Iterator` 介面用於外部迭代器或可以內部自行迭代的物件。它定義了以下需要在使用者定義的類中實現的抽象方法。

interface Iterator extends Traversable {
   /* Methods */
   public current(): mixed
   public key(): mixed
   public next(): void
   public rewind(): void
   public valid(): bool
}
  • `rewind()` 方法將迭代器重繞到第一個元素。這是啟動 `foreach` 迴圈時呼叫的第一個方法。它不會在 `foreach` 迴圈後執行。

  • `current()` 方法返回當前元素。

  • `key()` 方法在 `foreach` 迴圈的每次迭代中返回當前元素的鍵。

  • `next()` 方法在 `foreach` 迴圈的每次迭代後呼叫,並向前移動到下一個元素。

  • `valid()` 方法檢查當前位置是否有效。

示例

以下示例演示了透過實現 `Iterator` 介面進行物件迭代。

<?php
   class myclass implements Iterator {
      private $arr = array('a','b','c');

      public function rewind():void {
         echo "rewinding\n";
         reset($this->arr);
      }

      public function current() {
         $var = current($this->arr);
         echo "current: $var\n";
         return $var;
      }

      public function key() {
         $var = key($this->arr);
         echo "key: $var\n";
         return $var;
      }

      public function next() : void {
         $var = next($this->arr);
         echo "next: $var\n";
         # return $var;
      }

      public function valid() : bool {
         $key = key($this->arr);
         $var = ($key !== NULL && $key !== FALSE);
         echo "valid: $var\n";
         return $var;
      }
   }

   $obj = new myclass();

   foreach ($obj as $k => $v) {
      print "$k: $v\n";
   }
?>

它將產生以下輸出

rewinding
valid: 1
current: a
key: 0
0: a
next: b
valid: 1
current: b
key: 1
1: b
next: c
valid: 1
current: c
key: 2
2: c
next:

PHP 封裝

PHP 實現 **封裝**,這是 OOP 的重要原則之一,它使用訪問控制關鍵字:**public、private** 和 **protected**。

封裝是指將物件的成員變數或屬性與類外部的環境隔離,只允許透過類中可用的方法或函式進行受控訪問的機制。

下圖說明了面向物件程式設計方法中封裝的原則。

PHP Encapsulation 1

PHP 的關鍵字列表包含以下關鍵字,這些關鍵字確定物件的屬性和方法的可訪問性,該物件是 PHP 中類的例項:

  • **Public** - 類成員可以從任何地方訪問,甚至可以從類的範圍之外訪問,但只能透過物件引用訪問。

  • **Private** - 類成員只能在類本身內訪問。它可以防止外部類成員甚至透過類例項的引用進行訪問。

  • **Protected** - 成員只能在類及其子類中訪問,其他地方都不能訪問。

這三個關鍵字“**public、private** 和 **protected**”通常稱為訪問修飾符。它們也稱為可見性模式,因為它們決定特定類成員在多大程度上可用。

公共成員

在 PHP 中,類成員(成員變數和成員函式)預設為 public。

示例

在下面的程式中,物件的成員變數 title 和 price 可以自由地從類外部訪問,因為它們預設為 public,除非另有指定。

<?php
   class Person {
   
      /* Member variables */
      var $name;
      var $age;

      /*Constructor*/
      function __construct(string $param1="Ravi", int $param2=28) {
         $this->name = $param1;
         $this->age = $param2;
      }

      function getName() {
         echo "Name: $this->name" . PHP_EOL;;
      }
      function getAge() {
         echo "Age: $this->age" . PHP_EOL;;
      }
   }
   $b1 = new Person();
   $b1->getName();
   $b1->getAge();
   echo "Name : $b1->name Age: $b1->age" . PHP_EOL;
?>

它將產生以下輸出

Name: Ravi
Age: 28
Name : Ravi Age: 28

**注意**,預設情況下所有類成員的屬性都是公共的,如果需要,您可以顯式地將它們宣告為公共的。因此,例項方法 `getName()` 和 `getAge()` 可以從類外部呼叫。

由於屬性 `name` 和 `age` 也是公共的,因此它們也可以從類外部訪問,這與封裝的原則不符。

私有成員

如上所述,封裝的原則要求不應該直接訪問成員變數。只有方法才能訪問資料成員。因此,我們需要將成員變數設定為 private,並將方法設定為 public。

示例

讓我們將 `name` 和 `age` 屬性的宣告更改為私有,並執行以下 PHP 指令碼:

<?php
   class Person {
   
      /* Member variables */
      private $name;
      private $age;

      /*Constructor*/
      function __construct(string $param1="Ravi", int $param2=28) {
         $this->name = $param1;
         $this->age = $param2;
      }

      public function getName() {
         echo "Name: $this->name" . PHP_EOL;;
      }

      public function getAge(){
         echo "Age: $this->age" . PHP_EOL;;
      }
   }

   $b1 = new Person();
   $b1->getName();
   $b1->getAge();
   echo "Name : $b1->name Age: $b1->age" . PHP_EOL;
?>

它將產生以下輸出

Name: Ravi
Age: 28
PHP Fatal error:  Uncaught Error: Cannot access private property Person::$name in person.php:27

錯誤訊息說明了為什麼無法從公共作用域訪問私有屬性。

受保護成員

指定對類成員的受保護訪問的效果在類繼承的情況下是有效的。我們知道,public 成員可以從類外部的任何地方訪問,而 private 成員則不允許從類外部的任何地方訪問。

**protected** 關鍵字允許訪問同一類的物件及其繼承類的物件,而拒絕任何其他環境訪問。

示例

讓我們繼承 `person` 類並定義一個 `student` 類。我們將 `name` 屬性從私有更改為受保護。`student` 類有一個新的公共方法 `getDetails()`,它列印 `name` 和 `age` 屬性的值。

Person 類

<?php
class Person {

   /* Member variables */
   protected $name;
   private $age;

   /*Constructor*/
   function __construct(string $param1="Ravi", int $param2=28) {
      $this->name = $param1;
      $this->age = $param2;
   }

   public function getName(){
      echo "Name: $this->name" . PHP_EOL;;
   }

   public function getAge() {
      echo "Age: $this->age" . PHP_EOL;;
   }
}

Student 類

class student extends Person {
   public function getDetails() {
      echo "My Name: $this->name" . PHP_EOL;
      echo "My age: $this->age" . PHP_EOL;
   }
}
$s1 = new student();
$s1->getDetails();
?>

它將產生以下輸出

My Name: Ravi
PHP Warning:  Undefined property: student::$age in person.php on line 28
My age:

下表說明了 PHP 中類成員的可訪問性規則:

PHP Encapsulation 2

PHP - “Final” 關鍵字

PHP 中的 “final” 關鍵字用於類的定義、類中的方法定義以及類的常量屬性定義。

帶有 “final” 關鍵字的類

讓我們看看如何使用 “final” 關鍵字建立類:

final class myclass {
   /*class members*/   
}

類定義中的 “final” 關鍵字阻止該類被擴充套件。換句話說,您不能使用 final 類作為父類。如果您嘗試這樣做,PHP 解析器會丟擲錯誤。

<?php
   final class myclass {
   
      /* class body */
   }
   class newclass extends myclass {
   
      /* class body */ 
   }
?>

執行此程式碼時,它將顯示一個 **錯誤**:

PHP Fatal error:  Class newclass may not inherit from final class (myclass)

帶有 “final” 關鍵字的方法

以下是如何使用 “final” 關鍵字建立方法:

class myclass {
   final function myfunction() {
   
      /* function body */
   }
}

用 **final** 關鍵字作為方法定義的字首可以防止它在子類中被重寫。帶有 **final** 方法的類可以擴充套件,但子類不能重寫它。

示例

請看以下示例:

<?php
   class myclass {
      final public function hello() {
         echo "Hello World!";
      }
   }
   class newclass extends myclass {
      public function hello() {
         echo "Hello PHP!";
      }
   }
?>

執行此程式碼時,它將顯示一個 **錯誤**:

PHP Fatal error:  Cannot override final method myclass::hello() in hello.php

帶有 “final” 關鍵字的常量

從 PHP 8.1.0 開始,您還可以使用 **final** 關鍵字宣告類中的常量。

final public const NAME = "My Class";

如果您嘗試在子類中重寫父類中的 final 常量,則會遇到錯誤。

<?php
   class myclass {
      final public const NAME = "My Class";
      final public function hello() {
         echo "Hello World!";
      }
   }

   class newclass extends myclass {
      public const NAME = "New Class";
   }
?>

執行此程式碼時,它將顯示一個 **錯誤**:

Fatal error: newclass::NAME cannot override final constant myclass::NAME

示例

下面的 PHP 指令碼包含一個父類 `ellipse`,它具有宣告為 final 的 `PI` 常量和 `area()` 方法。它們被 `circle` 類繼承。`area()` 函式計算圓的面積。

<?php
   class ellipse {
      final public const PI=22/7;
      private float $a, $b;
      public function __construct($x, $y) {
         $this->a = $x;
         $this->b = $y;
      }
      final public function area() : float {
         return self::PI*$this->a*$this->b;
      }
   }
   class circle extends ellipse {
      public function __construct(float $x) {
         parent::__construct($x, $x);
      }
   }
   $c1 = new circle(5);
   echo "Area: " . $c1->area() . PHP_EOL;
?>

它將產生以下輸出

Area: 78.571428571429

請注意,不能將類的例項變數或屬性宣告為 final。

PHP 過載

在 C++ 或 Java 中,該術語表示一個類可以多次擁有相同名稱但引數和/或返回型別不同的類方法。在 PHP 中,該術語的解釋不同。它是一個可以動態建立屬性和方法的功能。PHP 的魔術方法(方法名稱以雙下劃線開頭)用於設定動態屬性和方法。

用於過載的魔術方法在與未宣告或在當前作用域中不可見的屬性或方法互動時被呼叫。

屬性過載

PHP 的魔術方法示例包括 __construct()、__destruct()、__tostring() 等。PHP 使用以下魔術方法來過載屬性。

public __set ( string $name , mixed $value ) : void
public __get ( string $name ) : mixed
public __isset ( string $name ) : bool
public __unset ( string $name ) : void

這裡:

  • __set() 用於向不可訪問的屬性(受保護的、私有的或不存在的屬性)寫入資料。

  • __get() 從不可訪問的屬性讀取資料。

  • __isset() 對不可訪問的屬性呼叫 isset() 或 empty()。

  • __unset() 在對不可訪問的屬性呼叫 unset() 時被呼叫。

上面使用的 $name 引數是要設定或檢索的屬性的名稱。__set() 方法的 $value 引數指定要分配給屬性的值。

__isset() 方法檢查某個屬性是否已設定。__unset() 方法刪除該屬性。

屬性過載僅在物件上下文中有效。在任何靜態上下文中,這些魔術方法都不會被觸發。因此,它們不應該宣告為靜態的。

示例

在下面的程式碼中,設定並檢索了一個名為 myprop 的動態屬性,該屬性未在類中宣告。

<?php
   class myclass {
      public function __set($name, $value) {
         echo "setting $name property to $value \n";
         $this->$name = $value;
      }

      public function __get($name) {
         echo "value of $name property is ";
         return $this->$name;
      }
   }

   $obj = new myclass();

   # This calls __set() method
   $obj->myproperty="Hello World!";

   # This call __get() method
   echo "Retrieving myproperty: " . $obj->myproperty . PHP_EOL;
?>

它將產生以下輸出

setting myproperty property to Hello World! 
Retrieving myproperty: Hello World!

__set()__get() 魔術方法還可以設定和檢索宣告為私有的屬性。在 myclass 中新增以下語句(在函式定義之前)

private $myproperty;

您可以檢查屬性,在myclass中定義__isset()方法:

public function __isset($name) {
   return isset($this->$name);
}

使用以下語句檢查屬性是否已設定:

var_dump (isset($obj->myproperty));

在這種情況下,它返回true

要使用在myclass中定義的__unset()方法取消設定動態建立的屬性:

public function __unset($name) {
   unset($this->$name);
}

以下程式碼將返回false

var_dump (isset($obj->myproperty));

方法過載

用於動態設定方法的兩個魔術方法是__call()__callStatic()

public __call (string $name , array $arguments) : mixed
public static __callStatic (string $name , array $arguments) : mixed

當在物件上下文中呼叫不可訪問的方法(未定義或私有的方法)時,將觸發 __call()。另一方面,當在靜態上下文中呼叫不可訪問的方法時,將觸發 __callStatic()。

示例

以下示例演示了 PHP 中的方法過載

<?php
   class myclass {
      public function __call($name, $args) {
	  
         // Value of $name is case sensitive.
         echo "Calling object method $name with " . implode(" ", $args). "\n";
      }
      public static function __callStatic($name, $args) {
         echo "Calling static method $name with " . implode(" ", $args). "\n";
      }
   }
   $obj = new myclass();

   # This invokes __call() magic method
   $obj->mymethod("Hello World!");

   # This invokes __callStatic() method
   myclass::mymethod("Hello World!");
?>

它將產生以下輸出

Calling object method mymethod with Hello World!
Calling static method mymethod with Hello World!

請注意,使用 "->" 運算子表示該方法是例項方法,而 "::" 運算子表示該方法是靜態方法

PHP 克隆物件

PHP 語句 "$obj1 = $obj2" 僅僅建立了對記憶體中同一物件的另一個引用。因此,屬性的更改會在原始物件和副本物件中都反映出來。PHP 中的clone關鍵字建立物件的淺複製。

$obj2 = $obj1

原始物件的更改不會反映在淺複製中。

示例

請看以下示例:

<?php
   class foo {
      var $var1 = 'Hello';
   }
   $x = new foo();
   $y = $x;		# reference copy
   echo $x->var1 . " " . $y->var1 . PHP_EOL;

   $x->var1 = "Hello World";
   echo $x->var1 . " " . $y->var1 . PHP_EOL;
?>

它將產生以下輸出

Hello Hello
Hello World Hello World

在第一種情況下,$y只是$x的引用副本。因此,var1屬性的任何更改都會反映在兩者中。

但是,如果我們將$y宣告為$x的克隆,則原始物件的任何更改都不會反映在其淺複製中。

示例

請看以下示例:

<?php
   class foo {
      var $var1 = 'Hello World';
   }

   $x = new foo();

   # shallow copy
   $y = clone $x;
   echo $x->var1 . " " . $y->var1 . PHP_EOL;

   $x->var1 = "Hello PHP";
   echo $x->var1 . " " . $y->var1 . PHP_EOL;
?>

它將產生以下輸出

Hello World Hello World
Hello PHP Hello World

示例

在下面的程式碼中,myclass的一個屬性是 address 類的物件。透過賦值複製 myclass 的物件。其嵌入的 address 物件的值的任何更改都將反映在這兩個物件中,但 name 屬性的更改不會影響克隆的物件。

<?php
   class address {
      var $city="Nanded";
      var $pin="431601";
      function setaddr($arg1, $arg2) {
         $this->city=$arg1;
         $this->pin=$arg2;
      }
   }
   class myclass {
      var $name="Raja";
      var $obj;
      function setname($arg) {
         $this->name=$arg;
      }
   }

   $obj1=new myclass();
   $obj1->obj=new address();
   echo "original object\n";
   print_r($obj1);
   echo "\n";

   $obj2=$obj1;		# reference copy
   $obj1->setname("Ravi");
   $obj1->obj->setaddr("Mumbai", "400001");
   echo "after change: Original object\n";
   print_r($obj1);
   echo "\nCopied object\n";
   print_r($obj2);
?>

它將產生以下輸出

original object
myclass Object
(
   [name] => Raja
   [obj] => address Object
   (
      [city] => Nanded
      [pin] => 431601
   )
)

after change: Original object
myclass Object
(
   [name] => Ravi
   [obj] => address Object
   (
      [city] => Mumbai
      [pin] => 400001
   )
)

Copied object
myclass Object
(
   [name] => Ravi
   [obj] => address Object
   (
      [city] => Mumbai
      [pin] => 400001
   )
)

使用“clone”關鍵字

在淺複製中,原始物件的任何引用其他變數的屬性都將保持引用。clone 關鍵字不會複製已複製物件的包含物件。

我們現在建立一個 myclass 物件的克隆,以便$obj2$obj1的克隆。我們將$obj1的 name 屬性從Raja更改為Ravi,並修改嵌入的 address 物件。屬性更改不會反映在其克隆中,但引用的 address 物件將被更改。

示例

請看以下示例:

<?php
   class address {
      var $city="Nanded";
      var $pin="431601";
      function setaddr($arg1, $arg2) {
         $this->city=$arg1;
         $this->pin=$arg2;
      }
   }
   class myclass {
      var $name="Raja";
      var $obj;
      function setname($arg) {
         $this->name=$arg;
      }
   }
   $obj1=new myclass();
   $obj1->obj=new address();
   echo "original object\n";
   print_r($obj1);
   echo "\n";

   $obj2=clone $obj1;		# clone copy
   $obj1->setname("Ravi");
   $obj1->obj->setaddr("Mumbai", "400001");
   echo "after change: Original object\n";
   print_r($obj1);
   echo "\nCopied object\n";
   print_r($obj2);
?>

它將產生以下輸出

original object
myclass Object
(
   [name] => Raja
   [obj] => address Object
   (
      [city] => Nanded
      [pin] => 431601
   )
)

after change: Original object
myclass Object
(
   [name] => Ravi
   [obj] => address Object
   (
      [city] => Mumbai
      [pin] => 400001
   )
)

Copied object
myclass Object
(
   [name] => Raja
   [obj] => address Object
   (
      [city] => Mumbai
      [pin] => 400001
   )
)

使用 __clone() 方法

clone 關鍵字建立物件的淺複製。當克隆物件時,PHP 將執行其所有屬性的淺複製。任何引用其他變數的屬性都將保持引用。因此,對原始物件所做的任何更改也將在克隆物件中出現。

如果您希望阻止複製的物件自動更新,我們需要使用 __clone() 方法建立物件的深複製。它是 PHP 中的一種魔術方法。

克隆完成後,如果定義了 __clone() 方法,則將呼叫新建立物件的 __clone() 方法,以允許更改任何需要更改的屬性。

示例

在上面的示例中,我們有一個 myclass 物件,其一個屬性 $obj 保持對 address 類物件的引用。為了實現深複製,我們重寫了 myclass 中的 __clone() 魔術方法。

<?php
   class address {
      var $city="Nanded";
      var $pin="431601";
      function setaddr($arg1, $arg2) {
         $this->city=$arg1;
         $this->pin=$arg2;
      }
   }
   class myclass {
      var $name="Raja";
      var $obj;
      function setname($arg) {
         $this->name=$arg;
      }
      public function __clone() {
         $this->obj = clone $this->obj ;
      }
   }
   $obj1=new myclass();
   $obj1->obj=new address();
   echo "original object\n";
   print_r($obj1);
   echo "\n";

   $obj2=clone $obj1;		# cloned deep copy
   $obj1->setname("Ravi");
   $obj1->obj->setaddr("Mumbai", "400001");
   echo "after change: Original object\n";
   print_r($obj1);
   echo "\nCloned object\n";
   print_r($obj2);
?>

您現在將看到原始物件的更改(我們更改了地址屬性)不會反映在克隆物件中,如下所示的輸出

original object
myclass Object
(
   [name] => Raja
   [obj] => address Object
   (
      [city] => Nanded
      [pin] => 431601
   )
)

after change: Original object
myclass Object
(
   [name] => Ravi
   [obj] => address Object
   (
      [city] => Mumbai
      [pin] => 400001
   )
)

Cloned object
myclass Object
(
   [name] => Raja
   [obj] => address Object
   (
      [city] => Nanded
      [pin] => 431601
   )
)

PHP 匿名類

7.0版本的釋出是PHP語言發展的一個重要里程碑,當時引入了許多新特性。匿名類的特性也在PHP 7.0版本中可用。

顧名思義,“匿名”類是沒有(程式設計師宣告的)名稱的類。通常的做法是使用某個識別符號定義一個類,以便可以重複使用它。另一方面,匿名類僅供一次性使用。

$obj = new class() {
   /* class body */
};

除了這個類沒有名稱之外,它與普通的命名類相似,因為它可以包含屬性和方法。其功能與命名類的物件沒有什麼不同。

當不需要為類編寫文件,並且類在執行期間僅使用一次時,可以使用匿名類而不是命名類。當需要建立簡單的一次性物件時,匿名類非常有用。

示例

在下面的程式碼中,例項化一個匿名類並將其儲存在 $obj 物件中。該類包含 addition() 和 division() 方法的定義,這些方法使用$obj物件呼叫。

<?php
   $obj = new class(10) {
      private int $x;
      function __construct($x) {
         $this->x = $x;
      }

      public function addition($x) {
         return $this->x+$x;
      }
      public function division($x) {
         return $this->x/$x;
      }
   };

   echo "Addition: " . $obj->addition(20) . PHP_EOL;
   echo "Division: " . $obj->division(20) . PHP_EOL;
?>

它將產生以下輸出

Addition: 30
Division: 0.5

匿名類作為子類

匿名類可以完成普通類可以完成的所有操作。它可以擴充套件另一個類,實現一個介面,甚至可以使用一個 trait。

示例

在下面的示例中,匿名類是一個子類,擴充套件了已經存在的父類。

<?php
   class myclass {
      public function hello() {
         echo "Hello World!" . PHP_EOL;
      }
   }
   $obj = new class("Neena") extends myclass {
      private string $nm;
      function __construct($x) {
         $this->nm = $x;
      }
      public function greeting() {
         parent::hello();
         echo "Welcome " . $this->nm . PHP_EOL;
      }
   };
   $obj->greeting();
?>

它將產生以下輸出

Hello World!
Welcome Neena

示例

雖然匿名類沒有任何使用者定義的名稱,但 PHP 確實為其分配了一個內部名稱,可以使用內建的 get_class() 函式如下獲取:

<?php
   $obj = new class() {
      function greeting() {
         echo "Hello World" . PHP_EOL;
      }
   };
   $obj->greeting();
   echo "Name of class: " . get_class($obj);
?>

它將產生以下輸出

Hello World
Name of class: class@anonymousC:\xampp\htdocs\hello.php:2$0

PHP 解析器隨機分配內部名稱。

PHP Web 概念

PHP 是一種伺服器端指令碼語言,用於建立動態網頁。它是 Web 開發中最流行的程式語言之一。本章旨在讓您熟悉使用 PHP 進行 Web 應用程式開發的某些重要概念。

一個基於 Web 的應用程式是網頁的集合。網頁主要由 HTML 標籤建立。HTML 由不同的 HTML 標籤組成,這些標籤需要定義頁面元素(如文字、影像、表格等)的外觀。因此,HTML 本質上建立的是靜態網頁。

Web 應用程式託管在安裝了 PHP 模組的 HTTP 伺服器上。瀏覽器充當 http 客戶端,以遵循 HTTP 協議與伺服器建立通訊。

PHP Web Concepts

如何在網頁上新增動態內容?

要在網頁上新增動態內容,有兩種可能性。

JavaScript 是一種客戶端指令碼語言,可以訪問 HTML 文件物件模型並在客戶端瀏覽器上呈現動態內容。JavaScript 程式碼可以嵌入到 HTML 頁面中。

瀏覽器可以以 HTML 表單元素的形式從使用者那裡收集資料,並將其傳送到 HTTP 伺服器進行處理。PHP 是一種廣泛使用的伺服器端處理語言。PHP 指令碼也可以嵌入到 HTML 頁面中。

示例

在下面的指令碼中,嵌入在 HTML 中的 JavaScript 程式碼根據客戶端瀏覽器呈現當前日期,而 PHP 程式碼顯示託管此指令碼的伺服器上的當前日期。

<!DOCTYPE html>
<html>
<body>
   <script type="text/JavaScript">
      document.write("Client's date :"+Date()+"\n");
   </script>
   <?php
      date_default_timezone_set("Asia/Calcutta");
      echo "server's date is " . date("Y-m-d") . "\n";
      echo "The time is " . date("h:i:sa");
   ?>
</body>
</html>

PHP 可以攔截和處理來自 HTML 表單的資料。這允許您收集使用者的資訊。下一章討論 PHP 的表單處理。

PHP 可用於與資料庫(如 MySQL 和 PostgreSQL)互動。這允許您儲存和檢索資料庫中的資料,並動態填充網頁或為 Web 應用程式提供動力。PHP 包含用於資料庫處理的 mysql、mysqli 和 PDO 擴充套件。

PHP 可以使用 HTTP GET 和 POST 方法處理從客戶端接收到的資料。我們將在後面的章節中詳細討論 PHP 如何處理 GET/POST 方法。

HTTP 是一種無狀態協議。但是,它允許分別在伺服器和客戶端上維護會話和 Cookie。PHP 可用於建立和管理會話和 Cookie。會話允許您在使用者瀏覽您的網站時跟蹤單個使用者,而 Cookie 允許您將資訊儲存在使用者的計算機上以供以後使用。在後面的章節中,我們將學習 PHP 如何處理會話和 Cookie。

PHP 可用於將檔案上傳到您的 Web 伺服器。這允許您建立允許使用者上傳檔案(如影像、影片或文件)的 Web 應用程式。

您可以使用 PHP 為您的網站建立登入頁面。當用戶輸入其使用者名稱和密碼時,PHP 可以檢查資料庫以檢視使用者是否有效。如果使用者有效,PHP 可以登入使用者並將其重定向到網站的主頁。

識別瀏覽器和平臺

PHP 建立了一些有用的環境變數,這些變數可以在用於設定 PHP 環境的 phpinfo.php 頁面中看到。

PHP 設定的環境變數之一是HTTP_USER_AGENT,它標識使用者的瀏覽器和作業系統。

PHP 提供了一個 getenv() 函式來訪問所有環境變數的值。HTTP_USER_AGENT 環境變數中包含的資訊可用於建立適合瀏覽器的動態內容。

示例

以下示例演示如何識別客戶端瀏覽器和作業系統。

注意 - preg_match() 函式在PHP 正則表示式 部分討論。

<?php
   function getBrowser() { 
      $u_agent = $_SERVER['HTTP_USER_AGENT']; 
      $bname = 'Unknown';
      $platform = 'Unknown';
      $version = "";
            
      //First get the platform
      if (preg_match('/linux/i', $u_agent)) {
         $platform = 'linux';
      } elseif (preg_match('/macintosh|mac os x/i', $u_agent)) {
         $platform = 'mac';
      } elseif (preg_match('/windows|win32/i', $u_agent)) {
         $platform = 'windows';
      }
            
      // Next get the name of the useragent yes seperately and for good reason
      if(preg_match('/MSIE/i',$u_agent) && !preg_match('/Opera/i',$u_agent)) {
         $bname = 'Internet Explorer';
         $ub = "MSIE";
      } elseif(preg_match('/Firefox/i',$u_agent)) {
         $bname = 'Mozilla Firefox';
         $ub = "Firefox";
      } elseif(preg_match('/Chrome/i',$u_agent)) {
         $bname = 'Google Chrome';
         $ub = "Chrome";
      } elseif(preg_match('/Safari/i',$u_agent)) {
         $bname = 'Apple Safari';
         $ub = "Safari";
      } elseif(preg_match('/Opera/i',$u_agent)) {
         $bname = 'Opera';
         $ub = "Opera";
      } elseif(preg_match('/Netscape/i',$u_agent)) {
         $bname = 'Netscape';
         $ub = "Netscape";
      }
            
      // finally get the correct version number
      $known = array('Version', $ub, 'other');
      $pattern = '#(?<browser>' . join('|', $known) . ')
         [/ ]+(?<version>[0-9.|a-zA-Z.]*)#';

      if (!preg_match_all($pattern, $u_agent, $matches)) {
         // we have no matching number just continue
      }

      // see how many we have
      $i = count($matches['browser']);

      if ($i != 1) {
         //we will have two since we are not using 'other' argument yet

         //see if version is before or after the name
         if (strripos($u_agent,"Version") < strripos($u_agent,$ub)){
            $version= $matches['version'][0];
         } else {
            $version= $matches['version'][1];
         }
      } else {
         $version= $matches['version'][0];
      }
            
      // check if we have a number
      if ($version == null || $version == "") {$version = "?";}
         return array(
            'userAgent' => $u_agent,
            'name'      => $bname,
            'version'   => $version,
            'platform'  => $platform,
            'pattern'   => $pattern
         );
   }
         
   // now try it
   $ua = getBrowser();
   $yourbrowser = "Your browser: " . $ua['name'] . " " . $ua['version'] .
   " on " .$ua['platform'] . " reports: <br >" . $ua['userAgent'];

   print_r($yourbrowser);
?>

這在我的機器上產生了以下結果。根據您使用的計算機的不同,此結果可能會有所不同。

它將產生以下結果 -

Your browser: Google Chrome 54.0.2840.99 on windows reports: 
Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) 
   Chrome/54.0.2840.99 Safari/537.36

隨機顯示影像

PHP 的rand()函式用於生成隨機數。此函式可以在給定範圍內生成數字。應為隨機數生成器設定種子,以防止生成規則的數字模式。這是透過使用srand()函式實現的,該函式將其引數指定為種子數。

示例

以下示例演示如何每次從四張影像中顯示不同的影像:

<?php
   srand( microtime() * 1000000 );
   $num = rand( 1, 4 );
         
   switch( $num ) {
      case 1: $image_file = "/php/images/php_image_sample_1.jpg";
         break;
            
      case 2: $image_file = "/php/images/php_image_sample_2.jpg";
         break;
            
      case 3: $image_file = "/php/images/php_image_sample_3.jpg";
         break;
            
      case 4: $image_file = "/php/images/php_image_sample_4.jpg";
         break;
   }
   echo "Random Image : <img src=$image_file />";
?>

它將產生以下結果 -

Display Image Randomly

使用 HTML 表單

處理 HTML 表單和 PHP 時需要注意的最重要的事情是,HTML 頁面中的任何表單元素都將自動可用於您的 PHP 指令碼。

示例

透過將原始碼放入 test.php 指令碼中來嘗試以下示例。

<?php
   if( $_POST["name"] || $_POST["age"] ) {
      if (preg_match("/[^A-Za-z'-]/",$_POST['name'] )) {
         die ("invalid name and name should be alpha");
      }
      
      echo "Welcome ". $_POST['name']. "<br />";
      echo "You are ". $_POST['age']. " years old.";
      
      exit();
   }
?>
<form action = "<?php <b>$_PHP_SELF</b> ?>" method = "POST">
   Name: <input type = "text" name = "name" />
   Age: <input type = "text" name = "age" />
   <input type = "submit" />
</form>

它將產生以下結果 -

Forms
  • PHP 預設變數$_PHP_SELF用於 PHP 指令碼名稱,當您單擊“提交”按鈕時,將呼叫相同的 PHP 指令碼併產生以下結果:

  • method = "POST" 方法用於將使用者資料釋出到伺服器指令碼。將資料釋出到伺服器指令碼的方法有兩種,在PHP GET & POST章節中討論。

瀏覽器重定向

PHP 的header()函式向瀏覽器提供原始 HTTP 標頭,可用於將其重定向到另一個位置。重定向指令碼應位於頁面的最頂部,以防止頁面的任何其他部分載入。

目標由Location:標頭指定為header()函式的引數。呼叫此函式後,可以使用exit()函式來停止解析其餘程式碼。

示例

以下示例演示如何將瀏覽器請求重定向到另一個網頁。透過將原始碼放入 test.php 指令碼中來嘗試此示例。

<?php
   if( $_POST["location"] ) {
      $location = $_POST["location"];
      header( "Location:$location" );
      
      exit();
   }
?>
<p>Choose a site to visit :</p>   
<form action = "<?php <b>$_SERVER['PHP_SELF']</b> ?>" method ="POST">
   <select name = "location">.
         
      <option value = "https://tutorialspoint.tw">
         Tutorialspoint.com
      </option>
         
      <option value = "http://www.google.com">
         Google Search Page
      </option>
         
   </select>
   <input type = "submit" />
</form>

它將產生以下結果 -

Browser Redirection

PHP 表單處理

HTML 表單在 PHP Web 應用程式中扮演著重要的角色。雖然純 HTML 組成的網頁是靜態網頁,但 HTML 表單元件是一個重要的功能,有助於增強互動性和呈現動態內容。PHP 的表單處理功能可以在處理之前驗證從使用者收集的資料。

HTML 表單是由各種表單控制元件(例如文字欄位、複選框、單選按鈕等)組成的集合,使用者可以與這些控制元件互動,輸入或選擇某些資料。這些資料可以透過 JavaScript 在本地處理(客戶端處理),也可以藉助於 PHP 等伺服器端程式設計指令碼傳送到遠端伺服器進行處理。

一個或多個表單控制元件元素放在 <form> 和 </form> 標籤內。表單元素具有不同的屬性,例如 name、action 和 method。

<form [attributes]>
   Form controls
</form>

表單屬性

在 HTML 表單元素的眾多屬性中,以下屬性通常是必需且已定義的:

Action 屬性

一個字串,表示處理表單提交的 URL。例如,http://example.com/test.php。要將表單資料提交到定義 HTML 表單的同一 PHP 指令碼,請使用 PHP_SELF 伺服器變數:

<form action="<?php echo $_SERVER['PHP_SELF'];?>" method="post">

Enctype 屬性

指定在將表單資料傳送到伺服器之前應使用哪種方法對其進行編碼。可能的值包括:

  • application/x-www-form-urlencoded − 預設值。

  • multipart/form-data − 如果表單包含 type=file 的 <input> 元素,則使用此值。

  • text/plain − 用於除錯目的。

Method 屬性

一個字串,表示提交表單時使用的 HTTP 方法。method 屬性的可能值為:

  • post − POST 方法;表單資料作為請求正文傳送。

  • get (預設) − GET 方法;表單資料使用“?”分隔符附加到 action URL。如果表單沒有副作用,請使用此方法。

  • dialog − 當表單位於 <dialog> 內時,關閉對話方塊並觸發提交事件,而無需提交資料或清除表單。

Name 屬性

表單的名稱。值不能是空字串,如果同一 HTML 文件中有多個表單,則必須唯一。

Target 屬性

一個字串,指示在提交表單後在哪裡顯示響應。應為以下值之一:

  • _self (預設) − 載入到與當前瀏覽器上下文相同的瀏覽器上下文。

  • _blank − 載入到新的未命名瀏覽器上下文。

  • _parent − 載入到當前瀏覽器的父級上下文。

  • _top − 載入到頂級瀏覽器上下文(當前瀏覽器的祖先,且沒有父級)。

因此,在 PHP Web 應用程式中使用的典型 HTML 表單如下所示:

<form name="form1" action="<?php echo $_SERVER['PHP_SELF'];?>" action="POST">
   Form controls
</form>

表單元素

HTML 表單使用不同型別的控制元件或元素設計。使用者可以與這些控制元件互動以輸入資料或從提供的可用選項中進行選擇。下面描述了一些元素:

Input 元素

input 元素表示資料欄位,使用者可以在其中輸入和/或編輯資料。

INPUT 元素的 type 屬性控制資料。INPUT 元素可能有以下型別:

Text

用於輸入單行文字的文字欄位。

<input type="text" name="employee">

Password

單行文字欄位,會掩蓋輸入的字元。

<input type="password" name="pwd"><br>

Checkbox

一個矩形的可選中複選框,它是一組來自預定義列表的零個或多個值。

<input type="checkbox" id="s1" name="sport1" value="Cricket">
<label for="s1">I like Cricket</label><br>
<input type="checkbox" id="s2" name="sport2" value="Football">
<label for="s2">I like Football</label><br>
<input type="checkbox" id="s3" name="sport3" value="Tennis">
<label for="s3">I like Tennis</label><br><br>

Radio

此型別呈現一個圓形的可點選按鈕,具有兩種狀態(ON 或 OFF),通常是單選組中多個按鈕的一部分。

<input type="radio" id="g1" name="gender" value="Male">
<label for="g1">Male</label><br>
<input type="radio" id="g2" name="female" value="Female">
<label for="g2">Female</label><br>

File

此輸入型別呈現一個標題為“檔案”的按鈕,允許使用者從客戶端檔案系統選擇檔案,通常用於上傳到伺服器。表單的 enctype 屬性必須設定為“multipart/form-data”。

<input type="file" name="file">

郵箱

單行文字欄位,自定義為接受符合有效電子郵件 ID 的字串。

URL

單行文字欄位,自定義為接受符合有效 URL 的字串。

Submit

此輸入元素呈現一個按鈕,單擊時會啟動將表單資料提交到當前表單 action 屬性中指定的 URL 的操作。

<input type="submit" name="Submit">

Select 元素

select 元素表示一個用於在一組選項中進行選擇的控制元件。每個選項都使用 Select 控制元件的 option 屬性定義。例如:

<select name="Subjects" id="subject">
   <option value="Physics">Physics</option>
   <option value="Chemistry">Chemistry</option>
   <option value="Maths">Maths</option>
   <option value="English">English</option>
</select>

表單示例

讓我們使用這些表單元素來設計一個 HTML 表單並將其傳送到 PHP_SELF 指令碼。

<html>
<body>
   <form method = "post" action = "<?php 
      echo htmlspecialchars($_SERVER["PHP_SELF"]);?>">
      <table>
         <tr>
            <td>Name:</td>
            <td><input type = "text" name = "name"></td>
         </tr>
         <tr>
            <td>E-mail: </td>
            <td><input type = "email" name = "email"></td>
         </tr>
         <tr>
            <td>Website:</td>
            <td><input type = "url" name = "website"></td>
         </tr>
         <tr>
            <td>Classes:</td>
            <td><textarea name = "comment" rows = "5" cols = "40"></textarea></td>
         </tr>
         <tr>
            <td>Gender:</td>
            <td>
               <input type = "radio" name = "gender" value = "female">Female
               <input type = "radio" name = "gender" value = "male">Male
            </td>
         </tr>
         <td>
            <input type = "submit" name = "submit" value = "Submit"> 
         </td>
      </table>
   </form>
   <?php
      $name = $email = $gender = $comment = $site = "";

      if ($_SERVER["REQUEST_METHOD"] == "POST") {
         $name = $_POST["name"];
         $email = $_POST["email"];
         $name = $_POST["name"];
         $comment = $_POST["comment"];
         $gender = $_POST["gender"];
         $site = $_POST["website"];
      }
      echo "<h2>Your given values are as:</h2>";
      echo $name;
      echo "<br>";

      echo $email;
      echo "<br>";

      echo $site;
      echo "<br>";

      echo $comment;
      echo "<br>";

      echo $gender;
   ?>
</body>
</html>

它將產生以下輸出

PHP Form Handling

PHP 表單驗證

術語“表單驗證”是指確定使用者在各種表單元素中輸入的資料是否可以進一步處理的過程。在後續處理之前驗證資料可以避免可能的異常和執行時錯誤。

驗證可以在客戶端和伺服器端進行。當客戶端提交表單時,伺服器上執行的 PHP 指令碼會攔截表單資料。使用 PHP 中提供的各種函式,可以進行伺服器端表單驗證。

客戶端驗證

根據 HTML5 規範,新的輸入控制元件具有內建驗證功能。例如,型別為“email”的 input 元素,即使是文字欄位,也自定義為接受符合電子郵件地址協議的字串。

驗證發生在資料提交到伺服器之前。其他輸入型別(如 URL、數字等)也是如此。

示例

下面是一個 HTML 表單,其中包含數字型別、電子郵件型別和 URL 型別的輸入元素。如果輸入的資料不符合所需格式,則在嘗試提交表單時會顯示相應的錯誤訊息。

<h1>Input Validation</h1>
<form>
   <p><Label for "name">Enter your name</label>
   <input type = "text" id="name" name="name"></p>
   <p><label for="age">Enter age</label>
   <input type = "text" id = "age" name="age"></p>
   <p><label for="email">Enter your email:</label>
   <input type="text" id="email" name="email"></p>
   <p><label for="URL">Enter your website<label>
   <input type = "text" id="URL" name="url"></p>
   <input type="submit">
</form>

數字型別文字欄位在右側顯示上下計數箭頭。只接受數字,並且可以遞增或遞減。

PHP Form Validation 1

如果電子郵件欄位中的資料無效,則會顯示如下錯誤訊息。

PHP Form Validation 2

同樣,URL 的任何不正確格式也會顯示如下錯誤:

PHP Form Validation 3

驗證函式

伺服器端使用 PHP 進行的驗證,要麼在表單資料透過客戶端驗證時發生,要麼根本沒有客戶端驗證。

在上例中使用的 HTML 表單中,讓我們移除所有特殊輸入型別,並使用所有文字型別的文字欄位。表單使用 POST 方法提交到伺服器上的 hello.php。

<form action="hello.php" method="POST">
   <p><Label for "name">Enter your name</label>
   <input type = "text" id="name" name="name"></p>
   <p><label for="age">Enter age</label>
   <input type = "text" id = "age" name="age"></p>
   <p><label for="email">Enter your email:</label>
   <input type="text" id="email" name="email"></p>
   <p><label for="URL">Enter your website<label>
   <input type = "text" id="URL" name="url"></p>
   <input type="submit">
</form>

表單為空

如果使用者(可能是無意中)單擊提交按鈕,您可以要求 PHP 再次顯示錶單。您需要使用 isset() 函式檢查 $_POST 陣列是否已初始化。如果沒有,header() 函式會將控制權重定向回表單。

<?php 
   if ($_SERVER["REQUEST_METHOD"] == "POST") {
      if (isset($_POST)) {
         header("Location: hello.html", true, 301);  
         exit();  
      }
      // form processing if the form is not empty
   }
?>

示例

您還可以檢查提交表單時任何欄位是否為空。

<?php        
   if ($_SERVER["REQUEST_METHOD"] == "POST") {
      foreach($_POST as $k=>$v) {
         if (empty($v)==true) {
            echo "One or more fields are empty \n";
            echo "<a href = 'hello.html'>Click here to go back </a>";
            exit;
         }
         else
         echo "$k => $v \n";
      }
   }
?>

年齡欄位不是數字

在 HTML 表單中,名稱的輸入欄位為文字型別,因此它可以接受任何字元。但是,我們希望它是數字。這可以透過 is_numeric() 函式來確保。

<?php    
   if (is_numeric($_POST["age"])==false) {
      echo "Age cannot be non-numeric \n";
      echo "<a href = 'hello.html'>Click here to go back</a>";
   }
?>

PHP 還具有 is_string() 函式來檢查欄位是否包含字串。另外兩個函式 trim() 和 htmlspecialchars() 也對錶單驗證很有用。

  • trim() − 刪除字串開頭和結尾的空格

  • htmlspecialchars() − 將特殊字元轉換為 HTML 實體,以防止跨站點指令碼 (XSS) 攻擊。

PHP 表單郵件/URL

PHP 提供了兩種替代方法來驗證表單資料項,這些資料項是字串,但應表示電子郵件 ID 或 URL。檢查表單元素是否包含電子郵件/URL 的一種方法是使用正則表示式 (RegEx),另一種更方便的方法是使用 filter_var() 函式。讓我們應用這兩種方法並驗證表單提交到 PHP 指令碼的電子郵件和 URL。

本章使用的 HTML 表單如下所示:

<h1>Email and URL Validation</h1>
<form action="hello.php" method="POST">
   <p><label for="email">Enter your email:</label>
   <input type="text" id="email" name="email"></p>
   <p><label for="URL">Enter your website<label>
   <input type = "text" id="URL" name="url"></p>
   <input type="submit">
</form>

使用正則表示式進行驗證

PHP 的內建函式庫包含preg_match() 函式,該函式執行正則表示式匹配。

preg_match(
   string $pattern,
   string $subject,
   array &$matches = null,
   int $flags = 0,
   int $offset = 0
): int|false

此函式在 subject 中搜索與 pattern 中給定的正則表示式匹配的內容。如果 pattern 與給定的 subject 匹配,preg_match() 返回 1;如果不匹配,則返回 0;如果失敗,則返回false

有效的電子郵件 ID 應滿足以下正則表示式:

"/^([a-z0-9\+_\-]+)(\.[a-z0-9\+_\-]+)*@([a-z0-9\-]+\.)+[a-z]{2,6}$/ix"

同樣,有效的 URL 應滿足以下正則表示式:

"/\b(?:(?:https?|ftp):\/\/|www\.)[-a-z0-9+&@#\/%?=~_|!:,.;]*[-a-z0-9+&@#\/%=~_|]/i"

以下函式如果字串是有效的電子郵件 ID,則返回“1”或“0”。

function checkemail($str) {
   return (!preg_match("/^([a-z0-9\+_\-]+)(\.[a-z0-9\+_\-]+)*@([a-z0-9\-]+\.)+[a-z]{2,6}$/ix", $str)) ? FALSE : TRUE;
}

示例

讓我們使用checkmail() 函式來檢查上面 HTML 中的電子郵件欄位是否有效,方法如下面的 PHP 程式碼所示:

<?php         
   function checkemail($str) {
      return (!preg_match("/^([a-z0-9\+_\-]+)(\.[a-z0-9\+_\-]+)*@
         ([a-z0-9\-]+\.)+[a-z]{2,6}$/ix", $str)) ? FALSE : TRUE;
   }
   if ($_SERVER["REQUEST_METHOD"] == "POST") {
      $email = $_POST['email'];
      if(!checkemail($email)){
         echo "Invalid email address.";
      } else {
         echo "Valid email address.";
      }
   }
?>

HTML 表單呈現如下:

PHP Form Email URl

透過在電子郵件欄位中輸入有效/無效的電子郵件字串來測試 PHP 程式碼。

以下checkURL() 函式檢查字串是否表示有效或無效的 URL,並返回“1”或“0”。

function checkURL($str) {
   return (!preg_match("/\b(?:(?:https?|ftp):\/\/|www\.)
      [-a-z0-9+&@#\/%?=~_|!:,.;]*[-a-z0-9+&@#\/%=~_|]/i", $str)) ? FALSE : TRUE;
}

示例

從 $_POST 陣列中提取的 URL 欄位作為引數傳遞給上述函式。

<?php         
   function checkURL($str) {
      return (!preg_match("/\b(?:(?:https?|ftp):\/\/|www\.)[-a-z0-9+&@#\/%?=~_|!:,.;]
         *[-a-z0-9+&@#\/%=~_|]/i", $str)) ? FALSE : TRUE;
   }
   if ($_SERVER["REQUEST_METHOD"] == "POST") {
      $url = $_POST['url'];
      if(!checkURL($url)){
         echo "Invalid URL.";
      } else {
         echo "Valid URL.";
      }
   }
?>

您可以透過在上表表單的 URL 欄位中輸入 URL 字串來測試上述程式碼。

使用 filter_var() 函式

內建的 filter_var() 函式使用指定的過濾器過濾變數。

filter_var(mixed $value, int $filter = FILTER_DEFAULT, array|int $options = 0): mixed

根據$filter引數值的列舉過濾器 ID,檢查$value引數,如果過濾器失敗,則函式返回已過濾的資料,否則返回 false。

有各種預定義的過濾器 ID 常量可用:

序號 ID & 描述
1

FILTER_VALIDATE_BOOL

對於“1”、“true”、“on”和“yes”返回 true。否則返回 false。

2

FILTER_VALIDATE_DOMAIN

驗證域名標籤長度是否有效。

3

FILTER_VALIDATE_EMAIL

驗證值是否為有效的電子郵件地址。

4

FILTER_VALIDATE_IP

將值驗證為 IP 地址

5

FILTER_VALIDATE_URL

將值驗證為 URL

示例

以下 PHP 指令碼驗證上面 HTML 表單提交的電子郵件和 URL 資料:

<?php
   if ($_SERVER["REQUEST_METHOD"] == "POST") {
      $email = $_POST['email'];
      $url = $_POST['url'];

      if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
         echo "Invalid email format and please re-enter valid email\n"; 
      }
      else
      echo "Email entered is in valid format\n";

      if (!filter_var($url, FILTER_VALIDATE_URL)) {
         echo "Invalid URL format and please re-enter valid URL\n"; 
      }
      else
      echo "URL entered is in valid format\n";
   }
?>

您可以透過輸入有效/無效的電子郵件/URL 來測試上述指令碼的效能。

PHP 完整表單

本章將表單驗證和從 HTML 表單資料提取到 PHP 程式碼中的所有概念都整合在一起。下面給出的完整的表單處理程式碼包含三個部分:開頭的 PHP 程式碼部分,用於檢查提交表單時是否存在任何驗證錯誤;帶有各種元素(例如文字欄位、單選按鈕、選擇控制元件、複選框等)的 HTML 表單;第三部分再次是 PHP 程式碼,用於呈現使用者輸入的資料。

PHP 錯誤跟蹤

捕獲錯誤的程式碼位於整個指令碼的開頭。顯然,每次載入頁面時都會執行此程式碼。如果在提交表單後加載此程式碼,則以下段落會檢查每個元素是否為空,電子郵件欄位是否格式正確,以及是否單擊了複選框(表示使用者同意條款)。

<?php

   // define variables and set to empty values
   $nameErr = $emailErr = $genderErr = $websiteErr = "";
   $name = $email = $gender = $class = $course = $subject = "";

   if ($_SERVER["REQUEST_METHOD"] == "POST") {
      if (empty($_POST["name"])) {
         $nameErr = "Name is required";
      } else {
         $name = test_input($_POST["name"]);
      }

      if (empty($_POST["email"])) {
         $emailErr = "Email is required";
      } else {
         $email = test_input($_POST["email"]);
		 
         // check if e-mail address is well-formed
         if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
            $emailErr = "Invalid email format"; 
         }
      }

      if (empty($_POST["course"])) {
         $course = "";
      } else {
         $course = test_input($_POST["course"]);
      }

      if (empty($_POST["class"])) {
         $class = "";
      } else {
         $class = test_input($_POST["class"]);
      }

      if (empty($_POST["gender"])) {
         $genderErr = "Gender is required";
      } else {
         $gender = test_input($_POST["gender"]);
      }

      if (empty($_POST["subject"])) {
         $subjectErr = "You must select one or more subjects";
      } else {
         $subject = $_POST["subject"];	
      }
   }

   function test_input($data) {
      $data = trim($data);
      $data = stripslashes($data);
      $data = htmlspecialchars($data);
      return $data;
   }
?>

HTML 表單

呈現輸入表單的 HTML 指令碼位於錯誤捕獲程式碼之後。表單設計中使用了各種表單元素。

<h2>Absolute Classes Registration Form</h2>
<p><span class = "error">* required field.</span></p>
<form method = "POST" action = "<?php echo htmlspecialchars($_SERVER["PHP_SELF"]);?>">
   <table>
      <tr>
         <td>Name:</td>
         <td>
            <input type = "text" name = "name">
            <span class = "error">* <?php echo $nameErr;?></span>
         </td>
      </tr>
      <tr>
         <td>E-mail: </td>
         <td>
            <input type = "text" name = "email">
            <span class = "error">* <?php echo $emailErr;?></span>
         </td>
      </tr>
      <tr>
         <td>Time:</td>
         <td>
            <input type = "text" name = "course">
            <span class = "error"><?php echo $websiteErr;?></span>
         </td>
      </tr>
      <tr>
         <td>Classes:</td>
         <td><textarea name = "class" rows = "5" cols = "40"></textarea></td>
      </tr>
      <tr>
         <td>Gender:</td>
         <td>
            <input type = "radio" name = "gender" value = "female">Female
            <input type = "radio" name = "gender" value = "male">Male
            <span class = "error">* <?php echo $genderErr;?></span>
         </td>
      </tr>
      <tr>
         <td>Select:</td>
         <td>
            <select name = "subject[]" size = "4" multiple>
               <option value = "Android">C</option>
               <option value = "Java">Java</option>
               <option value = "C#">C#</option>
               <option value = "Data Base">C++</option>
               <option value = "Hadoop">PHP</option>
               <option value = "VB script">Python</option>
            </select>
         </td>
      </tr>
      <tr>
         <td>Agree</td>
         <td><input type = "checkbox" name = "checked" value = "1"></td>
         <?php if(!isset($_POST['checked'])){ ?>
            <span class = "error">* <?php echo "You must agree to terms";?></span>
         <?php } ?> 
      </tr>
      <tr>
         <td>
            <input type = "submit" name = "submit" value = "Submit"> 
         </td>
      </tr>
   </table>
</form>

請注意,表單資料提交回同一指令碼,因此表單的 action 屬性設定為 $_SERVER["PHP_SELF"] 超全域性變數。此部分還包含某些內聯 PHP 程式碼,這些程式碼會在相應的表單控制元件旁邊顯示錯誤訊息——例如,如果在提交表單時名稱欄位為空,則名稱文字框旁邊會顯示“名稱必填”訊息。

顯示錶單資料

指令碼的第三部分再次是 PHP 程式碼,它會回顯使用者提交的每個表單欄位的值。

<?php
   if ($_SERVER["REQUEST_METHOD"] == "POST") {
      echo "<h2>Your given values are as :</h2>";
      echo ("<p><b>Name</b> : $name</p>");
      echo ("<p><b>Email address</b> : $email</p>");
      echo ("<p><b>Preffered class time</b> : $course</p>");
      echo ("<p><b>Class info</b> : $class </p>");
      echo ("<p><b>Gender</b> : $gender</p>");
      echo "<p><b>Subjcts Chosen:</b><p>";
      if (!empty($subject)) { 
         echo "<ul>";
         for($i = 0; $i < count($subject); $i++) {
            echo "<li>$subject[$i]</u/li>";
         }
         echo "</ul>";
      }
   }
?>

這是從伺服器的文件根資料夾執行指令碼時在表單中填寫的示例資料:

PHP Complete Form 1

提交後,輸出如下所示:

PHP Complete Form 2

示例

PHP 處理 HTML 表單的完整程式碼如下:

<html>
<head>
   <style>
      .error {color: #FF0000;}
   </style>
</head>
<body>
   <?php
   
      // define variables and set to empty values
      $nameErr = $emailErr = $genderErr = $websiteErr = "";
      $name = $email = $gender = $class = $course = $subject = "";

      if ($_SERVER["REQUEST_METHOD"] == "POST") {
         if (empty($_POST["name"])) {
            $nameErr = "Name is required";
         }else {
            $name = test_input($_POST["name"]);
         }

         if (empty($_POST["email"])) {
            $emailErr = "Email is required";
         } else {
            $email = test_input($_POST["email"]);

            // check if e-mail address is well-formed
            if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
               $emailErr = "Invalid email format"; 
            }
         }

         if (empty($_POST["course"])) {
            $course = "";
         } else {
            $course = test_input($_POST["course"]);
         }

         if (empty($_POST["class"])) {
            $class = "";
         } else {
            $class = test_input($_POST["class"]);
         }

         if (empty($_POST["gender"])) {
            $genderErr = "Gender is required";
         } else {
            $gender = test_input($_POST["gender"]);
         }

         if (empty($_POST["subject"])) {
            $subjectErr = "You must select one or more subjects";
         } else {
            $subject = $_POST["subject"];	
         }
      }

      function test_input($data) {
         $data = trim($data);
         $data = stripslashes($data);
         $data = htmlspecialchars($data);
         return $data;
      }
   ?>
   <h2>Absolute Classes Registration Form</h2>
   <p><span class = "error">* required field.</span></p>
   <form method = "POST" action = "<?php echo htmlspecialchars($_SERVER["PHP_SELF"]);?>">
      <table>
         <tr>
            <td>Name:</td>
            <td>
               <input type = "text" name = "name">
               <span class = "error">* <?php echo $nameErr;?></span>
            </td>
         </tr>
         <tr>
            <td>E-mail: </td>
            <td>
               <input type = "text" name = "email">
               <span class = "error">* <?php echo $emailErr;?></span>
            </td>
         </tr>
         <tr>
            <td>Time:</td>
            <td> 
               <input type = "text" name = "course">
               <span class = "error"><?php echo $websiteErr;?></span>
            </td>
         </tr>
         <tr>
            <td>Classes:</td>
            <td><textarea name = "class" rows = "5" cols = "40"></textarea></td>
         </tr>
         <tr>
            <td>Gender:</td>
            <td>
               <input type = "radio" name = "gender" value = "female">Female
               <input type = "radio" name = "gender" value = "male">Male
               <span class = "error">* <?php echo $genderErr;?></span>
            </td>
         </tr>
         <tr>
            <td>Select:</td>
            <td>
               <select name = "subject[]" size = "4" multiple>
                  <option value = "C">C</option>
                  <option value = "Java">Java</option>
                  <option value = "C#">C#</option>
                  <option value = "c++">C++</option>
                  <option value = "PHP">PHP</option>
                  <option value = "Python">Python</option>
               </select>
            </td>
         </tr>
         <tr>
            <td>Agree</td>
            <td><input type = "checkbox" name = "checked" value = "1"></td>
            <?php if(!isset($_POST['checked'])){ ?>
               <span class = "error">* <?php echo "You must agree to terms";?></span>
            <?php } ?> 
         </tr>
         <tr>
            <td>
               <input type = "submit" name = "submit" value = "Submit"> 
            </td>
         </tr>
      </table>
   </form>
   <?php
      if ($_SERVER["REQUEST_METHOD"] == "POST") {
         echo "<h2>Your given values are as :</h2>";
         echo ("<p><b>Name</b> : $name</p>");
         echo ("<p><b>Email address</b> : $email</p>");
         echo ("<p><b>Preffered class time</b> : $course</p>");
         echo ("<p><b>Class info</b> : $class </p>");
         echo ("<p><b>Gender</b> : $gender</p>");
         echo "<p><b>Subjcts Chosen:</b><p>";
         if (!empty($subject)) { 
            echo "<ul>";
            for($i = 0; $i < count($subject); $i++) {
               echo "<li>$subject[$i]</u/li>";
            }
            echo "</ul>";
         }
      }
   ?>
</body>
</html>

它將產生以下輸出

PHP Complete Form 1

PHP 檔案包含

您可以在伺服器執行之前將一個 PHP 檔案的內容包含到另一個 PHP 檔案中。可以使用兩個 PHP 函式將一個 PHP 檔案包含到另一個 PHP 檔案中。

  • include() 函式

  • require() 函式

這是PHP的一個強大之處,它有助於建立可在多個頁面上重複使用的函式、頁首、頁尾或元素。這將幫助開發人員輕鬆地以最小的努力更改整個網站的佈局。如果需要任何更改,則只需更改包含的檔案,而無需更改數千個檔案。

include() 函式

include() 函式獲取指定檔案中的所有文字,並將其複製到使用 include 函式的檔案中。如果載入檔案時出現任何問題,則include() 函式會生成警告,但指令碼將繼續執行。

假設您想為您的網站建立一個公共選單。然後建立一個名為 menu.php 的檔案,內容如下。

<a href="https://tutorialspoint.tw/index.htm">Home</a> 
<a href="https://tutorialspoint.tw/ebxml">ebXML</a>   
<a href="https://tutorialspoint.tw/ajax">AJAX</a>   
<a href="https://tutorialspoint.tw/perl">PERL</a> 

現在建立任意數量的頁面,幷包含此檔案以建立頁首。例如,現在您的 test.php 檔案可以包含以下內容。

<?php <b>include("menu.php");</b> ?>
<p>This is an example to show how to include PHP file!</p>

它將產生以下結果 -

Include

require() 函式

require() 函式獲取指定檔案中的所有文字,並將其複製到使用 include 函式的檔案中。如果載入檔案時出現任何問題,則require() 函式會生成致命錯誤並停止指令碼執行。

因此,require() 和 include() 之間的區別僅在於它們處理錯誤條件的方式。建議使用 require() 函式而不是 include() 函式,因為如果檔案丟失或名稱錯誤,指令碼不應繼續執行。

您可以嘗試使用上述示例和 require() 函式,它將生成相同的結果。但是,如果您嘗試以下兩個不存在檔案的示例,您將得到不同的結果。

<?php include("xxmenu.php"); ?>
<p>This is an example to show how to include wrong PHP file!</p>

這將產生以下結果:

This is an example to show how to include wrong PHP file!

現在讓我們嘗試使用 require() 函式的相同示例。

<?php <b>require("xxmenu.php");</b> ?>
<p>This is an example to show how to include wrong PHP file!</p>

這次檔案執行停止,沒有任何內容顯示。

注意 - 您可能會收到簡單的警告訊息、致命錯誤訊息或根本沒有任何訊息。這取決於您的 PHP 伺服器配置。

PHP GET 和 POST

由於PHP主要用於Web應用程式開發,瀏覽器客戶端傳送的資料主要採用GET和POST型別的HTTP請求方法。HTTP協議還定義了其他用於向伺服器傳送請求的方法。它們是PUT、DELETE、HEAD和OPTIONS(除了GET和POST方法)。在本章中,我們將重點介紹PHP如何處理GET和POST方法。

GET方法

GET方法傳送附加到頁面請求的編碼使用者資訊。頁面和編碼資訊由?字元分隔。

http://www.test.com/index.htm?name1=value1&name2=value2
  • GET 方法會產生一個長字串,該字串會出現在您的伺服器日誌中以及瀏覽器的“位置:”框中。

  • GET方法僅限於傳送最多1024個字元。

  • 如果要傳送密碼或其他敏感資訊到伺服器,切勿使用GET方法。

  • GET不能用於向伺服器傳送二進位制資料,例如影像或Word文件。

  • 透過GET方法傳送的資料可以使用QUERY_STRING環境變數訪問。

  • PHP提供$_GET關聯陣列,可以使用GET方法訪問所有傳送的資訊。

透過將原始碼放入 test.php 指令碼中來嘗試以下示例。

<?php
   if( $_GET["name"] || $_GET["age"] ) {
      echo "Welcome ". $_GET['name']. "<br />";
      echo "You are ". $_GET['age']. " years old.";
      
      exit();
   }
?>
<form action = "<?php <b>$_PHP_SELF</b> ?>" method = "GET">
   Name: <input type = "text" name = "name" />
   Age: <input type = "text" name = "age" />
   <input type = "submit" />
</form>

它將產生以下結果 -

Forms

POST方法

POST方法透過HTTP標頭傳輸資訊。資訊按照GET方法中描述的方式進行編碼,並放入名為QUERY_STRING的標頭中。

  • POST方法對要傳送的資料大小沒有任何限制。

  • POST方法可用於傳送ASCII和二進位制資料。

  • 透過POST方法傳送的資料透過HTTP標頭,因此安全性取決於HTTP協議。透過使用安全HTTP,您可以確保您的資訊安全。

  • PHP提供$_POST關聯陣列,可以使用POST方法訪問所有傳送的資訊。

透過將原始碼放入 test.php 指令碼中來嘗試以下示例。

<?php
   if( $_POST["name"] || $_POST["age"] ) {
      if (preg_match("/[^A-Za-z'-]/",$_POST['name'] )) {
         die ("invalid name and name should be alpha");
      }
      echo "Welcome ". $_POST['name']. "<br />";
      echo "You are ". $_POST['age']. " years old.";
      
      exit();
   }
?>
<form action = "<?php <b>$_PHP_SELF</b> ?>" method = "POST">
   Name: <input type = "text" name = "name" />
   Age: <input type = "text" name = "age" />
   <input type = "submit" />
</form>

它將產生以下結果 -

Forms

GET和POST的區別

GET和POST方法的主要區別在於,雖然附加到URL的請求引數在瀏覽器的URL中公開,但POST資料包含在訊息正文中,並且不會在URL中顯示。因此,不應使用GET方法向伺服器傳送敏感資料。

其次,GET方法中的請求資料不能超過2048個字元,並且只能包含ASCII字元,而POST方法對請求資料沒有限制,也可以是二進位制資料(POST資料的預設最大大小由php.ini檔案中的post_max_size設定確定)。

PHP提供以下三個超級全域性變數來檢索和處理請求引數:

  • $_GET - 一個關聯陣列,用於使用GET方法訪問所有傳送的資訊。

  • $_POST - 一個關聯陣列,用於使用POST方法訪問所有傳送的資訊。

  • $_REQUEST - 一個關聯陣列,可用於獲取透過GET和POST方法傳送的表單資料的結果。

$_GET陣列

您可以將請求引數以直接附加到URL的查詢字串的形式傳遞。

將以下PHP指令碼儲存在文件根資料夾(htdocs)中,命名為“hello.php”:

<?php
   echo "First name: " . $_REQUEST['first_name'] . " " . 
      "Last Name: " . $_REQUEST['last_name'] . "";
?>

在瀏覽器視窗中輸入https:///hello.php?first_name=Amar&last_name=Sharma作為URL(確保PHP伺服器正在執行)。

$_GET陣列將從請求中填充,輸出如下所示:

First name: Amar Last Name: Sharma

如果HTML表單的method屬性為GET,您也可以使用HTML表單資料填充$_GET陣列。

使用以下HTML表單收集資料並將其傳送到“hello.php”。在文件根目錄下,將以下指令碼儲存為“hello.html”:

<form action="hello.php" method="get">
   First Name: <input type="text" name="first_name"/>  <br/>
   Last Name: <input type="text" name="last_name" />
   <input type="submit" value="Submit" />
</form>

在您的瀏覽器中,輸入URL“https:///hello.html”:

PHP Get Post

您應該在瀏覽器視窗中獲得類似的輸出

$_POST陣列

向伺服器傳送POST請求資料的最簡單方法是將HTML表單的method屬性指定為POST。假設瀏覽器中的URL是“https:///hello.php”,method=POST設定在HTML表單“hello.html”中,如前面的示例所示:

<form action="hello.php" method="post">
   First Name: <input type="text" name="first_name"/>  <br/>
   Last Name: <input type="text" name="last_name" />
   <input type="submit" value="Submit" />
</form> 

“hello.php”指令碼(在文件根資料夾中)在$_POST陣列中檢索表單資料,並將其呈現為HTTP響應返回給瀏覽器:

<?php
   echo "First name: " . $_POST['first_name'] . " " . 
      "Last Name: " . $_POST['last_name'] . "";
?>

在瀏覽器中開啟“https:///hello.html”。輸入的資料將由伺服器檢索,並如前面的示例一樣呈現回客戶端。

PHP 檔案上傳

典型PHP Web應用程式所需的一個常見功能是允許使用者上傳檔案的功能。在PHP中,從客戶端上傳檔案非常容易。在本章中,我們將學習如何使用PHP指令碼進行檔案上傳過程。

上傳檔案的過程遵循以下步驟:

  • 使用者開啟包含HTML表單的頁面,該表單包含文字檔案、瀏覽按鈕和提交按鈕。

  • 使用者單擊瀏覽按鈕,並從本地PC中選擇要上傳的檔案。

  • 選定檔案的完整路徑顯示在文字欄位中,然後使用者單擊提交按鈕。

  • 選定的檔案被髮送到伺服器上的臨時目錄。

  • 在表單的action屬性中指定為表單處理程式的PHP指令碼檢查檔案是否已到達,然後將檔案複製到目標目錄。

  • PHP指令碼向用戶確認成功。

為了執行此操作,我們必須首先確保在“php.ini”中啟用了與檔案上傳相關的配置設定。

開啟“php.ini”檔案,並確保透過刪除file_uploads、upload_tmp_dir、upload_max_filesize和max_file_uploads引數開頭的分號(;)符號來啟用以下設定:

;;;;;;;;;;;;;;;;
; File Uploads ;
;;;;;;;;;;;;;;;;

; Whether to allow HTTP file uploads.
; https://php.net.tw/file-uploads
file_uploads=On

; Temporary directory for HTTP uploaded files (will use system
; default if not specified).
; https://php.net.tw/upload-tmp-dir
upload_tmp_dir="C:\xampp\tmp"

; Maximum allowed size for uploaded files.
; https://php.net.tw/upload-max-filesize
upload_max_filesize=40M

; Maximum number of files that can be uploaded via a single request
max_file_uploads=20

臨時位置和最終位置的資料夾必須設定允許檔案寫入的許可權。如果任一設定為只讀,則過程將失敗。

建立檔案上傳表單

接下來,我們需要設計一個用於檔案上傳的HTML表單。表單的method屬性必須為POST,enctype必須為multipart/form-data。使用input型別為file,允許使用者瀏覽並選擇要上傳的檔案。

<h2>File Upload Form</h2>
<form method = "POST" action = "uploadfile.php" enctype="multipart/form-data">
   <label for="file">File name:</label>
   <input type="file" name="uploadfile" />
   <input type="submit" name="submit" value="Upload" />
</form>

建立上傳指令碼

uploadfile.php指令碼接收上傳的檔案。檔案資料收集在一個超級全域性變數$_FILES中。獲取上傳檔案的名稱、檔案型別、大小和tmp_name屬性。

move_uploaded_file()函式將選定的檔案複製到文件資料夾。

<?php
   echo "<b>File to be uploaded: </b>" . $_FILES["uploadfile"]["name"] . "<br>";
   echo "<b>Type: </b>" . $_FILES["uploadfile"]["type"] . "<br>";
   echo "<b>File Size: </b>" . $_FILES["uploadfile"]["size"]/1024 . "<br>";
   echo "<b>Store in: </b>" . $_FILES["uploadfile"]["tmp_name"] . "<br>";

   if (file_exists($_FILES["uploadfile"]["name"])){
      echo "<h3>The file already exists</h3>";
   } else {
      move_uploaded_file($_FILES["uploadfile"]["tmp_name"], $_FILES["uploadfile"]["name"]);
      echo "<h3>File Successfully Uploaded</h3>";
   }
?>

假設myform.php和uploadfile.php這兩個檔案都儲存在文件資料夾中。

在瀏覽器中開啟“myform.php”(https:///myform.php):

PHP File Uploading 1

單擊檔案按鈕,瀏覽到要上傳的目標檔案,然後單擊上傳按鈕。

伺服器將返回以下訊息:

PHP File Uploading 2

PHP Cookie

全球資訊網由HTTP協議提供支援,HTTP協議是一種無狀態協議。Cookie機制幫助伺服器維護先前請求的資訊。PHP透明地支援HTTP Cookie。

  • 當客戶端第一次傳送請求時,伺服器會將其響應作為Cookie的一部分包含一小部分資料。PHP提供setcookie()方法來在響應中注入Cookie。

  • 此Cookie資料作為文字檔案儲存在客戶端的計算機中。在相同客戶端的後續訪問中,這些Cookie作為請求標頭的一部分包含。

  • 伺服器使用客戶端請求中存在的所有Cookie填充PHP超級全域性變數“$_COOKIE”。

本章將教你如何設定Cookie,如何訪問它們以及如何刪除它們。

Cookie的結構

Cookie通常設定在HTTP標頭中(儘管JavaScript也可以直接在瀏覽器上設定Cookie)。設定Cookie的PHP指令碼可能會發送如下所示的標頭:

HTTP/1.1 200 OK
Date: Fri, 04 Feb 2000 21:03:38 GMT
Server: Apache/1.3.9 (UNIX) PHP/4.0b3
Set-Cookie: name=xyz; expires=Friday, 04-Feb-07 22:03:38 GMT; 
                 path=/; domain=tutorialspoint.com
Connection: close
Content-Type: text/html

如您所見,Set-Cookie標頭包含一個名稱值對、一個GMT日期、一個路徑和一個域。名稱和值將進行URL編碼。expires欄位是指示瀏覽器在給定的時間和日期後“忘記”Cookie的指令。

如果瀏覽器配置為儲存Cookie,它將保留此資訊,直到過期日期。如果使用者將瀏覽器指向與Cookie的路徑和域匹配的任何頁面,它將把Cookie重新發送到伺服器。瀏覽器的標頭可能如下所示:

GET / HTTP/1.0
Connection: Keep-Alive
User-Agent: Mozilla/4.6 (X11; I; Linux 2.2.6-15apmac ppc)
Host: zink.demon.co.uk:1126
Accept: image/gif, */*
Accept-Encoding: gzip
Accept-Language: en
Accept-Charset: iso-8859-1,*,utf-8
Cookie: name=xyz

然後,PHP指令碼可以透過環境變數$_COOKIE或$HTTP_COOKIE_VARS[]訪問Cookie,該變數包含所有Cookie名稱和值。可以使用$HTTP_COOKIE_VARS["name"]訪問上面的Cookie。

如何在PHP中設定Cookie?

PHP包含setcookie函式,用於建立一個Cookie物件,以便與HTTP響應一起傳送到客戶端。

setcookie(name, value, expire, path, domain, security);

引數

以下是所有引數的詳細資訊:

  • 名稱 - 這將設定Cookie的名稱,並存儲在一個名為HTTP_COOKIE_VARS的環境變數中。訪問Cookie時使用此變數。

  • - 這將設定命名變數的值,並且是您實際要儲存的內容。

  • 過期時間 - 這指定自1970年1月1日00:00:00 GMT以來的秒數。在此時間之後,Cookie將變得不可訪問。如果未設定此引數,則Cookie將在Web瀏覽器關閉時自動過期。

  • 路徑 - 這指定Cookie有效的目錄。單個正斜槓字元允許Cookie對所有目錄都有效。

  • - 這可用於在非常大的域中指定域名,並且必須包含至少兩個點才能有效。所有Cookie僅對建立它們的宿主和域有效。

  • 安全性 - 這可以設定為1,以指定Cookie應該只通過使用HTTPS的安全傳輸傳送,否則設定為0,這意味著Cookie可以透過常規HTTP傳送。

示例

下面的PHP指令碼檢查名為username的Cookie是否已設定,如果已設定,則檢索其值。如果沒有,則設定一個新的Cookieusername

<?php
   if (isset($_COOKIE['username'])) {
      echo "<h2>Cookie username already set:" . $_COOKIE['username'] . "</h2>";
   } else {
      setcookie("username", "MohanKumar");
      echo "<h2>Cookie username is now set</h2>";
   }
?>

從Apache伺服器的文件根目錄執行此指令碼。您應該看到此訊息:

Cookie username is now set

如果重新執行此指令碼,則 Cookie 現在已設定。

Cookie username already set: MohanKumar

您的瀏覽器的開發者工具是一個非常有用的工具。您可以使用它來設定、檢索和刪除Cookie。上述程式設定的Cookie可以在瀏覽器開發者工具的“應用程式”選項卡下檢視。

PHP Cookies

如下所示的foreach迴圈檢索所有Cookie:

<?php
   $arr=$_COOKIE;
   foreach ($arr as $key=>$val);
   echo "<h2>$key=>$val </h2>";
?>

下面的指令碼包含一個HTML表單。它將表單資料傳送到setcookie.php指令碼,該指令碼使用從$_POST陣列檢索到的資料設定cookie。

HTML表單由以下程式碼呈現:

<form action="setcookie.php" method="POST">
   <input type="text" name="name">
   <input type="text" name="age">
   <input type="submit" name="Submit">
</form>

SetCookie.php讀取表單資料並設定cookie。

if (isset($_POST["submit"]) {
   setcookie("name", $_POST["name"]);
   setcookie("age", $_POST["age"]);
}

使用另一個getcookie.php程式碼,我們可以檢索設定的cookie。

if (isset($_COOKIE["name"])
echo "Cookie: name => " . $_COOKIE["name"]. "<br>";
if (isset($_COOKIE["age"])
echo "Cookie: age => " . $_COOKIE["age"]. "<br>";

使用PHP訪問Cookie

PHP提供了許多訪問cookie的方法。最簡單的方法是使用$_COOKIE或$HTTP_COOKIE_VARS變數。以下示例將訪問在上述示例中設定的所有cookie。

<?php
   echo $_COOKIE["name"]. "<br />";

   /* is equivalent to */
   echo $HTTP_COOKIE_VARS["name"]. "<br />";

   echo $_COOKIE["age"] . "<br />";

   /* is equivalent to */
   echo $HTTP_COOKIE_VARS["age"] . "<br />";
?>    

您可以使用isset()函式檢查是否設定了cookie。

<?php
   if( isset($_COOKIE["name"]))
      echo "Welcome " . $_COOKIE["name"] . "<br />";

   else
      echo "Sorry... Not recognized" . "<br />";
?>

刪除Cookie

要刪除cookie,請設定一個已過期日期的cookie,以便瀏覽器觸發cookie刪除機制。

示例

請看以下示例:

<?php
   setcookie("username", "", time() - 3600);
   echo "<h2>Cookie username is now removed</h2>";
?>

瀏覽器顯示以下響應:

Cookie username is now removed

您也可以透過在cookie名稱中使用陣列表示法來設定陣列cookie。

setcookie("user[three]", "Guest");
setcookie("user[two]", "user");
setcookie("user[one]", "admin");

如果cookie名稱包含點(.),PHP會將它們替換為下劃線(_)。

儘管cookie背後的主要目的是幫助Web開發者提供更個性化和便捷的使用者體驗,但它可能會對您的隱私和個人資訊構成風險。

在某些情況下,如果您不接受其cookie,應用程式可能會拒絕您完全訪問。在這種情況下,建議定期清除瀏覽器快取中與cookie相關的 資料。

PHP Session

Web會話是從使用者與伺服器建立連線的時間到連線終止的時間段。與cookie一起,會話變數使資料可在整個網站的各個頁面之間訪問。

在會話期間,網站會維護有關使用者操作和偏好的資訊。會話資料填充在超全域性關聯陣列$_SESSION中。

要在PHP中啟動新會話,您需要呼叫session_start()函式。

啟動會話

為了啟用對會話資料的訪問,必須呼叫session_start()函式。session_start()根據透過GET或POST請求傳遞的會話識別符號,或透過cookie傳遞的會話識別符號,建立會話或恢復當前會話。

session_start(array $options = []): bool

如果會話成功啟動,此函式返回true,否則返回false

PHP首先為該特定會話建立一個唯一的識別符號,這是一個32個十六進位制數字的隨機字串。

session_id()函式設定或檢索唯一的會話ID。

session_id(?string $id = null): string|false

如果沒有給出$id引數,PHP將生成一個隨機的會話ID。您可以指定您自己的ID。該函式返回當前會話的會話ID,如果當前沒有會話,則返回空字串。失敗時,它返回false

示例

請看以下示例:

<?php  
   // Starting the session
   session_start();
   $id = session_id();
   echo "Session Id: ".$id ;
?>

瀏覽器將顯示一個隨機字串作為輸出

Session Id: mi3976f8ssethe9f04vq1ag6it

名為PHPSESSID的cookie會自動傳送到使用者的計算機,以儲存唯一的會話識別符號字串。

PHP Sessions 1

會話在伺服器上的臨時目錄中建立一個檔案,其中儲存註冊的會話變數及其值。在此訪問期間,此資料將可用於網站上的所有頁面。

臨時檔案的位置由"php.ini"檔案中名為"session.save_path"的設定確定。

處理會話變數

會話變數儲存在名為$_SESSION[]的關聯陣列中。這些變數可以在會話的生命週期內訪問。

要建立一個新的會話變數,請在$_SESSION陣列中新增一個鍵值對:

$_SESSION[ "var"]=value;

要讀取會話變數的值,您可以使用echo/print語句,或var_dump()或print_r()函式。

echo $_SESSION[ "var"];

要獲取當前會話中所有會話變數的列表,您可以使用foreach迴圈遍歷$_SESSION:

foreach ($_SESSION as $key=>$val)
echo $key . "=>" . $val;

示例

以下示例啟動一個會話,然後註冊一個名為counter的變數,該變數在會話期間每次訪問頁面時都會遞增。

使用isset()函式檢查會話變數是否已設定。

以下PHP指令碼在第一次執行時啟動一個會話,並設定一個名為counter的會話變數。當客戶端再次訪問相同的URL時,由於會話變數已設定,因此計數器會遞增。

<?php
   session_start();
   if( isset( $_SESSION['counter'] ) ) {
      $_SESSION['counter'] += 1;
   } else {
      $_SESSION['counter'] = 1;
   }
   $msg = "Number of visits in this session: ".  $_SESSION['counter'];
?>
<?php  
   echo "$msg"; 
?>

多次重新整理瀏覽器以模擬重複訪問。瀏覽器顯示計數器:

Number of visits in this session: 5

銷燬PHP會話

可以使用session_destroy()函式銷燬PHP會話。此函式不需要任何引數,一次呼叫即可銷燬所有會話變數。如果您想銷燬單個會話變數,則可以使用unset()函式來取消設定會話變數。

這是一個取消設定單個變數的示例:

<?php
   unset($_SESSION['counter']);
?>

這是將銷燬所有會話變數的呼叫:

<?php
   session_destroy();
?>

如果您可以在php.ini檔案中將session.auto_start變數設定為1,則當用戶訪問您的網站時,您不需要呼叫start_session()函式來啟動會話。

示例

以下PHP指令碼呈現一個HTML表單。表單資料用於建立三個會話變數。超連結將瀏覽器帶到另一個頁面,該頁面讀取會話變數。

<html>
<body>
   <form action="<?php echo $_SERVER['PHP_SELF'];?>" method="post">
      <h3>User's ID: <input type="text" name="ID"/></h3>
      <h3>User's Name: <input type="text" name="name"/></h3>
      <h3>User Type: <input type="text" name="type"/></h3>
      <input type="submit" value="Submit" />
   </form>

   <?php
      session_start();
      if ($_SERVER["REQUEST_METHOD"] == "POST") {
         $_SESSION['ID'] = $_POST['ID'];
         $_SESSION['Name'] = $_POST['name'];
         $_SESSION['type'] = $_POST['type'];

         echo "<h2>Following Session variables Created</h2>";
         foreach ($_SESSION as $key=>$val) {
            echo "<h3>" . $key . "=>" . $val . "</h3>";
         }
         echo "<a href='test.php'><b>Click Here</b></a>";
      }
   ?>
</body>
</html>

將此程式碼另存為文件根資料夾中的"hello.php",並在客戶端瀏覽器中開啟它。

PHP Sessions 2

按下提交按鈕。瀏覽器將顯示建立的會話變數:

PHP Sessions 3

瀏覽器透過遵循顯示的連結導航到另一個頁面。它讀取回會話變數。

PHP Sessions 3

PHP Session 選項

從PHP 7版本開始,session_start()函式接受一個選項陣列,以覆蓋在"php.ini"中設定的會話配置指令。"php.ini"中的[session]部分定義了各種選項的預設值。

如果提供選項,則其形式為選項的關聯陣列,這些選項將覆蓋當前設定的會話配置指令。鍵不應包含"session."字首。

示例

例如,您可以使用定義為session_start()函式引數的兩個會話選項啟動HTTP會話:

<?php
   session_start([
      'cache_limiter' => 'private',
      'read_and_close' => true,
   ]);
?>

HTTP會話的可配置選項

PHP中HTTP會話的一些可配置選項如下:

session.name

它指定用作cookie名稱的會話名稱。它應該只包含字母數字字元。預設為PHPSESSID。

session.save_handler

它定義用於儲存和檢索與會話關聯的資料的處理程式的名稱。預設為files。

session.auto_start

它指定會話模組是否在請求啟動時自動啟動會話。預設為0(停用)。

session.cookie_lifetime

它以秒為單位指定傳送到瀏覽器的cookie的生命週期。值0表示“直到瀏覽器關閉”。預設為0。

session.cache_limiter

它指定用於會話頁面的快取控制方法。它可以是以下值之一:nocache、private、private_no_expire或public。預設為nocache。

session.sid_length

它允許您指定會話ID字串的長度。會話ID長度可以在22到256之間。預設為32。

session.upload_progress.enabled

它啟用上傳進度跟蹤,填充$_SESSION變數。預設為1,啟用。

session.lazy_write

當它設定為1時,這意味著只有在會話資料更改時才會重寫它。預設為1,啟用。

PHP 傳送郵件

傳送電子郵件是典型的PHP驅動Web應用程式的常用功能之一。您希望透過PHP應用程式本身傳送包含通知、更新和其他通訊的電子郵件給註冊使用者,而不是使用不同的郵件服務。您可以透過採用本章中描述的技術,將此功能新增到您的PHP應用程式中。

PHP有一個內建的mail()函式來發送電子郵件。但是,您需要正確配置"php.ini"設定才能這樣做。首先,您必須知道您正在使用的Web託管平臺的SMTP域。例如,如果您的網站託管在GoDaddy託管服務上,則SMTP域為"smtp.secureserver.net",您應該在配置中使用它。

如果您使用GoDaddy的基於Windows的託管,您應該確保在php.ini檔案中啟用了兩個指令。第一個稱為SMTP,它定義您的電子郵件伺服器地址。第二個稱為sendmail_from,它定義您自己的電子郵件地址。

Windows的配置如下所示:

[mail function]
; For Win32 only.
SMTP = smtp.secureserver.net

; For win32 only
sendmail_from = webmaster@tutorialspoint.com

Linux使用者只需讓PHP知道其sendmail應用程式的位置即可。路徑和任何所需的開關都應指定給sendmail_path指令。

Linux的配置如下所示:

[mail function]
; For Win32 only.
SMTP =

; For win32 only
sendmail_from = 

; For Unix only
sendmail_path = /usr/sbin/sendmail -t -i

PHP中的mail()函式需要三個必填引數,它們指定收件人的電子郵件地址、郵件的主題和實際郵件,此外還有另外兩個可選引數。

mail( to, subject, message, headers, parameters );

引數

  • to - 必需。指定電子郵件的接收者/接收者

  • subject - 必需。指定電子郵件的主題。此引數不能包含任何換行符

  • message - 必需。定義要傳送的訊息。每一行都應該用LF(\n)分隔。行不應超過70個字元

  • headers - 可選。指定其他標頭,如From、Cc和Bcc。其他標頭應以CRLF(\r\n)分隔

  • parameters - 可選。向sendmail程式指定附加引數

多個收件人可以作為mail()函式的第一個引數以逗號分隔的列表的形式指定。

傳送HTML電子郵件

當您使用PHP傳送文字訊息時,所有內容都將被視為純文字。即使您在文字訊息中包含HTML標記,它也會顯示為純文字,並且HTML標記不會根據HTML語法進行格式化。但是PHP提供了將HTML訊息作為實際HTML訊息傳送的選項。

傳送電子郵件時,您可以指定Mime版本、內容型別和字元集以傳送HTML電子郵件。

示例

以下示例顯示如何將HTML電子郵件訊息傳送到"xyz@somedomain.com",並將其抄送至"afgh@somedomain.com"。您可以編寫此程式,使其接收使用者的所有內容,然後傳送電子郵件。

它應該接收使用者的所有內容,然後傳送電子郵件。

<?php
   $to = "xyz@somedomain.com";
   $subject = "This is subject";

   $message = "<b>This is HTML message.</b>";
   $message .= "<h1>This is headline.</h1>";

   $header = "From:abc@somedomain.com \r\n";
   $header .= "Cc:afgh@somedomain.com \r\n";
   $header .= "MIME-Version: 1.0\r\n";
   $header .= "Content-type: text/html\r\n";

   $retval = mail ($to,$subject,$message,$header);

   if( $retval == true ) {
      echo "Message sent successfully...";
   }else {
      echo "Message could not be sent...";
   }
?>

它將產生以下輸出

Message could not be sent...
sh: 1: /usr/sbin/sendmail: not found

從本地主機發送電子郵件

以上呼叫PHP mail()的方法可能無法在您的本地主機上執行。在這種情況下,有一種替代的傳送電子郵件的解決方案。您可以使用PHPMailer透過本地主機的SMTP傳送電子郵件。

PHPMailer是一個開源庫,用於連線SMTP來發送電子郵件。您可以從PEAR或Composer儲存庫下載它,也可以從https://github.com/PHPMailer/PHPMailer下載它。從此處下載ZIP檔案,並將PHPMailer資料夾的內容複製到PHP配置中指定的include_path目錄之一,並手動載入每個類檔案。

示例

使用以下PHP指令碼使用PHPMailer庫傳送電子郵件:

Phpmailer.php

<?php
   use PHPMailer\PHPMailer\PHPMailer;
   use PHPMailer\PHPMailer\SMTP;
   use PHPMailer\PHPMailer\Exception;

   require_once __DIR__ . '/vendor/phpmailer/src/Exception.php';
   require_once __DIR__ . '/vendor/phpmailer/src/PHPMailer.php';
   require_once __DIR__ . '/vendor/phpmailer/src/SMTP.php';  
   require 'vendor/autoload.php';

   $mail = new PHPMailer;
   if(isset($_POST['send'])){
   
      // getting post values
      $fname=$_POST['fname'];		
      $toemail=$_POST['toemail'];	
      $subject=$_POST['subject'];	
      $message=$_POST['message'];
      $mail->isSMTP();					      // Set mailer to use SMTP
      $mail->Host = 'smtp.gmail.com';             
      $mail->SMTPAuth = true;                     
      $mail->Username = 'myID@gmail.com';	// SMTP username
      $mail->Password = 'mypassword'; 		// SMTP password

      // Enable TLS encryption, 'ssl' also accepted
      $mail->SMTPSecure = 'tls';
      $mail->Port = 587;                          
      $mail->setFrom(myID@gmail.com', 'My_Name');
      $mail->addReplyTo(myID@gmail.com', 'My_Name');
      $mail->addAddress($toemail);   	  // Add a recipient
      $mail->isHTML(true);                // Set email format to HTML
      $bodyContent=$message;
      $mail->Subject =$subject;
      $body = 'Dear'.$fname;
      $body .='<p>'.$message.'</p>';
      $mail->Body = $body;

      if(!$mail->send()) {
         echo 'Message could not be sent.';
         echo 'Mailer Error: ' . $mail->ErrorInfo;
      } else {
         echo 'Message has been sent';
      }
   }
?>

使用以下HTML表單撰寫郵件。表單提交到上面的phpmail.php指令碼

Email.html

<h1>PHP - Sending Email</h1>
<form action="PHPmailer.php" method="post">
   <label for="inputName">Name</label>
   <input type="text" id="inputName" name="fname" required>

   <label for="inputEmail">Email</label>
   <input type="email" id="inputEmail" name="toemail" required>

   <label for="inputSubject">Subject</label>
   <input type="text" id="inputSubject" name="subject" required>

   <label for="inputMessage">Message</label>
   <textarea id="inputMessage" name="message" rows="5" required></textarea>

   <button type="submit" name="send">Send</button>
</form>

傳送帶有附件的電子郵件

要傳送包含混合內容的電子郵件,應將 Content-type 頭設定為 multipart/mixed。然後可以在邊界內指定文字和附件部分。

邊界以兩個連字元開頭,後面跟著一個唯一的數字,該數字不能出現在電子郵件的訊息部分中。PHP 函式 md5() 用於建立一個 32 位十六進位制數字來建立唯一數字。表示電子郵件最後一部分的最終邊界也必須以兩個連字元結尾。

示例

請看以下示例:

<?php

   // request variables 	
   $from = $_REQUEST["from"];
   $emaila = $_REQUEST["emaila"];
   $filea = $_REQUEST["filea"];

   if ($filea) {
      function mail_attachment ($from , $to, $subject, $message, $attachment){
         $fileatt = $attachment; 		// Path to the file
         $fileatt_type = "application/octet-stream"; // File Type 

         $start = strrpos($attachment, '/') == -1 ? 
         strrpos($attachment, '//') : strrpos($attachment, '/')+1;

         // Filename that will be used for the file as the attachment
         $fileatt_name = substr($attachment, $start, 
         strlen($attachment));

         $email_from = $from; 		// Who the email is from
         $subject = "New Attachment Message";

         $email_subject =  $subject; // The Subject of the email 
         $email_txt = $message;     // Message that the email has in it 
         $email_to = $to; 	 	   // Who the email is to

         $headers = "From: ".$email_from;
         $file = fopen($fileatt,'rb'); 
         $data = fread($file,filesize($fileatt)); 
         fclose($file); 

         $msg_txt="\n\n You have recieved a new attachment message from $from";
         $semi_rand = md5(time()); 
         $mime_boundary = "==Multipart_Boundary_x{$semi_rand}x"; 
         $headers .= "\nMIME-Version: 1.0\n" . "Content-Type: multipart/mixed;\n" . "
         boundary=\"{$mime_boundary}\"";

         $email_txt .= $msg_txt;

         $email_message .= "This is a multi-part message in MIME format.\n\n" . 
         "--{$mime_boundary}\n" . "Content-Type:text/html; 
         charset = \"iso-8859-1\"\n" . "Content-Transfer-Encoding: 7bit\n\n" . 
         $email_txt . "\n\n";

         $data = chunk_split(base64_encode($data));

         $email_message .= "--{$mime_boundary}\n" . "Content-Type: {$fileatt_type};\n" .
         " name = \"{$fileatt_name}\"\n" . //"Content-Disposition: attachment;\n" . 
         //" filename = \"{$fileatt_name}\"\n" . "Content-Transfer-Encoding: 
         "base64\n\n" . $data . "\n\n" . "--{$mime_boundary}--\n";

         $ok = mail($email_to, $email_subject, $email_message, $headers);

         if($ok) {
            echo "File Sent Successfully.";
            // delete a file after attachment sent.
            unlink($attachment);
         } else {
            die("Sorry but the email could not be sent. Please go back and try again!");
         }
      }
      move_uploaded_file($_FILES["filea"]["tmp_name"],
      'temp/'.basename($_FILES['filea']['name']));

      mail_attachment("$from", "youremailaddress@gmail.com", 
      "subject", "message", ("temp/".$_FILES["filea"]["name"]));
   }
?>
<html>
<head>
   <script language = "javascript" type = "text/javascript">
      function CheckData45() {
         with(document.filepost) {
            if(filea.value ! = "") {
               document.getElementById('one').innerText = "Attaching File ... Please Wait";
            }
         }
      }
   </script>
</head>
<body>
   <table width = "100%" height = "100%" border = "0" 
      cellpadding = "0" cellspacing = "0">
      <tr>
         <td align = "center">
            <form name = "filepost" method = "post" 
               action = "file.php" enctype = "multipart/form-data" id = "file">
               <table width = "300" border = "0" cellspacing = "0" 
                  cellpadding = "0">
                  <tr valign = "bottom">
                     <td height = "20">Your Name:</td>
                  </tr>
                  <tr>
                     <td><input name = "from" type = "text" id = "from" size = "30"></td>
                  </tr>
                  <tr valign = "bottom">
                     <td height = "20">Your Email Address:</td>
                  </tr>
                  <tr>
                     <td class = "frmtxt2"><input name = "emaila" type = "text" id = "emaila" size = "30"></td>
                  </tr>
                  <tr>
                     <td height = "20" valign = "bottom">Attach File:</td>
                  </tr>
                  <tr valign = "bottom">
                     <td valign = "bottom"><input name = "filea" type = "file" id = "filea" size = "16"></td>
                  </tr>
                  <tr>
                     <td height = "40" valign = "middle">
                        <input name = "Reset2" type = "reset" id = "Reset2" value = "Reset">
                        <input name = "Submit2" type = "submit" value = "Submit" onClick = "return CheckData45()">
                     </td>
                  </tr>
               </table>
            </form>
            <center>
               <table width = "400">
                  <tr>
                     <td id = "one"></td>
                  </tr>
               </table>
            </center>
         </td>
      </tr>
   </table>
</body>
</html>

它將產生以下輸出

PHP Sending Emails

PHP 輸入過濾

在 PHP 中,務必確保透過刪除任何不需要的字元來正確清理輸入資料,然後再由伺服器端程式碼處理。通常,使用者透過 HTML 表單將其資料輸入到 PHP Web 應用程式中。如果表單資料包含任何不需要的字元,則可能會造成危害,因此必須執行適當的清理操作。

可以使用 PHP 中的一個或多個以下函式進行輸入清理。

htmlspecialchars() 函式

此函式將特殊字元轉換為 HTML 實體。

htmlspecialchars(
   string $string,
   int $flags = ENT_QUOTES | ENT_SUBSTITUTE | ENT_HTML401,
   ?string $encoding = null,
   bool $double_encode = true
): string

在 HTML 中,某些字元具有特殊的意義。此 htmlspecialchars() 函式用於將特殊字元編碼為 HTML 實體。當您想將使用者輸入顯示為 HTML 並想防止指令碼注入攻擊時,這非常有用。

以下 **特殊字元** 將按如下所示轉換:

字元 替換為
& (與號) &amp;
" (雙引號) &quot;,除非設定了 **ENT_NOQUOTES**
' (單引號) &#039; (對於 **ENT_HTML401**) 或 &apos; (對於 **ENT_XML1、ENT_XHTML** 或 **ENT_HTML5**), 但僅當設定了 **ENT_QUOTES** 時。
< (小於號) &lt;
> (大於號) &gt;

標誌常量

**flags** 引數是一個或多個以下標誌的位掩碼,這些標誌指定如何處理引號、無效程式碼單元序列和使用的文件型別。

序號 常量 & 說明
1

ENT_COMPAT

將轉換雙引號,而保留單引號。

2

ENT_QUOTES

將轉換雙引號和單引號。

3

ENT_NOQUOTES

將保留雙引號和單引號。

4

ENT_IGNORE

丟棄無效的程式碼單元序列,而不是返回空字串。

5

ENT_SUBSTITUTE

將無效的程式碼單元序列替換為 Unicode 替換字元 U+FFFD (UTF-8) 或 &#xFFFD;。

6

ENT_DISALLOWED

將給定文件型別中無效的程式碼點替換為 Unicode 替換字元 U+FFFD (UTF-8) 或 &#xFFFD; (否則),而不是保留它們。這可能很有用。

7

ENT_HTML401

將程式碼處理為 HTML 4.01。

8

ENT_XML1

將程式碼處理為 XML 1。

9

ENT_XHTML

將程式碼處理為 XHTML。

10

ENT_HTML5

將程式碼處理為 HTML 5。

示例

請看以下示例:

<?php
   $str = 'Welcome To "PHP Tutorial" by <b>TutorialsPoint</b>';
   echo htmlspecialchars($str);
?>

它將產生以下輸出

Welcome To "PHP Tutorial" by <b>TutorialsPoint</b>

strip_tags() 函式

strip_tags() 函式從給定的字串中刪除所有 HTML 和 PHP 標籤。

strip_tags(string $string, array|string|null $allowed_tags = null): string

當您想確保使用者輸入不包含任何潛在的惡意標籤時,此函式非常有用。

**allowed_tags** 引數是一個可選的第二個引數,用於指定不應去除的標籤。這些標籤可以作為字串或陣列給出。

示例

請看以下示例:

<?php
   $text = '<p>Hello World</p><!-- Comment --> 
      <a href="/test.html">Click Here</a>';
   echo strip_tags($text);
   echo "\n";

   // Allow <p> and <a>
   echo strip_tags($text, '<p><a>');
?>

它將產生以下輸出

Hello World 
      Click Here
Hello World

 
      Click Here

addslashes() 函式

addslashes() 函式在字串中新增反斜槓。

addslashes(string $string): string

該函式返回一個字串,其中在需要轉義的字元前添加了反斜槓。這些字元是:

  • 單引號 (')

  • 雙引號 (")

  • 反斜槓 (\)

  • NUL (空位元組)

當您將使用者輸入儲存在資料庫中並想防止 SQL 注入攻擊時,請使用此函式。

示例

請看以下示例:

<?php
   $text = "Newton's Laws";
   $str = addslashes($text);  

   // prints the escaped string 
   echo($str);  
?>

它將產生以下輸出

Newton\'s Laws

filter_var() 函式

藉助特定的過濾器標誌,您可以使用 filter_var() 函式來清理使用者輸入。

filter_var(mixed $value, int $filter = 
   FILTER_DEFAULT, array|int $options = 0): mixed

$value 引數是一個需要清理其值的變數。$filter 引數是任何預定義的過濾器常量。

序號 ID & 描述
1

FILTER_SANITIZE_EMAIL

刪除除字母、數字和 !#$%&'*+-=?^_`{|}~@.[]. 之外的所有字元。

2

FILTER_SANITIZE_ENCODED

URL 編碼字串,可以選擇性地去除或編碼特殊字元。

3

FILTER_SANITIZE_ADD_SLASHES

應用 addslashes()。(從 PHP 7.3.0 開始可用)。

4

FILTER_SANITIZE_NUMBER_FLOAT

刪除除數字、+- 和可選的 .,eE 之外的所有字元。

5

FILTER_SANITIZE_NUMBER_INT

刪除除數字、加號和減號之外的所有字元。

6

FILTER_SANITIZE_SPECIAL_CHARS

HTML 編碼 '"<>& 和 ASCII 值小於 32 的字元,可以選擇性地去除或編碼其他特殊字元。
特殊字元。

7

FILTER_SANITIZE_FULL_SPECIAL_CHARS

等同於呼叫帶有設定 **ENT_QUOTES** 的 htmlspecialchars()。可以透過設定 **FILTER_FLAG_NO_ENCODE_QUOTES** 來停用編碼引號。

8

FILTER_SANITIZE_URL

刪除除字母、數字和 $-_.+!*'(),{}|\\^~[]`<>#%";/?:@&=.

9

FILTER_UNSAFE_RAW

示例

以下程式碼顯示如何清理電子郵件資料:

<?php
   $a = 'abc def@xyz.com';

   $sa = filter_var($a, FILTER_SANITIZE_EMAIL);
   echo "$sa";
?>

它將產生以下輸出

abcdef@xyz.com

示例

以下程式碼顯示如何清理 URL:

<?php
   $a = "http://example.c o m";

   $sa = filter_var($a, FILTER_SANITIZE_URL);
   echo "$sa";
?>

它將產生以下輸出

http://example.com

PHP POST-Redirect-GET (PRG)

在 PHP 中,PRG 代表“Post/Redirect/Get”。這是一種常用的技術,旨在防止在提交表單後重新提交表單。您可以輕鬆地在 PHP 中實現此技術以避免重複提交表單。

通常,HTML 表單使用 POST 方法將資料傳送到伺服器。伺服器指令碼獲取資料以進行進一步處理,例如在後端資料庫中新增新記錄或執行查詢以獲取資料。如果使用者意外重新整理瀏覽器,則可能再次提交相同的表單資料,這可能會導致資料完整性丟失。PHP 中的 PRG 方法可幫助您避免此陷阱。

示例

首先,讓我們考慮以下 PHP 指令碼,該指令碼呈現一個簡單的 HTML 表單,並使用 POST 方法將其提交回自身。當用戶填寫資料並提交時,後端指令碼獲取資料、呈現結果並返回再次顯示空白表單。

<?php
   if (isset($_POST["submit"])) {
      if ($_SERVER["REQUEST_METHOD"] == "POST")
         echo "First name: " . $_REQUEST['first_name'] . " " . "Last Name: " . $_REQUEST['last_name'] . "";
   }
?>

<html>
<body>
   <form action="<?php echo $_SERVER['PHP_SELF'];?>" method="post">
      First Name: <input type="text" name="first_name">  <br/>
      Last Name: <input type="text" name="last_name" />
      <button type="submit" name="submit">Submit</button>
   </form>
</body>
</html>

假設伺服器正在執行,上述指令碼位於文件根資料夾中,並在瀏覽器中訪問。

填寫資料並提交。瀏覽器會回顯結果,並重新渲染表單。現在,如果您嘗試重新整理瀏覽器頁面,則會彈出如下所示的警告:

PHP PRG 1

如果您按下 **繼續**,則會再次釋出相同的資料。

可以使用下圖理解該問題:

PHP PRG 2

PHP 指令碼中採取以下步驟來避免此問題:

  • HTML 表單之前的 PHP 指令碼啟動一個新會話。

  • 檢查表單是否已使用 POST 方法提交。

  • 如果是,則將表單資料儲存在會話變數中

  • 將瀏覽器重定向到結果頁面。在我們的例子中,它是同一頁面。使用 exit 命令終止此指令碼,以確保不再執行任何程式碼。

  • 如果 PHP 發現 REQUEST 方法不是 POST,則檢查是否設定了會話變數。如果是,則將它們與表單的新副本一起呈現。

  • 現在,即使重新整理表單,您也已成功避免了重新提交的可能性。

示例

以下是使用 PRG 技術的 PHP 程式碼:

<?php
   session_start();
   if (isset($_POST["submit"])) {
      $_SESSION['fname'] = $_POST['first_name'];
      $_SESSION['lname'] = $_POST['last_name']; 
      header("Location: hello.php");
      exit;
   }
   if (isset($_SESSION["fname"])) {
      echo "First name: " . $_SESSION['fname'] . " " . "Last Name: " . $_SESSION['lname'] . "";
      unset($_SESSION["fname"]); unset($_SESSION["lname"]);
   }
?>

<html>
<body>
   <form action="<?php echo $_SERVER['PHP_SELF'];?>" method="post">
      First Name: <input type="text" name="first_name">  <br />
      Last Name: <input type="text" name="last_name" />
      <button type="submit" name="submit">Submit</button>
   </form>
</body>
</html>

PHP 快閃記憶體訊息

在 PHP Web 應用程式中,**訊息閃現** 指的是使某些訊息在瀏覽器視窗中彈出以供使用者接收應用程式反饋的技術。能夠為使用者的互動提供有意義的反饋是一個重要的設計原則,它提供了更好的使用者體驗。

在 PHP Web 應用程式中,我們可以使用會話資料來不時地閃現有關某個操作成功或失敗、通知或警告等的訊息,以使使用者瞭解情況。

**閃現訊息** 允許您在一個頁面上建立訊息,並在另一個頁面上顯示一次。要將訊息從一個頁面傳輸到另一個頁面,您可以使用 **$_SESSION** 超全域性變數。

首先,您可以按照如下所示向 $_SESSION 陣列新增變數:

<?php
   session_start();
   $_SESSION['flash_message'] = "Hello World";
?>

稍後,導航到另一個頁面,並從 $_SESSION 變數中檢索閃現的訊息並將其分配給變數。然後,您可以顯示訊息,然後從 $_SESSION 中刪除訊息:

<?php
   session_start();
   if(isset($_SESSION['flash_message'])) {
      $message = $_SESSION['flash_message'];
      unset($_SESSION['flash_message']);
      echo $message;
   }
?>

為了概括處理閃現訊息的基本思想,我們將編寫一個將訊息新增到 $_SESSION 的函式:

session_start();
function create_flash_message(string $name, string $message): void {

   // remove existing message with the name
   if (isset($_SESSION[FLASH][$name])) {
      unset($_SESSION[FLASH][$name]);
   }
   // add the message to the session
   $_SESSION[FLASH][$name] = ['message' => $message]; 
}

讓我們再編寫另一個函式來讀取訊息,將其閃現在瀏覽器上,並將其從 $_SESSION 中刪除。

function display_flash_message(string $name): void {
   if (!isset($_SESSION[FLASH][$name])) {
      return;
   }

   // get message from the session
   $flash_message = $_SESSION[FLASH][$name];

   // delete the flash message
   unset($_SESSION[FLASH][$name]);

   // display the flash message
   echo format_flash_message($flash_message);
}

**format_flash_message()** 函式使用適當的 CSS 規則對獲得的字串應用所需的格式。

如果應用程式閃現了多條訊息,則可以使用以下示例檢索和閃現所有訊息:

function display_all_flash_messages(): void {
   if (!isset($_SESSION[FLASH])) {
      return;
   }

   // get flash messages
   $flash_messages = $_SESSION[FLASH];

   // remove all the flash messages
   unset($_SESSION[FLASH]);

   // show all flash messages
   foreach ($flash_messages as $flash_message) {
      echo format_flash_message($flash_message);
   }
}

使用以下 **flash() 函式** 來建立、格式化和閃現訊息

function flash(string $name = '', string $message = ''): void {
   if ($name !== '' && $message !== '') {
      create_flash_message($name, $message);
   } 
   elseif ($name !== '' && $message === '') {
      display_flash_message($name);		// display a flash message
   } elseif ($name === '' && $message === '' ) {
      display_all_flash_messages(); 	// display all flash message
   }
}

要實現上述方法,請在第一頁上呼叫 **flash() 函式**。

flash('first', 'Hello World');

導航到另一個頁面並呼叫 flash() 函式來檢索和顯示訊息:

flash('first');

使用閃現訊息的機制通常用於註冊頁面,以便在使用者註冊後將使用者重定向到登入頁面並顯示歡迎訊息。

PHP AJAX 簡介

PHP 驅動的 Web 應用程式經常使用 AJAX,它們一起用於建立動態和互動式 Web 應用程式。AJAX 代表 **非同步 JavaScript 和 XML**。它允許網頁非同步更新,無需重新載入整個頁面。

在 AJAX 應用程式中,Web 瀏覽器和伺服器端 PHP 指令碼之間的資料交換是非同步的。PHP 是一種伺服器端指令碼語言,可用於生成動態內容和處理資料。

由於 AJAX 在 Web 應用程式和 Web 伺服器之間建立了一個稱為 AJAX 引擎的附加層,因此我們可以使用 JavaScript 進行後臺伺服器呼叫並檢索所需的資料,可以更新 Web 頁面的請求部分,而無需強制重新載入頁面。它減少了頁面重新整理時間,併為使用者提供了快速且響應迅速的體驗。

PHP AJAX Introduction

執行 AJAX 需要什麼?

AJAX 使用的技術已經在所有現代瀏覽器中實現。因此,客戶端不需要任何額外的模組來執行 AJAX 應用程式。AJAX 使用的技術是:

  • **JavaScript** - 它是 AJAX 的重要組成部分。它允許您建立客戶端功能。或者我們可以說它用於建立 AJAX 應用程式。

  • **XML** - 用於在 Web 伺服器和客戶端之間交換資料。

  • **XMLHttpRequest** - 用於在 Web 瀏覽器和 Web 伺服器之間執行非同步資料交換。

  • **HTML 和 CSS** - 用於為網頁文字提供標記和樣式。

  • **DOM** - 用於動態地互動和更改網頁佈局和內容。

要將 AJAX 與 PHP 一起使用,您需要在 JavaScript 中使用 XMLHttpRequest 物件向 PHP 伺服器傳送請求。然後,PHP 伺服器將處理請求並返回響應,通常以 JSON 或 XML 的形式。然後,JavaScript 程式碼可以解析響應並相應地更新網頁。

JavaScript 中的 XMLHttpRequest 物件是一個基於瀏覽器的 API,允許開發人員向伺服器發出 HTTP 請求而無需重新載入頁面。這是 AJAX 程式設計的基礎,它允許動態和互動式 Web 應用程式。

XMLHttpRequest 物件可用於:

  • 從伺服器檢索資料,例如 JSON、XML 或 HTML。

  • 向伺服器傳送資料,例如表單資料或檔案上傳。

  • 更新網頁而無需重新載入。

  • 建立聊天應用程式和其他互動式功能。

要使用 XMLHttpRequest 物件,首先需要建立一個新的例項。然後,可以使用 open() 方法指定 HTTP 方法和請求 URL。接下來,如果需要,可以設定任何請求頭。最後,可以使用 send() 方法傳送請求。

示例

這是一個使用 XMLHttpRequest 物件從伺服器檢索資料的簡單 JavaScript 程式碼示例:

// Create a new XMLHttpRequest object
var xhr = new XMLHttpRequest();

// Set the HTTP method and request URL
xhr.open("GET", "test.php");

// Send the request
xhr.send();

// Listen for the onload event to be fired
xhr.onload = function() {

   // Check the status code to ensure the request was successful
   if (xhr.status === 200) {
   
      // Get the response data.
      var users = JSON.parse(xhr.responseText);

      // Do something with the user data.
   } else {   
      // Handle the error
   }
};

伺服器上的 PHP 指令碼從 AJAX 請求中檢索資料併發送回響應。

// Get the request data.
$name = $_GET["name"];

// Create a response object.
$response = new stdClass();
$response->message = "Hello, $name!";

// Send the response back to the client.
header("Content-Type: application/json");
echo json_encode($response);

PHP AJAX 搜尋

AJAX 是非同步 JavaScript 和 XML 的縮寫。Ajax 用於構建快速且動態的網頁。下面的示例演示了使用 AJAX 函式與後端 PHP 指令碼互動,以便在網頁上提供搜尋欄位。

步驟 1

將以下指令碼儲存為“example.php”:

<html>
<head>
   <style>
      span {
         color: green;
      }
   </style>
   <script>
      function showHint(str) {
         if (str.length == 0) {
            document.getElementById("txtHint").innerHTML = "";
            return;
         } else {
            var xmlhttp = new XMLHttpRequest();
            xmlhttp.onreadystatechange = function() {
               if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
                  document.getElementById("txtHint").innerHTML = xmlhttp.responseText;
               }
            }
            xmlhttp.open("GET", "hello.php?q=" + str, true);
            xmlhttp.send();
         }
      }
   </script>
</head>
<body>
   <p><b>Search your favourite tutorials:</b></p>
   <form>
      <input type = "text" onkeyup = "showHint(this.value)">
   </form>
   <p>Entered Course name: <span id="txtHint"></span></p>
</body>
</html>

此程式碼本質上是一個 HTML 指令碼,它呈現一個帶有文字欄位的 HTML 表單。在其 `onkeyup` 事件中,將呼叫 showHint() JavaScript 函式。該函式向伺服器上的另一個 PHP 指令碼傳送 HTTP GET 請求。

步驟 2

將以下指令碼儲存為“php_ajax.php”:

<?php
   // Array with names
   $a[] = "Android";
   $a[] = "B programming language";
   $a[] = "C programming language";
   $a[] = "D programming language";
   $a[] = "euphoria";
   $a[] = "F#";
   $a[] = "GWT";
   $a[] = "HTML5";
   $a[] = "ibatis";
   $a[] = "Java";
   $a[] = "K programming language";
   $a[] = "Lisp";
   $a[] = "Microsoft technologies";
   $a[] = "Networking";
   $a[] = "Open Source";
   $a[] = "Prototype";
   $a[] = "QC";
   $a[] = "Restful web services";
   $a[] = "Scrum";
   $a[] = "Testing";
   $a[] = "UML";
   $a[] = "VB Script";
   $a[] = "Web Technologies";
   $a[] = "Xerox Technology";
   $a[] = "YQL";
   $a[] = "ZOPL";

   $q = $_REQUEST["q"];
   $hint = "";

   if ($q !== "") {
      $q = strtolower($q);
      $len = strlen($q);

      foreach($a as $name) {
         if (stristr($q, substr($name, 0, $len))) {
            if ($hint === "") {
               $hint = $name;
            } else {
               $hint .= ", $name";
            }
         }
      }
   }
   echo $hint === "" ? "Please enter a valid course name" : $hint;
?>

步驟 3

我們將透過在瀏覽器中輸入 URL `https:///example.php` 來開啟 example.php 來啟動此應用程式。

在搜尋欄位中的每次按鍵操作中,都會向伺服器傳送一個 GET 請求。伺服器指令碼從 $_REQUEST 陣列中讀取字元,並搜尋匹配的課程名稱。匹配的值將顯示在瀏覽器中的文字欄位下方。

PHP AJAX Search

PHP AJAX XML 解析器

使用 PHP 和 AJAX,我們可以解析本地目錄以及伺服器上的 XML 文件。以下示例演示如何使用 Web 瀏覽器解析 XML。

客戶端指令碼呈現一個 HTML 表單,並定義一個 JavaScript 函式,用於使用 XMLHttpRequest 物件向伺服器傳送 HTTP 請求。

在伺服器端,PHP 指令碼從所需的 XML 文件載入 DOM 物件,從 $_REQUEST 變數中獲取選定的課程,並將所選課程的詳細資訊作為響應呈現回客戶端。

步驟 1

以下 XML 文件儲存在 XAMPP 伺服器的文件根目錄中。

<?xml version = "1.0" encoding = "utf-8"?>
<CATALOG>

   <SUBJECT>
      <COURSE>Android</COURSE>
      <COUNTRY>India</COUNTRY>
      <COMPANY>TutorialsPoint</COMPANY>
      <PRICE>$10</PRICE>
      <YEAR>2015</YEAR>
   </SUBJECT>

   <SUBJECT>
      <COURSE>Html</COURSE>
      <COUNTRY>India</COUNTRY>
      <COMPANY>TutorialsPoint</COMPANY>
      <PRICE>$15</PRICE>
      <YEAR>2015</YEAR>
   </SUBJECT>

   <SUBJECT>
      <COURSE>Java</COURSE>
      <COUNTRY>India</COUNTRY>
      <COMPANY>TutorialsPoint</COMPANY>
      <PRICE>$20</PRICE>
      <YEAR>2015</YEAR>
   </SUBJECT>

   <SUBJECT>
      <COURSE>Microsoft</COURSE>
      <COUNTRY>India</COUNTRY>
      <COMPANY>TutorialsPoint</COMPANY>
      <PRICE>$25</PRICE>
      <YEAR>2015</YEAR>
   </SUBJECT>
   
</CATALOG>

步驟 2

下面的 AJAX 程式碼包含一個 HTML 表單和一個 JavaScript 函式,用於透過 XMLHttpRequest 物件發出 HTTP 請求。

<html>
<head>
   <script>
      function showCD(str) {
         if (str == "") {
            document.getElementById("txtHint").innerHTML = "";
            return;
         }

         if (window.XMLHttpRequest) {
		 
            // code for IE7+, Firefox, Chrome, Opera, Safari
            xmlhttp = new XMLHttpRequest();
         } else {  
		 
            // code for IE6, IE5
            xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
         }

         xmlhttp.onreadystatechange = function() {
            if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
               document.getElementById("txtHint").innerHTML = xmlhttp.responseText;
            }
         }
         xmlhttp.open("GET","hello.php?q="+str,true);
         xmlhttp.send();
      }
   </script>
</head>
<body>
   <form>
      Select a Course:
      <select name = "cds" onchange = "showCD(this.value)">
         <option value = "">Select a course:</option>
         <option value = "Android">Android </option>
         <option value = "Html">HTML</option>
         <option value = "Java">Java</option>
         <option value = "Microsoft">MS technologies</option>
      </select>
   </form>
   <div id = "txtHint"><b>Course info will be listed here...</b></div>
</body>
</html>

步驟 3

伺服器端用於在 XML 文件中搜索的 PHP 指令碼如下:

<?php
   $q = $_GET["q"];

   $xmlDoc = new DOMDocument();
   $xmlDoc->load("test.xml");

   $x = $xmlDoc->getElementsByTagName('COURSE');

   for ($i = 0; $i<=$x->length-1; $i++) {
      if ($x->item($i)->nodeType == 1) {
         if ($x->item($i)->childNodes->item(0)->nodeValue == $q) {
            $y = ($x->item($i)->parentNode);
         }
      }
   }

   $cd = ($y->childNodes);

   for ($i = 0;$i<$cd->length;$i++) {
      if ($cd->item($i)->nodeType == 1) {
         echo("<b>" . $cd->item($i)->nodeName . ":</b> ");
         echo($cd->item($i)->childNodes->item(0)->nodeValue);
         echo("<br>");
      }
   }
?>

訪問“https:///example.php”以允許使用者選擇課程。選擇後,相關詳細資訊將從伺服器提取並顯示如下:

PHP AJAX XML Parser

PHP AJAX 自動完成搜尋

自動完成功能是一種鍵入提示機制,用於在使用者在提供的搜尋框中輸入資料時顯示輸入建議。它也稱為即時搜尋,因為它會對使用者的輸入做出反應。在這個例子中,我們將使用 AJAX 和 PHP 中的 XML 解析器來演示自動完成文字框的使用。

此應用程式具有三個主要組成部分:

  • XML 文件

  • JavaScript 程式碼

  • PHP 中的 XML 解析器

現在讓我們詳細討論這三個組成部分:

XML 文件

將以下 XML 指令碼儲存為“`autocomplete.xml`”到文件根資料夾

<?xml version = "1.0" encoding = "utf-8"?>
<pages>

   <link>
      <title>android</title>
      <url>https://tutorialspoint.tw/android/index.htm</url>
   </link>

   <link>
      <title>Java</title>
      <url>https://tutorialspoint.tw/java/index.htm</url>
   </link>

   <link>
      <title>CSS </title>
      <url>https://tutorialspoint.tw/css/index.htm</url>
   </link>

   <link>
      <title>angularjs</title>
      <url>https://tutorialspoint.tw/angularjs/index.htm </url>
   </link>

   <link>
      <title>hadoop</title>
      <url>https://tutorialspoint.tw/hadoop/index.htm </url>
   </link>

   <link>
      <title>swift</title>
      <url>https://tutorialspoint.tw/swift/index.htm </url>
   </link>

   <link>
      <title>ruby</title>
      <url>https://tutorialspoint.tw/ruby/index.htm </url>
   </link>

   <link>
      <title>nodejs</title>
      <url>https://tutorialspoint.tw/nodejs/index.htm </url>
   </link>
   
</pages>

JavaScript 程式碼

以下指令碼呈現一個文字欄位,供使用者輸入他選擇的課程名稱。每次按鍵操作都會呼叫一個 JavaScript 函式,並將輸入值透過 GET 方法傳遞給伺服器端的 PHP 指令碼。伺服器的響應將非同步呈現。

將此程式碼儲存為“`index.php`”。

<html>
<head>
   <script>
      function showResult(str) {
         if (str.length == 0) {
            document.getElementById("livesearch").innerHTML = "";
            document.getElementById("livesearch").style.border = "0px";
            return;
         }

         if (window.XMLHttpRequest) {
            xmlhttp = new XMLHttpRequest();
         } else {
            xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
         }

         xmlhttp.onreadystatechange = function() {
            if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
               document.getElementById("livesearch").innerHTML = xmlhttp.responseText;
               document.getElementById("livesearch").style.border = "1px solid #A5ACB2";
            }
         }

         xmlhttp.open("GET","livesearch.php?q="+str,true);
         xmlhttp.send();
      }
   </script>
</head>
<body>
   <form>
      <h2>Enter Course Name</h2>
      <input type = "text" size = "30" onkeyup = "showResult(this.value)">
      <div id = "livesearch"></div>
      <a href = "https://tutorialspoint.tw">More Details</a>
   </form>
</body>
</html>

PHP 中的 XML 解析器

這是伺服器上的 PHP 指令碼。它解析給定的 XML 源文件,讀取輸入欄位中輸入的字元,在解析的 XNL 物件中搜索它,然後傳送迴響應。

將以下程式碼儲存為“livesearch.php”。

<?php
   $xml_doc = new DOMDocument();
   $xml_doc->load('autocomplete.xml');

   $x=$xml_doc->getElementsByTagName('link');

   $q = $_GET['q'];
   $result = '';
   foreach($x as $node) {
      if (stripos("{$node->nodeValue}", $q) !== false) {
         $result .= "{$node->nodeValue}";
      }
   }

   // Set $response to "No records found." in case no hint was found
   // or the values of the matching values
   if ($result == '')
      $result = 'No records found.';

   // show the results or "No records found."
   echo $result;
?>

在 XAMPP 伺服器執行的情況下,訪問“https:///index.php”,瀏覽器將顯示一個輸入文字欄位。對於其中鍵入的每個字元,相關的建議都會顯示在其下方。

PHP AJAX Auto Search

PHP AJAX RSS Feed 示例

Really Simple Syndication (RSS)

RSS(代表 Really Simple Syndication)用於釋出網站上經常更新的資訊,例如音訊、影片、影像等。我們可以使用 AJAX 和 PHP 將 RSS 提要整合到網站中。此程式碼演示如何在我們的網站上顯示 RSS 提要。

Index.html

索引頁面應如下所示:

<html>
<head>
   <script>
      function showRSS(str) {
         if (str.length == 0) { 
            document.getElementById("output").innerHTML = "";
            return;
         }

         if (window.XMLHttpRequest) {
            xmlhttp = new XMLHttpRequest();
         } else {
            xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
         }
         xmlhttp.onreadystatechange = function() {
            if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
               document.getElementById("output").innerHTML = xmlhttp.responseText;
            }
         }

         xmlhttp.open("GET","rss.php?q="+str,true);
         xmlhttp.send();
      }
   </script>
</head>
<body>
   <p>Please Select an option to get RSS:</p>
   <form>
      <select onchange = "showRSS(this.value)">
         <option value = "">Select an RSS-feed:</option>
         <option value = "cnn">CNN</option>
         <option value = "bbc">BBC News</option>
         <option value = "pc">PC World</option>
      </select>
   </form>
   <br>
   <div id = "output">RSS-feeds</div>
</body>
</html>

rss.php

“rss.php”包含有關如何訪問`RSS 提要`RSS 提要並將 RSS 提要返回到網頁的語法。

<?php
   $q = $_GET["q"];

   if($q == "cnn") {
      $xml = ("http://rss.cnn.com/rss/cnn_topstories.rss");
   } elseif($q == "bbc") {
      $xml = ("http://newsrss.bbc.co.uk/rss/newsonline_world_edition/americas/rss.xml");
   } elseif($q = "pcw"){
      $xml = ("http://www.pcworld.com/index.rss");
   }

   $xmlDoc = new DOMDocument();
   $xmlDoc->load($xml);

   $channel = $xmlDoc->getElementsByTagName('channel')->item(0);

   $channel_title = $channel->getElementsByTagName('title')
   ->item(0)->childNodes->item(0)->nodeValue;

   $channel_link = $channel->getElementsByTagName('link')
   ->item(0)->childNodes->item(0)->nodeValue;

   $channel_desc = $channel->getElementsByTagName('description')
   ->item(0)->childNodes->item(0)->nodeValue;

   echo("<p><a href = '" . $channel_link . "'>" . 
      $channel_title . "</a>");
   echo("<br>");
   echo($channel_desc . "</p>");

   $x = $xmlDoc->getElementsByTagName('item');

   for ($i = 0; $i<=2; $i++) {
      $item_title = $x->item($i)->getElementsByTagName('title')
      ->item(0)->childNodes->item(0)->nodeValue;

      $item_link = $x->item($i)->getElementsByTagName('link')
      ->item(0)->childNodes->item(0)->nodeValue;

      $item_desc = $x->item($i)->getElementsByTagName('description')
      ->item(0)->childNodes->item(0)->nodeValue;

      echo ("<p><a href = '" . $item_link . "'>" . $item_title . "</a>");
      echo ("<br>");
      echo ($item_desc . "</p>");
   }
?>

它將產生以下輸出:

PHP RSS Feed Example

PHP XML 簡介

藉助 PHP 的內建函式和庫,我們可以處理 XML 資料的操作。XML(代表可擴充套件標記語言)是一種用於結構化文件交換的資料格式,尤其是在 Web 上。

XML 是一種流行的檔案格式,用於序列化資料,儲存資料,將其傳輸到另一個位置,並在目標位置重建它。

在本章中,我們將學習使用 PHP 進行 XML 處理的基礎知識。

XML 的特性

XML 的一個特性是它既可以被人閱讀也可以被機器閱讀。XML 的規範由全球資訊網聯盟定義和標準化。PHP 解析器可以對 XML 資料執行讀/寫操作。

XML 標籤

與 HTML 一樣,XML 文件也是藉助`標籤`組成的。但是,您可以定義自己的標籤,這與 HTML 不同,在 HTML 中您需要使用預定義標籤來組成 HTML 文件。

HTML 標籤主要對文字、影像、多媒體資源等應用格式化屬性。XML 標籤為資料元素定義使用者指定的屬性。

XML 文件

XML 文件具有標籤的分層結構,這些標籤定義文件內資料的元素和屬性。每個 XML 文件都包含一個根元素,該元素包含其他元素。元素可以具有屬性,這些屬性提供有關元素的附加資訊或屬性。元素中的資料包含在開始和結束標籤中。

示例

下面是一個典型 XML 文件的示例:

<?xml version = '1.0' encoding = 'UTF-8'?>   
<note>
   <Course>Android</Course>
   <Subject>Android</Subject>
   <Company>TutorialsPoint</Company>
   <Price>$10</Price>
</note>

XML 解析器的型別

在 PHP 中,有兩種型別的 XML 解析器可用:

  • 基於樹的解析器

  • 基於事件的解析器

基於樹的解析器

使用這種型別的解析器,PHP 會將整個 XML 文件載入到記憶體中,並將 XML 文件轉換為樹結構。它分析整個文件,並提供對樹元素的訪問。

`對於較小的文件,基於樹的解析器效果很好`,但對於大型 XML 文件,它會導致主要的效能問題。`SimpleXML 解析器`和`DOM XML 解析器`是基於樹的解析器的示例。

Simple XML 解析器

Simple XML 解析器也稱為基於樹的 XML 解析器,它將解析簡單的 XML 檔案。Simple XML 解析將呼叫 simplexml_load_file() 方法以訪問特定路徑中的 xml。

DOM 解析器

DOM 解析器也稱為複雜節點解析器,用於解析高度複雜的 XML 檔案。它用作修改 XML 檔案的介面。DOM 解析器使用 UTF-8 字元編碼進行編碼。

基於事件的解析器

基於事件的解析器不會將整個 XML 文件載入到記憶體中。相反,它一次讀取一個節點。解析器允許您即時互動。一旦您移動到下一個節點,舊節點將從記憶體中刪除。

由於不涉及記憶體超載,這種型別的解析器適用於大型 XML 文件,並且文件的解析速度比任何基於樹的解析器都快。XMLReader 和 XML Expat 解析器是基於事件的解析器的示例。

XML 解析器

XML 解析基於 SAX 解析。它比所有上述解析器都快。它將建立 XML 檔案並解析 XML。XML 解析器使用 ISO-8859-1、US-ASCII 和 UTF-8 字元編碼進行編碼。

XML 閱讀器

XML 閱讀器解析也稱為拉取 XML 解析。它用於更快地讀取 XML 檔案。它適用於具有 XML 驗證的高度複雜的 XML 文件。

PHP 簡單XML解析器

PHP 的 SimpleXML 擴充套件提供了一個非常簡單易用的工具集,用於將 XML 轉換為可以使用普通屬性選擇器和陣列迭代器處理的物件。它是一個基於樹的解析器,適用於簡單的 XML 檔案,但在處理較大且複雜的 XML 文件時可能會遇到問題。

SimpleXML 擴充套件中定義了以下函式:

simplexml_load_file

simplexml_load_file() 函式將 XML 檔案解釋為一個物件:

simplexml_load_file(
   string $filename,
   ?string $class_name = SimpleXMLElement::class,
   int $options = 0,
   string $namespace_or_prefix = "",
   bool $is_prefix = false
): SimpleXMLElement|false

給定檔案中的格式良好的 XML 文件將轉換為物件。

filename 引數是表示要解析的 XML 檔案的字串。class_name 是可選引數。它指定函式將返回其物件的類。該函式返回一個 SimpleXMLElement 類的物件,其屬性包含 XML 文件中儲存的資料,或者在失敗時返回 `false`。

示例

請看以下示例:

<?php
   $xml = simplexml_load_file("test.xml") or die("Error: Cannot create object");
   print_r($xml);
?>

它將產生以下輸出

SimpleXMLElement Object
(
   [Course] => Android
   [Subject] => Android
   [Company] => TutorialsPoint
   [Price] => $10
)

simplexml_load_string

simplexml_load_string() 函式將 XML 檔案解釋為一個物件。

simplexml_load_string(
   string $filename,
   ?string $class_name = SimpleXMLElement::class,
   int $options = 0,
   string $namespace_or_prefix = "",
   bool $is_prefix = false
): SimpleXMLElement|false

給定字串中的格式良好的 XML 文件將轉換為物件。

$data 引數是表示要解析的 XML 文件的字串。class_name 是可選引數。它指定函式將返回其物件的類。該函式返回一個 SimpleXMLElement 類的物件,其屬性包含 XML 文件中儲存的資料,或者在失敗時返回 `false`。

示例

請看以下示例:

<?php
   $data = "<?xml version = '1.0' encoding = 'UTF-8'?>   
   <note>
      <Course>Android</Course>
      <Subject>Android</Subject>
      <Company>TutorialsPoint</Company>
      <Price>$10</Price>
   </note>";
   $xml = simplexml_load_string($data) or die("Error: Cannot create object");
   print_r($xml);
?>

它將產生以下輸出

SimpleXMLElement Object
(
   [Course] => Android
   [Subject] => Android
   [Company] => TutorialsPoint
   [Price] => $10
)

simplexml_import_dom

simplexml_import_dom() 函式從 DOM 節點構造一個 SimpleXMLElement 物件。

simplexml_import_dom(SimpleXMLElement|DOMNode $node, ?string 
   $class_name = SimpleXMLElement::class): ?SimpleXMLElement

此函式獲取 DOM 文件的節點並將其轉換為 SimpleXML 節點。然後,此新物件可以用作本機 SimpleXML 元素。

node 引數是 DOM 元素節點。可以提供可選的 class_name,以便 simplexml_import_dom() 將返回 SimpleXMLElement 類的指定子類的物件。此函式返回的值是 SimpleXMLElement 或失敗時的 null。

示例

請看以下示例:

<?php
   $dom = new DOMDocument;
   $dom->loadXML('<books><book><title>PHP Handbook</title></book></books>');
   if (!$dom) {
      echo 'Error while parsing the document';
      exit;
   }

   $s = simplexml_import_dom($dom);
   echo $s->book[0]->title;
?>

它將產生以下輸出

PHP Handbook

獲取節點值

以下程式碼顯示如何從 XML 檔案中獲取節點值,XML 應如下所示:

<?xml version = "1.0" encoding = "utf-8"?>
<tutorialspoint>
   <course category = "JAVA">
      <title lang = "en">Java</title>
      <tutor>Gopal</tutor>
      <duration></duration>
      <price>$30</price>
   </course>

   <course category = "HADOOP">
      <title lang = "en">Hadoop</title>.
      <tutor>Satish</tutor>
      <duration>3</duration>
      <price>$50</price>
   </course>

   <course category = "HTML">
      <title lang = "en">html</title>
      <tutor>raju</tutor>
      <duration>5</duration>
      <price>$50</price>
   </course>

   <course category = "WEB">
      <title lang = "en">Web Technologies</title>
      <tutor>Javed</tutor>
      <duration>10</duration>
      <price>$60</price>
   </course>
</tutorialspoint>

示例

PHP 程式碼應如下所示:

<?php
   $xml = simplexml_load_file("books.xml") or die("Error: Cannot create object");

   foreach($xml->children() as $books) { 
      echo $books->title . "<br> "; 
      echo $books->tutor . "<br> "; 
      echo $books->duration . "<br> ";
      echo $books->price . "<hr>"; 
   }
?>

它將產生以下輸出

Java
Gopal

$30
________________________________________
Hadoop
Satish
3
$50
________________________________________
html
raju
5
$50
________________________________________
Web Technologies
Javed
10
$60
________________________________________

PHP SAX 解析器示例

PHP 在 php.ini 設定檔案中預設啟用了 XML 解析器擴充套件。此解析器實現 SAX API,這是一種基於事件的解析演算法。

基於事件的解析器不會將整個 XML 文件載入到記憶體中。相反,它一次讀取一個節點。解析器允許您即時互動。一旦您移動到下一個節點,舊節點將從記憶體中刪除。

基於 SAX 的解析機制比基於樹的解析器更快。PHP 庫包含用於處理 XML 事件的函式,如本章所述。

解析 XML 文件的第一步是使用 xml_parse_create() 函式建立一個解析器物件。

xml_parser_create(?string $encoding = null): XMLParser

此函式建立一個新的 XML 解析器,並返回一個 XMLParser 物件,供其他 XML 函式使用。

xml_parse() 函式開始解析 XML 文件。

xml_parse(XMLParser $parser, string $data, bool $is_final = false): int

xml_parse() 解析 XML 文件。配置事件的處理程式將根據需要呼叫多次。

XMLParser 擴充套件提供不同的事件處理程式函式。

xml_set_element_handler()

此函式設定 XML 解析器的元素處理程式函式。每當 XML 解析器遇到開始或結束標籤時,都會發出元素事件。開始標籤和結束標籤有單獨的處理程式。

xml_set_element_handler(XMLParser $parser, callable $start_handler, 
   callable $end_handler): true

當開啟新的 XML 元素時,呼叫 start_handler() 函式。當關閉 XML 元素時,呼叫 end_handler() 函式。

xml_set_character_data_handler()

此函式設定 XML 解析器的字元資料處理程式函式。字元資料大致包含 XML 文件的所有非標記內容,包括標籤之間的空格。

xml_set_character_data_handler(XMLParser $parser, callable $handler): true

xml_set_processing_instruction_handler()

此函式設定 XML 解析器的處理指令 (PI) 處理程式函式。<?php ?> 是一個處理指令,其中 php 稱為“PI 目標”。這些的處理是特定於應用程式的。

xml_set_processing_instruction_handler(XMLParser $parser, callable $handler): true

一個處理指令具有以下格式:

<?target
   data
?>

xml_set_default_handler()

此函式設定 XML 解析器的預設處理程式函式。未傳遞給其他處理程式的內容將傳遞給預設處理程式。您將在預設處理程式中獲得諸如 XML 和文件型別宣告之類的內容。

xml_set_default_handler(XMLParser $parser, callable $handler): true

示例

以下示例演示了使用 SAX API 解析 XML 文件。我們將使用如下所示的 SAX.xml:

<?xml version = "1.0" encoding = "utf-8"?>
<tutors>
   <course>
      <name>Android</name>
      <country>India</country>
      <email>contact@tutorialspoint.com</email>
      <phone>123456789</phone>
   </course>

   <course>
      <name>Java</name>
      <country>India</country>
      <email>contact@tutorialspoint.com</email>
      <phone>123456789</phone>
   </course>

   <course>
      <name>HTML</name>
      <country>India</country>
      <email>contact@tutorialspoint.com</email>
      <phone>123456789</phone>
   </course>
</tutors>

示例

下面給出解析上述文件的 PHP 程式碼。它開啟 XML 檔案並呼叫 xml_parse() 函式,直到到達檔案末尾。事件處理程式將資料儲存在 tutors 陣列中。然後逐個元素地輸出該陣列。

<?php

   // Reading XML using the SAX(Simple API for XML) parser 
   $tutors   = array();
   $elements   = null;

   // Called to this function when tags are opened 
   function startElements($parser, $name, $attrs) {
      global $tutors, $elements;
      if(!empty($name)) {
         if ($name == 'COURSE') {
		 
            // creating an array to store information
            $tutors []= array();
         }
         $elements = $name;
      }
   }

   // Called to this function when tags are closed 
   function endElements($parser, $name) {
      global $elements;

      if(!empty($name)) {
         $elements = null;
      }
   }

   // Called on the text between the start and end of the tags
   function characterData($parser, $data) {
      global $tutors, $elements;
      if(!empty($data)) {
         if ($elements == 'NAME' || $elements == 'COUNTRY' ||  $elements == 'EMAIL' ||  $elements == 'PHONE') {
            $tutors[count($tutors)-1][$elements] = trim($data);
         }
      }
   }

   $parser = xml_parser_create();
   xml_set_element_handler($parser, "startElements", "endElements");
   xml_set_character_data_handler($parser, "characterData");

   // open xml file
   if (!($handle = fopen('sax.xml', "r"))) {
      die("could not open XML input");
   }

   while($data = fread($handle, 4096)) {
      xml_parse($parser, $data);  
   }

   xml_parser_free($parser); 
   $i = 1;

   foreach($tutors as $course) {
      echo "course No - ".$i. '<br/>';
      echo "course Name - ".$course['NAME'].'<br/>';
      echo "Country - ".$course['COUNTRY'].'<br/>';
      echo "Email - ".$course['EMAIL'].'<br/>';
      echo "Phone - ".$course['PHONE'].'<hr/>'; 
      $i++; 
   }
?>

上述程式碼輸出如下:

course No - 1
course Name - Android
Country - India
Email - contact@tutorialspoint.com
Phone - 123456789
________________________________________
course No - 2
course Name - Java
Country - India
Email - contact@tutorialspoint.com
Phone - 123456789
________________________________________
course No - 3
course Name - HTML
Country - India
Email - contact@tutorialspoint.com
Phone - 123456789
________________________________________

PHP DOM 解析器示例

PHP 中的 DOM 擴充套件具有廣泛的功能,我們可以使用這些功能對 XML 和 HTML 文件執行各種操作。我們可以動態構建 DOM 物件,從 HTML 檔案或包含 HTML 標籤樹的字串載入 DOM 文件。我們還可以將 DOM 文件儲存到 XML 檔案,或從 XML 文件中提取 DOM 樹。

DOMDocument 類是 DOM 擴充套件中定義的最重要的類之一。

$obj = new DOMDocument($version = "1.0", $encoding = "")

它表示整個 HTML 或 XML 文件;作為文件樹的根。DOMDocument 類包含許多靜態方法的定義,其中一些方法在此介紹:

序號 方法與說明
1

createElement

建立新的元素節點

2

createAttribute

建立新的屬性

3

createTextNode

建立新的文字節點

4

getElementById

搜尋具有特定 ID 的元素

5

getElementsByTagName

搜尋所有具有給定區域性標籤名稱的元素

6

load

從檔案載入 XML

7

loadHTML

從字串載入 HTML

8

loadHTMLFile

從檔案載入 HTML

9

loadXML

從字串載入 XML

10

save

將內部 XML 樹轉儲迴文件

11

saveHTML

使用 HTML 格式將內部文件轉儲到字串中

12

saveHTMLFile

使用 HTML 格式將內部文件轉儲到檔案中

13

saveXML

將內部 XML 樹轉儲回字符串中

示例

讓我們為此示例使用以下 HTML 檔案:

<html>
<head> 
   <title>Tutorialspoint</title>
</head> 
<body> 
   <h2>Course details</h2> 
   <table border = "0"> 
      <tbody> 
         <tr> 
            <td>Android</td> 
            <td>Gopal</td> 
            <td>Sairam</td> 
         </tr>
         <tr> 
            <td>Hadoop</td> 
            <td>Gopal</td> 
            <td>Satish</td> 
         </tr> 
         <tr> 
            <td>HTML</td> 
            <td>Gopal</td> 
            <td>Raju</td> 
         </tr> 
         <tr> 
            <td>Web technologies</td> 
            <td>Gopal</td> 
            <td>Javed</td> 
         </tr> 
         <tr> 
            <td>Graphic</td> 
            <td>Gopal</td> 
            <td>Satish</td> 
         </tr> 
         <tr> 
            <td>Writer</td> 
            <td>Kiran</td> 
            <td>Amith</td> 
         </tr> 
         <tr> 
            <td>Writer</td> 
            <td>Kiran</td> 
            <td>Vineeth</td> 
         </tr> 
      </tbody> 
   </table> 
</body> 
</html>

我們現在將透過在以下 PHP 程式碼中呼叫 loadHTMLFile() 方法來從上述 HTML 檔案中提取文件物件模型:

<?php 

   /*** a new dom object ***/ 
   $dom = new domDocument; 

   /*** load the html into the object ***/ 
   $dom->loadHTMLFile("hello.html");

   /*** discard white space ***/ 
   $dom->preserveWhiteSpace = false; 

   /*** the table by its tag name ***/ 
   $tables = $dom->getElementsByTagName('table'); 

   /*** get all rows from the table ***/ 
   $rows = $tables[0]->getElementsByTagName('tr'); 

   /*** loop over the table rows ***/ 
   foreach ($rows as $row) {
   
      /*** get each column by tag name ***/ 
      $cols = $row->getElementsByTagName('td'); 

      /*** echo the values ***/ 
      echo 'Designation: '.$cols->item(0)->nodeValue.'<br />'; 
      echo 'Manager: '.$cols->item(1)->nodeValue.'<br />'; 
      echo 'Team: '.$cols->item(2)->nodeValue; 
      echo '<hr />'; 
   }
   
?>

它將產生以下輸出

Designation: Android
Manager: Gopal
Team: Sairam
________________________________________
Designation: Hadoop
Manager: Gopal
Team: Satish
________________________________________
Designation: HTML
Manager: Gopal
Team: Raju
________________________________________
Designation: Web technologies
Manager: Gopal
Team: Javed
________________________________________
Designation: Graphic
Manager: Gopal
Team: Satish
________________________________________
Designation: Writer
Manager: Kiran
Team: Amith
________________________________________
Designation: Writer
Manager: Kiran
Team: Vineeth
________________________________________

PHP 登入示例

典型的 PHP Web 應用程式會在登入前對使用者進行身份驗證,方法是詢問其憑據,例如使用者名稱密碼。然後將憑據與伺服器上可用的使用者資料進行檢查。在此示例中,使用者資料以關聯陣列的形式提供。下面解釋以下 PHP 登入指令碼:

HTML 表單

程式碼的 HTML 部分呈現一個簡單的 HTML 表單,該表單接受使用者名稱和密碼,並將資料釋出給自己。

<form action = "<?php echo htmlspecialchars($_SERVER['PHP_SELF']); ?>" method="post">
   <div>
      <label for="username">Username:</label>
      <input type="text" name="username" id="name">
   </div>
   <div>
      <label for="password">Password:</label>
      <input type="password" name="password" id="password">
   </div>
   <section style="margin-left:2rem;">
      <button type="submit" name="login">Login</button>
   </section>
</form>

PHP 身份驗證

PHP 指令碼解析 POST 資料,並檢查 users 陣列中是否存在使用者名稱。如果找到,它將進一步檢查密碼是否與陣列中註冊的使用者相對應。

<?php
   if (array_key_exists($user, $users)) {
      if ($users[$_POST['username']]==$_POST['password']) {
         $_SESSION['valid'] = true;
         $_SESSION['timeout'] = time();
         $_SESSION['username'] = $_POST['username'];
         $msg = "You have entered correct username and password";
      } else { 
         $msg = "You have entered wrong Password"; 
      }
   } else {
      $msg = "You have entered wrong user name";
   }
?>

使用者名稱和相應的訊息將新增到 $_SESSION 陣列中。系統將提示使用者輸入正確的憑據或錯誤訊息。

完整程式碼

這是完整的程式碼:

Login.php

<?php
   ob_start();
   session_start();
?>
<html lang = "en">
<head>
   <meta charset="UTF-8">
   <meta name="viewport" content="width=device-width, initial-scale=1.0">
   <link rel="stylesheet" href="loginstyle.css">
   <title>Login</title>
</head>
<body>
   <h2 style="margin-left:10rem; margin-top:5rem;">Enter Username and Password</h2> 
   <?php
      $msg = '';
      $users = ['user'=>"test", "manager"=>"secret", "guest"=>"abc123"];

      if (isset($_POST['login']) && !empty($_POST['username']) 
      && !empty($_POST['password'])) {
         $user=$_POST['username'];                  
         if (array_key_exists($user, $users)){
            if ($users[$_POST['username']]==$_POST['password']){
               $_SESSION['valid'] = true;
               $_SESSION['timeout'] = time();
               $_SESSION['username'] = $_POST['username'];
               $msg = "You have entered correct username and password";
            }
            else {
               $msg = "You have entered wrong Password";
            }
         }
         else {
            $msg = "You have entered wrong user name";
         }
      }
   ?>

   <h4 style="margin-left:10rem; color:red;"><?php echo $msg; ?></h4>
   <br/><br/>
   <form action = "<?php echo htmlspecialchars($_SERVER['PHP_SELF']); ?>" method="post">
      <div>
         <label for="username">Username:</label>
         <input type="text" name="username" id="name">
      </div>
      <div>
         <label for="password">Password:</label>
         <input type="password" name="password" id="password">
      </div>
      <section style="margin-left:2rem;">
         <button type="submit" name="login">Login</button>
      </section>
   </form>

   <p style="margin-left: 2rem;"> 
      <a href = "logout.php" tite = "Logout">Click here to clean Session.</a>
   </p>
   </div> 
</body>
</html>

Logout.php

要登出,使用者單擊指向logout.php的連結。

<?php
   session_start();
   unset($_SESSION["username"]);
   unset($_SESSION["password"]);
   
   echo '<h4>You have cleaned session</h4>';
   header('Refresh: 2; URL = login.php');
?>

輸入“https:///login.php”啟動應用程式。以下是不同場景

正確的使用者名稱和密碼

PHP Login Example 1

密碼錯誤

PHP Login Example 2

使用者名稱錯誤

PHP Login Example 3

當用戶單擊底部的連結時,會話變數將被刪除,並且登入螢幕將重新出現。

PHP Facebook 登入

可以使用社交媒體登入(也稱為 SSO)要求使用者登入 Web 應用程式。這樣,使用者無需建立新帳戶。相反,使用者可以使用其現有的社交媒體帳戶資訊登入。社交媒體登入的一些示例包括:Google、Facebook、LinkedIn、Apple。

在本章中,我們將解釋如何使用 Facebook 憑據啟用登入 PHP 應用程式。

新增 Facebook 登入功能的第一步是建立一個 Facebook 應用程式。訪問https://developers.facebook.com/apps/creation/ 並使用您的 Facebook 帳戶登入。

PHP Facebook Login 1

接下來,輸入要建立的 Facebook 應用的名稱:

PHP Facebook Login 2

進入應用設定並獲取應用程式 ID 和金鑰:

PHP Facebook Login 3

選擇平臺為網站:

PHP Facebook Login 4

接下來,您需要在 PHP 中設定 Facebook SDK。從“https://packagist.org/packages/facebook/php-sdk”下載 PHP 版 Facebook SDK,或使用composer:composer require "facebook/graph-sdk-v5"。將 SDK 檔案解壓縮到您的 PHP 應用程式可以訪問的目錄中。

要在 PHP 程式碼中配置 Facebook SDK,請在您的 PHP 檔案中包含 Facebook SDK 自動載入器:require_once __DIR__ . '/vendor/autoload.php';

設定您的應用的訪問令牌和應用金鑰:

$app_id = 'YOUR_APP_ID';
$app_secret = 'YOUR_APP_SECRET';

接下來,建立 Facebook 登入按鈕。建立一個 HTML 按鈕,並新增 Facebook 登入 JavaScript SDK 來觸發登入流程:

<button id="facebook-login-button">Login with Facebook</button>

包含 Facebook JavaScript SDK:

<script src="https://#/en_US/sdk.js#xfbml=1&version=v13.0&appId=YOUR_APP_ID&autoLogApp=true" async defer></script>

建立一個 PHP 指令碼以處理 Facebook 登入回撥:

<?php
   session_start();

   $fb = new Facebook\Facebook([
      'app_id' => $app_id,
      'app_secret' => $app_secret,
      'default_graph_version' => 'v13.0',
   ]);

   $helper = $fb->getRedirectLoginHelper();
   $accessToken = $helper->getAccessToken();

   if ($accessToken) {
      // User is logged in, handle their data
      $user = $fb->get('/me', ['fields' => 'id,name,email']);
      $_SESSION['user_data'] = $user;
      header('Location: profile.php');
   } else {
      // User is not logged in, redirect to login page
      $loginUrl = $helper->getLoginUrl(['scope' => 'public_profile,email']);
      header('Location: ' . $loginUrl);
   }
?>

登入成功後,將使用者資料儲存在會話中,然後重定向到受保護的頁面。在受保護的頁面上,檢查會話中的使用者資料以驗證訪問許可權。

PHP Paypal 整合

PayPal 是一個支付處理系統。我們可以使用 PHP 將 PayPal 與網站整合。

PayPal 整合檔案系統

PayPal 整合檔案系統包含四個檔案,如下所示:

  • constants.php - 此檔案包含 API 使用者名稱、密碼和簽名。

  • CallerService.php - 此檔案包含用於呼叫 PayPal 服務的 PayPal 服務。

  • confirmation.php - 此檔案包含一個表單,其中包含進行支付流程所需的最小欄位,它將返回支付成功或失敗。

  • PayPal_entry.php - 此頁面用於將使用者資料傳送到 PayPal。它充當 PayPal 和使用者表單之間的介面卡。

使用者必須從此處下載 PayPal SDK 檔案並解壓縮 zip 檔案。zip 檔案包含四個 PHP 檔案。我們不需要更改任何檔案,除了“constants.php”。

constants.php

“constants.php”檔案包含如下所示的程式碼:

<?php
   define('API_USERNAME', 'YOUR USER NAME HERE');
   define('API_PASSWORD', 'YOUR PASSWORD HERE');
   define('API_SIGNATURE', 'YOUR API SIGNATURE HERE');
   define('API_ENDPOINT', 'https://api-3t.paypal.com/nvp');
   define('USE_PROXY',FALSE);
   define('PROXY_HOST', '127.0.0.1');
   define('PROXY_PORT', '808');
   define('PAYPAL_URL', 'https://www.PayPal.com/webscr&cmd=_express-checkout&token=');
   define('VERSION', '53.0');
?>

使用者將以上語法中宣告的使用者名稱、密碼和簽名放在“constants.php”中。

這是一個實驗性示例,因此最後的金額將新增到沙盒帳戶。

PHP MySQL 登入

MySQL 是 PHP 驅動的 Web 應用程式的後端資料庫的流行選擇。在本章中,我們將學習為 PHP 應用程式開發一個登入頁面,該頁面驗證給定的使用者名稱和密碼。

您應該有一個安裝了 PHP 和 MySQL 的 Web 伺服器,才能試驗本章中討論的示例。可以在您的作業系統上輕鬆安裝 Apache、PHP 和 MySQL (MariaDB) 的捆綁二進位制檔案(例如 XAMPP)。

在執行示例程式碼之前,您應該有一個名為 mydb 的 MySQL 資料庫,其中必須有一個名為 admin 的表。您可以使用以下 SQL 指令碼建立表並插入測試資料

use mydb;

CREATE TABLE `admin` (
   `username` varchar(10) NOT NULL,
   `passcode` varchar(10) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;

INSERT INTO `admin` (`username`, `passcode`) VALUES
('guest', 'abc123'),
('manager', 'secret'),
('user', 'test');

ALTER TABLE `admin`
   ADD PRIMARY KEY (`username`);
COMMIT;

PHP 登入應用程式的第一部分是建立資料庫連線物件。我們使用 myqli API 獲取連線物件。將以下程式碼儲存為“config.php”

Config.php

<?php
   define('DB_SERVER', 'localhost');
   define('DB_USERNAME', 'root');
   define('DB_PASSWORD', '');
   define('DB_DATABASE', 'mydb');
   $db = mysqli_connect(DB_SERVER,DB_USERNAME,DB_PASSWORD,DB_DATABASE);
?>

此 PHP 指令碼在登入指令碼中呼叫。它向用戶顯示一個 HTML 表單以輸入使用者名稱和密碼。如果提交表單,PHP 將執行一個 SELECT 查詢以檢索 admin 表中使用者名稱和密碼與使用者輸入匹配的行。

$myusername = mysqli_real_escape_string($db,$_POST['username']);
$mypassword = mysqli_real_escape_string($db,$_POST['password']); 
      
$sql = "SELECT * FROM admin WHERE username = '$myusername' and passcode = '$mypassword'";
      
$result = mysqli_query($db,$sql);
$row = mysqli_num_rows($result);

如果行數為 1,則表示輸入的使用者名稱和密碼匹配。使用者名稱將儲存到 $_SESSION 變數中,並將瀏覽器定向到 welcome.php 指令碼。

Login.php

將以下程式碼儲存為“login.php”:

<?php
   include("config.php");
   session_start();
   $error='';
   if($_SERVER["REQUEST_METHOD"] == "POST") {
   
      // username and password sent from form 
      $myusername = mysqli_real_escape_string($db,$_POST['username']);
      $mypassword = mysqli_real_escape_string($db,$_POST['password']); 

      $sql = "SELECT * FROM admin WHERE username = '$myusername' and passcode = '$mypassword'";

      $result = mysqli_query($db,$sql);      
      $row = mysqli_num_rows($result);      
      $count = mysqli_num_rows($result);

      if($count == 1) {
	  
         // session_register("myusername");
         $_SESSION['login_user'] = $myusername;
         header("location: welcome.php");
      } else {
         $error = "Your Login Name or Password is invalid";
      }
   }
?>
<html>
<head>
   <title>Login Page</title>
   <style type = "text/css">
      body {
         font-family:Arial, Helvetica, sans-serif;
         font-size:14px;
      }
      label {
         font-weight:bold;
         width:100px;
         font-size:14px;
      }
      .box {
         border:#666666 solid 1px;
      }
   </style>
</head>
<body bgcolor = "#FFFFFF">
   <div align = "center">
      <div style = "width:300px; border: solid 1px #333333; " align = "left">
         <div style = "background-color:#333333; color:#FFFFFF; padding:3px;"><b>Login</b></div>
         <div style = "margin:30px">
            <form action = "" method = "post">
               <label>UserName  :</label><input type = "text" name = "username" class = "box"/><br /><br />
               <label>Password  :</label><input type = "password" name = "password" class = "box" /><br/><br />
               <input type = "submit" value = " Submit "/><br />
            </form>
            <div style = "font-size:11px; color:#cc0000; margin-top:10px"><?php echo $error; ?></div>
         </div>
      </div>
   </div>
</body>
</html>

Welcome.php

當用戶經過身份驗證時,“welcome.php”指令碼將被呼叫。它讀取會話變數以顯示歡迎訊息。

<?php
   include('session.php');
?>
<html>
<head>
   <title>Welcome </title>
</head>
<body>
   <h1>Welcome <?php echo $login_session; ?></h1> 
   <h2><a href = "logout.php">Sign Out</a></h2>
</body>
</html>

Logout.php

最後,登出指令碼將刪除會話並重定向使用者到登入頁面。

<?php
   session_start();

   if(session_destroy()) {
      header("Location: login.php");
   }
?>

要啟動登入應用程式,請訪問“https:///login.php”

PHP MySQL Login 1

輸入使用者名稱和密碼。按下提交按鈕後,將針對 admin 表中的行檢查這些輸入。成功後,您將收到以下訊息:

PHP MySQL Login 2

如果查詢未獲取任何匹配的行,則會顯示錯誤訊息,如下所示:

PHP MySQL Login 3

PHP 和 MySQL

PHP 幾乎可以與所有資料庫軟體一起使用,包括 Oracle 和 Sybase,但最常用的資料庫是免費的 MySQL 資料庫。

您應該已經擁有了什麼?

  • 您已經學習過 MySQL 教程以瞭解 MySQL 基礎知識。

  • 下載並安裝了最新版本的 MySQL。

  • 建立了密碼為guest123的資料庫使用者guest

  • 如果您尚未建立資料庫,則需要 root 使用者及其密碼才能建立資料庫。

我們將本章分為以下部分:

PHP.INI 檔案配置

在您的機器上安裝 PHP 軟體後,將在安裝目錄中建立 php.ini。對於 XAMPP,php.ini 位於 c:\xamm\php 資料夾中。這是一個重要的配置檔案,它控制性能並設定所有與 PHP 相關的引數。

phpinfo() 函式顯示 PHP、Apache、MySQL 和 Web 伺服器安裝的其他元件的不同引數及其當前值列表。

執行以下程式碼以顯示設定,其中一個設定顯示“php.ini”檔案的路徑。

<?php
   echo phpinfo();
?>

已載入的配置檔案

找到顯示 php.ini 檔案位置的“已載入的配置檔案”設定。

C:\xampp\php\php.ini

PHP 的許多行為方面都由大量引數(稱為指令)配置。“php.ini”檔案中的大多數行以分號 (;) 開頭,表示該行已註釋。未註釋的行才是有效的指令及其值。換句話說,要啟用併為特定指令賦值,請刪除開頭的分號。

directive = value

指令名稱*區分大小寫*。指令是用於配置 PHP 或 PHP 擴充套件的變數。請注意,沒有名稱驗證,因此如果找不到預期的指令,將使用預設值,該值可以是字串、數字、PHP 常量(例如 E_ALL 或 M_PI)、INI 常量之一(On、Off、True、False、Yes、No 和 None)。

實際上,C:\XAMPP\PHP 資料夾包含兩個 INI 檔案,一個用於生產環境,另一個用於開發環境。

php.ini-development.ini 與其生產版本非常相似,只是在錯誤方面更為詳細。在開發階段,將其複製為 php.ini 以追蹤程式碼中的錯誤。程式碼準備好部署後,使用 php.ini-production.ini 檔案作為有效的 php.ini 檔案,這實際上會在很大程度上抑制錯誤訊息。

php.ini 中的指令分為不同的類別,例如錯誤處理、資料處理、路徑和目錄、檔案上傳、PHP 擴充套件和模組設定。

以下是“php.ini”檔案中一些重要指令的列表:

short_open_tag = Off

短標籤如下所示:<? ?>。如果要使用 XML 函式,則必須將此選項設定為 Off。

safe_mode = Off

如果將其設定為 On,則可能已使用 --enable-safe-mode 標誌編譯了 PHP。安全模式與 CGI 使用最相關。請參閱本章前面“CGI 編譯時選項”部分中的說明。

safe_mode_exec_dir = [DIR]

此選項僅在安全模式開啟時才相關;它也可以在 Unix 構建過程中使用 --with-exec-dir 標誌進行設定。處於安全模式下的 PHP 僅執行此目錄中的外部二進位制檔案。預設值為 /usr/local/bin。這與提供正常的 PHP/HTML 網頁無關。

safe_mode_allowed_env_vars = [PHP_]

此選項設定使用者在安全模式下可以更改的環境變數。預設情況下,只有以“PHP_”開頭的變數。如果此指令為空,則大多數變數都是可更改的。

safe_mode_protected_env_vars = [LD_LIBRARY_PATH]

此選項設定使用者在安全模式下不能更改的環境變數,即使 safe_mode_allowed_env_vars 設定得很寬鬆。

disable_functions = [function1, function2...]

PHP4 配置中一個受歡迎的補充,並在 PHP5 中得以延續的是能夠出於安全原因停用選定的函式。以前,這需要手動編輯 PHP 的 C 程式碼。檔案系統、系統和網路函式可能是首先要刪除的,因為允許透過 HTTP 寫入檔案和更改系統絕不是一個好主意。

max_execution_time = 30

set_time_limit() 函式在安全模式下不起作用,因此這是使指令碼在安全模式下超時的主要方法。在 Windows 中,必須根據消耗的最大記憶體而不是時間來中止。如果使用 Apache,還可以使用 Apache 超時設定進行超時,但這也會應用於網站上的非 PHP 檔案。

error_reporting = E_ALL & ~E_NOTICE

預設值為 E_ALL & ~E_NOTICE,除通知以外的所有錯誤。開發伺服器應至少設定為預設值;只有生產伺服器才應該考慮較小的值。

error_prepend_string = [""]

透過其結尾標記 error_append_string,此設定允許您使錯誤訊息的顏色與其他文字不同,或者類似操作。

warn_plus_overloading = Off

如果 + 運算子與字串一起使用(如在表單值中),此設定會發出警告。

variables_order = EGPCS

此配置設定取代了 gpc_order。兩者現在都已棄用,register_globals 也已棄用。它設定不同變數的順序:環境、GET、POST、COOKIE 和 SERVER(又名內建)。您可以更改此順序。

變數將按從左到右的順序依次被覆蓋,最右邊的變數每次都勝出。這意味著,如果您保留預設設定,並且碰巧對環境變數、POST 變數和 COOKIE 變數使用了相同的名稱,則在程序結束時,COOKIE 變數將擁有該名稱。在現實生活中,這種情況很少發生。

register_globals = Off

此設定允許您決定是否要將 EGPCS 變數註冊為全域性變數。此設定現已棄用,從 PHP4.2 開始,此標誌預設設定為 Off。請改用超全域性陣列。本書中的所有主要程式碼清單都使用超全域性陣列。

magic_quotes_gpc = On

此設定轉義傳入的 GET/POST/COOKIE 資料中的引號。如果您使用許多可能提交給自己或其他表單並顯示錶單值的表單,則可能需要將此指令設定為 On 或準備對字串型別資料使用 addslashes()。

magic_quotes_runtime = Off

此設定轉義傳入的資料庫和文字字串中的引號。請記住,SQL 在儲存字串時會為單引號和撇號新增反斜槓,並在返回它們時不會將其刪除。如果此設定為 Off,則在輸出來自 SQL 資料庫的任何型別的字串資料時,需要使用 stripslashes()。如果 magic_quotes_sybase 設定為 On,則此設定必須為 Off。

magic_quotes_sybase = Off

此設定使用 Sybase 樣式的單引號而不是反斜槓轉義傳入的資料庫和文字字串中的單引號。如果 magic_quotes_runtime 設定為 On,則此設定必須為 Off。

auto_prepend_file = [path/to/file]

如果在此處指定路徑,則 PHP 必須在每個 PHP 檔案的開頭自動 include() 它。包括路徑限制也適用。

auto_append_file = [path/to/file]

如果在此處指定路徑,則 PHP 必須在每個 PHP 檔案的結尾自動 include() 它,除非您使用 exit() 函式進行轉義。包括路徑限制也適用。

include_path = [DIR]

如果設定此值,則只能從這些目錄包含或需要檔案。include 目錄通常位於您的文件根目錄下;如果您在安全模式下執行,則這是必需的。將其設定為 . 以包含與指令碼所在的目錄相同的目錄中的檔案。多個目錄由冒號分隔:.:/usr/local/apache/htdocs:/usr/local/lib。

doc_root = [DIR]

如果您使用的是 Apache,則已在 httpd.conf 中為此伺服器或虛擬主機設定了文件根目錄。如果您使用的是安全模式,或者只想在網站的一部分(例如,僅在 Web 根目錄的一個子目錄中)啟用 PHP,請在此處設定此值。

file_uploads = [on/off]

如果您將使用 PHP 指令碼上傳檔案,請開啟此標誌。

upload_tmp_dir = [DIR]

除非您瞭解 HTTP 上傳的含義,否則請勿註釋此行!

session.save_handler = files

除極少數情況外,您都不希望更改此設定。所以不要碰它。

ignore_user_abort = [On/Off]

此設定控制網站訪問者單擊瀏覽器“停止”按鈕時會發生什麼。預設值為 On,這意味著指令碼將繼續執行到完成或超時。如果將設定更改為 Off,指令碼將中止。此設定僅在模組模式下有效,在 CGI 模式下無效。

mysql.default_host = hostname

如果未指定其他主機,則連線到資料庫伺服器時使用的預設伺服器主機。

mysql.default_user = username

如果未指定其他名稱,則連線到資料庫伺服器時使用的預設使用者名稱。

mysql.default_password = password

如果未指定其他密碼,則連線到資料庫伺服器時使用的預設密碼。

PHP 陣列解構

在 PHP 中,“陣列解構”是指將陣列元素提取到單個變數中的機制。它也可以稱為陣列解包。PHP 的 list() 結構用於解構給定的陣列,並將其專案在一個語句中分配給變數列表。

list($var1, $var2, $var3, . . . ) = array(val1, val2, val3, . . .);

因此,**val1** 賦值給 **$var1**,**val2** 賦值給 **$var2**,依此類推。即使由於括號的存在,您可能認為 list() 是一個函式,但它不是,因為它沒有返回值。PHP 將字串視為陣列,但是不能用 list() 解包它。此外,list() 中的括號不能為空。

除了 list() 之外,您還可以使用方括號 [] 作為解構陣列的快捷方式。

[$var1, $var2, $var3, . . . ] = array(val1, val2, val3, . . .);

示例

請看以下示例:

<?php
   $marks = array(50, 56, 70);
   list($p, $c, $m) = $marks;
   echo "Physics: $p  Chemistry: $c  Maths: $m" . PHP_EOL;

   # shortcut notation
   [$p, $c, $m] = $marks;
   echo "Physics: $p  Chemistry: $c  Maths: $m" . PHP_EOL;
?>

它將產生以下輸出

Physics: 50  Chemistry: 56  Maths: 70
Physics: 50  Chemistry: 56  Maths: 70

解構關聯陣列

在 PHP 7.1.0 之前,list() 僅適用於從 0 開始的數字索引的數字陣列。在 PHP 7.1 中,陣列解構也適用於關聯陣列。

讓我們嘗試解構(或解包)以下關聯陣列,一個具有非數字索引的陣列。

$marks = array('p'=>50, 'c'=>56, 'm'=>70);

要解構此陣列,list() 語句會將每個陣列鍵與一個獨立變數關聯。

list('p'=>$p, 'c'=>$c, 'm'=>$m) = $marks;

或者,您還可以使用 [] 替代解構表示法。

['p'=>$p, 'c'=>$c, 'm'=>$m] = $marks;

嘗試執行以下 PHP 指令碼:

<?php
   $marks = array('p'=>50, 'c'=>56, 'm'=>70);
   list('p'=>$p, 'c'=>$c, 'm'=>$m) = $marks;
   echo "Physics: $p  Chemistry: $c  Maths: $m" . PHP_EOL;

   # shortcut notation
   ['p'=>$p, 'c'=>$c, 'm'=>$m] = $marks;
   echo "Physics: $p  Chemistry: $c  Maths: $m" . PHP_EOL;
?>

跳過陣列元素

對於索引陣列,您可以跳過其中一些元素,只將其他元素賦值給所需的變數。

<?php
   $marks = array(50, 56, 70);
   list($p, , $m) = $marks;
   echo "Physics: $p  Maths: $m" . PHP_EOL;

   # shortcut notation
   [$p, , $m] = $marks;
   echo "Physics: $p  Maths: $m" . PHP_EOL;
?>

對於關聯陣列,由於索引不是從 0 開始遞增的,因此在賦值時不必遵循元素的順序。

<?php
   $marks = array('p'=>50, 'c'=>56, 'm'=>70);
   list('c'=>$c, 'p'=>$p, 'm'=>$m) = $marks;
   echo "Physics: $p  Chemistry: $c  Maths: $m" . PHP_EOL;

   ['c'=>$c, 'm'=>$m, 'p'=>$p] = $marks;		# shortcut notation
   echo "Physics: $p  Chemistry: $c  Maths: $m" . PHP_EOL;
?>

解構巢狀陣列

您還可以將陣列解構的概念擴充套件到巢狀陣列。在下面的示例中,巢狀的子陣列是一個索引陣列。

<?php
   $marks = ['marks' => [50, 60, 70]];
   ['marks' => [$p, $c, $m]] = $marks;
   echo "Physics: $p  Chemistry: $c  Maths: $m" . PHP_EOL;
?>

即使巢狀陣列也是關聯陣列,解構也能很好地工作。

<?php
   $marks = ['marks' => ['p'=>50, 'c'=>60, 'm'=>70]];
   ['marks' => ['p'=>$p, 'c'=>$c, 'm'=>$m]] = $marks;
   echo "Physics: $p  Chemistry: $c  Maths: $m" . PHP_EOL;
?>

PHP 編碼規範

每個公司都根據其最佳實踐遵循其自身的編碼標準。需要編碼標準是因為可能有許多開發人員從事不同的模組,如果他們開始發明自己的標準,那麼原始碼將變得非常難以管理,並且將來難以維護該原始碼。

以下是應該使用編碼規範的一些原因:

  • 您的同行程式設計師必須理解您編寫的程式碼。編碼標準充當所有團隊破譯程式碼的藍圖。

  • 一致的編碼實現的簡潔性和清晰性可避免常見的錯誤。

  • 如果您過一段時間後修改程式碼,則更容易理解該程式碼。

  • 遵循統一的編碼標準可以提高軟體質量。

在 PHP 中編碼時,可以遵循一些準則。

縮排和行長

使用 4 個空格縮排,不要使用任何製表符,因為不同的計算機使用不同的製表符設定。建議將行長保持在大約 75-85 個字元,以提高程式碼可讀性。

控制結構

這些包括 if、for、while、switch 等。控制語句在控制關鍵字和左括號之間應留有一個空格,以便將它們與函式呼叫區分開來。強烈建議您始終使用花括號,即使在技術上可選的情況下也是如此。

示例

if ((condition1) || (condition2)) {
   action1;
} elseif ((condition3) && (condition4)) {
   action2;
} else {
   default action;
}

您可以按如下方式編寫switch語句

switch (condition) {
   case 1:
      action1;
      break;

   case 2:
      action2;
      break;

   default:
      defaultaction;
      break;
}

函式呼叫

函式呼叫時,函式名稱、左括號和第一個引數之間不應有空格;逗號和每個引數之間應有空格;最後一個引數、右括號和分號之間不應有空格。這是一個示例:

$var = foo($bar, $baz, $quux);

函式定義

函式宣告遵循“BSD/Allman 樣式”:

function fooFunction($arg1, $arg2 = '') {
   if (condition) {
      statement;
   }
   return $val;
}

註釋

C 樣式註釋(/* */)和標準 C++ 註釋(//)都可以。允許使用 Perl/shell 樣式註釋(#),但不鼓勵使用。

PHP 程式碼標籤

始終使用<?php ?> 來分隔 PHP 程式碼,而不是<? ?> 簡寫。這是 PHP 相容性所必需的,也是在不同作業系統和設定上包含 PHP 程式碼最可移植的方式。

變數名

  • 使用所有小寫字母

  • 使用 '_' 作為單詞分隔符。

  • 全域性變數應以 'g' 開頭。

  • 全域性常量應全部大寫,並使用 '_' 分隔符。

  • 靜態變數可以以 's' 開頭。

使函式可重入

函式不應保留阻止函式可重入的靜態變數。

宣告塊的對齊

宣告塊應對齊。

每行一個語句

每行應只有一個語句,除非語句非常緊密相關。

簡短的方法或函式

方法應限制在單頁程式碼內。

編寫 PHP 程式時,還應考慮許多其他要點。總體目標是在整個程式碼程式設計過程中保持一致,只有遵循任何編碼標準才能做到這一點。如果您喜歡不同的內容,可以設計自己的標準。

PHP - 正則表示式

正則表示式只不過是字元本身的序列或模式。它們為模式匹配功能奠定了基礎。

使用正則表示式,您可以在另一個字串中搜索特定字串,您可以用另一個字串替換一個字串,並且您可以將一個字串拆分為許多塊。

PHP 提供了特定於兩組正則表示式函式的函式,每組函式對應於某種型別的正則表示式。您可以根據自己的喜好使用任何一種。

  • POSIX 正則表示式
  • PERL 風格正則表示式

POSIX 正則表示式

POSIX 正則表示式的結構與典型的算術表示式並不相似:各種元素(運算子)組合在一起形成更復雜的表示式。

最簡單的正則表示式是匹配單個字元的表示式,例如字串 g、haggle 或 bag 中的 g。

讓我們解釋一下 POSIX 正則表示式中使用的幾個概念。之後,我們將向您介紹與正則表示式相關的函式。

方括號

方括號 ([]) 在正則表示式上下文中具有特殊含義。它們用於查詢一系列字元。

序號 表示式和描述
1

[0-9]

它匹配從 0 到 9 的任何十進位制數字。

2

[a-z]

它匹配從 a 到 z 的任何小寫字元。

3

[A-Z]

它匹配從 A 到 Z 的任何大寫字元。

4

[a-Z]

它匹配從小寫 a 到大寫 Z 的任何字元。

上面顯示的範圍是通用的;您也可以使用範圍 [0-3] 來匹配從 0 到 3 的任何十進位制數字,或使用範圍 [b-v] 來匹配從小寫 b 到 v 的任何小寫字元。

量詞

括號字元序列和單個字元的頻率或位置可以用特殊字元表示。每個特殊字元都有其特定的含義。+、*、?、{int. range} 和 $ 標誌都跟在一個字元序列之後。

序號 表示式和描述
1

p+

它匹配任何包含至少一個 p 的字串。

2

p*

它匹配任何包含零個或多個 p 的字串。

3

p?

它匹配任何包含零個或一個 p 的字串。

4

p{N}

它匹配任何包含N個 p 序列的字串

5

p{2,3}

它匹配任何包含兩個或三個 p 序列的字串。

6

p{2, }

它匹配任何包含至少兩個 p 序列的字串。

7

p$

它匹配任何在結尾處有 p 的字串。

8

^p

它匹配任何在開頭處有 p 的字串。

示例

以下示例將闡明您關於匹配字元的概念。

序號 表示式和描述
1

[^a-zA-Z]

它匹配任何不包含從 a 到 z 和從 A 到 Z 的任何字元的字串。

2

p.p

它匹配任何包含 p、後跟任何字元,然後後跟另一個 p 的字串。

3

^.{2}$

它匹配任何包含恰好兩個字元的字串。

4

<b>(.*)</b>

它匹配任何包含在<b>和</b>之間的字串。

5

p(hp)*

它匹配任何包含 p 後跟零個或多個 php 序列的字串。

預定義字元範圍

為了方便您的程式設計,可以使用多個預定義字元範圍,也稱為字元類。字元類指定整個字元範圍,例如字母或整數集:

序號 表示式和描述
1

[[:alpha:]]

它匹配任何包含字母字元 aA 到 zZ 的字串。

2

[[:digit:]]

它匹配任何包含數字 0 到 9 的字串。

3

[[:alnum:]]

它匹配任何包含字母數字字元 aA 到 zZ 和 0 到 9 的字串。

4

[[:space:]]

它匹配任何包含空格的字串。

PHP 的 Regexp POSIX 函式

PHP 目前提供七個函式,用於使用 POSIX 風格正則表示式搜尋字串:

序號 函式及描述
1 ereg()

ereg() 函式在 string 指定的字串中搜索 pattern 指定的字串,如果找到該模式,則返回 true,否則返回 false。

2 ereg_replace()

ereg_replace() 函式搜尋 pattern 指定的字串,如果找到,則用 replacement 替換 pattern。

3 eregi()

eregi() 函式在 pattern 指定的字串中搜索 string 指定的字串。搜尋不區分大小寫。

4 eregi_replace()

eregi_replace() 函式的工作方式與 ereg_replace() 完全相同,只是它對 string 中 pattern 的搜尋不區分大小寫。

5 split()

split() 函式會將字串分成多個元素,每個元素的邊界基於 string 中 pattern 的出現。

6 spliti()

spliti() 函式的工作方式與其同級 split() 完全相同,只是它不區分大小寫。

7 sql_regcase()

sql_regcase() 函式可以被認為是一個實用程式函式,它將輸入引數字串中的每個字元轉換為包含兩個字元的括號表示式。

PERL 風格正則表示式

Perl 風格正則表示式與其 POSIX 對應項類似。POSIX 語法幾乎可以與 Perl 風格正則表示式函式互換使用。實際上,您可以使用上一節 POSIX 中介紹的任何量詞。

讓我們解釋一下 PERL 正則表示式中使用的幾個概念。之後,我們將向您介紹與正則表示式相關的函式。

元字元

元字元只是一個以反斜槓開頭的字母字元,它賦予組合特殊的含義。

例如,您可以使用 '\d' 元字元搜尋大量金額:/([\d]+)000/,這裡\d將搜尋任何數字字元的字串。

以下是 PERL 風格正則表示式中可使用的元字元列表。

Character		Description
.              a single character
\s             a whitespace character (space, tab, newline)
\S             non-whitespace character
\d             a digit (0-9)
\D             a non-digit
\w             a word character (a-z, A-Z, 0-9, _)
\W             a non-word character
[aeiou]        matches a single character in the given set
[^aeiou]       matches a single character outside the given set
(foo|bar|baz)  matches any of the alternatives specified

修飾符

有幾個修飾符可以使您使用正則表示式的操作更容易,例如區分大小寫、多行搜尋等。

Modifier	Description
i 	Makes the match case insensitive
m 	Specifies that if the string has newline or carriage
	return characters, the ^ and $ operators will now
	match against a newline boundary, instead of a
	string boundary
o 	Evaluates the expression only once
s 	Allows use of . to match a newline character
x 	Allows you to use white space in the expression for clarity
g 	Globally finds all matches
cg 	Allows a search to continue even after a global match fails

PHP 的 Regexp PERL 相容函式

PHP 提供以下函式,用於使用 Perl 相容的正則表示式搜尋字串:

序號 函式及描述
1 preg_match()

preg_match() 函式在 string 中搜索 pattern,如果存在 pattern,則返回 true,否則返回 false。

2 preg_match_all()

preg_match_all() 函式匹配 string 中 pattern 的所有出現。

3 preg_replace()

preg_replace() 函式的工作方式與 ereg_replace() 完全相同,只是可以在 pattern 和 replacement 輸入引數中使用正則表示式。

4 preg_split()

preg_split() 函式的工作方式與 split() 完全相同,只是它接受正則表示式作為 pattern 的輸入引數。

5 preg_grep()

preg_grep() 函式搜尋 input_array 的所有元素,返回與正則表示式 pattern 匹配的所有元素。

6 preg_quote()

引用正則表示式字元

PHP 錯誤處理

PHP 中的錯誤處理是指在 PHP 程式碼中設定規定,以有效識別和恢復程式可能遇到的執行時錯誤。在 PHP 中,錯誤的處理藉助於:

  • die() 函式

  • 錯誤處理程式函式

die() 函式

die() 函式是 PHP 中 exit() 的別名。兩者都會在遇到時終止當前 PHP 指令碼。如果在括號中指定可選字串,則會在程式終止之前輸出該字串。

die("message");

示例

以下程式碼是 die() 在 PHP 指令碼中的典型用法。如果 PHP 找不到檔案,它會顯示“檔案未找到”訊息,否則會繼續開啟它以進行後續處理。

<?php
   if(!file_exists("nosuchfile.txt")) {
      die("File not found");
   } else {
      $file = fopen("nosuchfile","r");
      print "Opend file sucessfully";
	  
      // Rest of the code here.
      fclose($file);
   }
?>

它將產生以下輸出

File not found

使用上述技術,您可以隨時停止程式出錯並顯示更有意義且使用者友好的訊息,而不是讓 PHP 生成致命錯誤訊息。

錯誤處理程式函式

使用 die() 進行錯誤處理被認為是一種笨拙且程式設計不良的做法,因為它會導致網站使用者體驗不佳。PHP 提供了一個更優雅的替代方案,您可以使用它來定義自定義函式並將其指定為錯誤處理程式。

set_error_handler() 函式具有以下引數:

set_error_handler(?callable $callback, int $error_levels = E_ALL): ?callable

第一個引數是一個使用者定義的函式,每當遇到錯誤時都會自動呼叫該函式。

自定義錯誤處理程式回撥函式應具有以下引數:

handler(
   int $errno,
   string $errstr,
   string $errfile = ?,
   int $errline = ?,
   array $errcontext = ?
): bool

引數

引數 重要性 描述
errno 必需 它指定使用者定義錯誤的錯誤級別。它必須是數值。
errstr 必需 它指定使用者定義錯誤的錯誤訊息。
errfile 可選 它指定發生錯誤的檔名。
errline 可選 它指定發生錯誤的行號。
errcontext 可選 它指定一個數組,其中包含發生錯誤時正在使用的變數及其值。

如果回撥函式返回 false,則將呼叫預設錯誤。

$errno 是與預定義錯誤級別對應的整數。

序號 常量 & 說明
1

E_ERROR (int)

無法恢復的致命執行時錯誤。指令碼執行將停止。

1
2

E_WARNING (int)

執行時警告(非致命錯誤)。指令碼執行不會停止。

2
3

E_PARSE (int)

編譯時解析錯誤。解析錯誤應該只由解析器生成。

4
4

E_NOTICE (int)

執行時提示。某些內容可能表示錯誤,但也可能在指令碼正常執行過程中發生。

8
5

E_CORE_ERROR (int)

PHP 初始啟動期間發生的致命錯誤。這類似於E_ERROR

16
6

E_CORE_WARNING (int)

PHP 初始啟動期間發生的警告(非致命錯誤)。這類似於E_WARNING

32
7

E_COMPILE_ERROR (int)

致命的編譯時錯誤。這類似於E_ERROR

64
8

E_COMPILE_WARNING (int)

編譯時警告(非致命錯誤)。這類似於E_WARNING

128
9

E_USER_ERROR (int)

使用者生成的錯誤訊息。這類似於E_ERROR,透過使用PHP函式trigger_error()在PHP程式碼中生成。

256
10

E_USER_WARNING (int)

使用者生成的警告訊息。這類似於E_WARNING,透過使用函式trigger_error()在PHP程式碼中生成。

512
11

E_USER_NOTICE (int)

使用者生成的提示訊息。這類似於E_NOTICE,透過使用函式trigger_error()在PHP程式碼中生成。

1024
12

E_STRICT (int)

啟用此選項可以使PHP建議對程式碼進行更改,以確保程式碼的最佳互操作性和向前相容性。

2048
13

E_RECOVERABLE_ERROR (int)

可捕獲的致命錯誤。如果錯誤沒有被使用者定義的處理程式捕獲,則應用程式將中止,如同E_ERROR一樣。

4096
14

E_DEPRECATED (int)

執行時提示。啟用此選項可接收有關將來版本中無法執行的程式碼的警告。

8192
15

E_USER_DEPRECATED (int)

使用者生成的警告訊息。這類似於E_DEPRECATED,透過使用函式trigger_error()在PHP程式碼中生成。

16384
16

E_ALL (int)

所有錯誤、警告和提示。

32767

示例

請看以下示例:

<?php
   error_reporting(E_ERROR);

   function myerrorhandler($errno, $errstr) {
      echo "error No: $errno Error message: $errstr" . PHP_EOL;
      echo "Terminating PHP script"; 
      die();
   }

   set_error_handler("myerrorhandler");

   $f = fopen("nosuchfile.txt", "r");
   echo "file opened successfully";
   // rest of the code
   fclose($f);
?>

它將產生以下輸出

error No: 2 Error message: fopen(nosuchfile.txt): Failed to open stream: No 
such file or directory
Terminating PHP script

PHP 的錯誤類層次結構從 throwable 介面開始。PHP 中所有預定義的 Error 類都繼承自 Error 類。

ArithmeticError 類

ArithmeticError 類繼承自Error 類。此類錯誤可能在執行某些數學運算時發生,例如執行負數位的按位移位運算。

示例

請看以下示例:

<?php
   try {
      $a = 10;
      $b = -3;
      $result = $a << $b;
   } 
   catch (ArithmeticError $e) {
      echo $e->getMessage(); 
   }
?>

它將產生以下輸出

Bit shift by negative number

當呼叫 intdiv() 函式的結果值超出整數的合法範圍時,也會丟擲此錯誤。

示例

請看以下示例:

<?php
   try {
      $a = PHP_INT_MIN;
      $b = -1;
      $result = intdiv($a, $b);
      echo $result;
   } 
   catch (ArithmeticError $e) {
      echo $e->getMessage(); 
   } 
?>

它將產生以下輸出

Division of PHP_INT_MIN by -1 is not an integer

DivisionByZeroError

DivisionByZeroError 類是 ArithmeticError 類的子類。當除法運算中分母的值為零時,就會發生此類錯誤。

示例:模零

請檢視以下示例

<?php
   try {
      $a = 10;
      $b = 0;
      $result = $a%$b;
      echo $result;
   } 
   catch (DivisionByZeroError $e) {
      echo $e->getMessage(); 
   }
?>

它將產生以下輸出

Modulo by zero

當模運算子 (%) 的第二個運算數為 0,以及 intdiv() 函式的第二個引數為 0 時,也會發生這種情況。

示例:除以零

請看以下示例:

<?php
   try {
      $a = 10;
      $b = 0;
      $result = $a/$b;
      echo $result;
   } 
   catch (DivisionByZeroError $e) {
      echo $e->getMessage(); 
   }
?>

它將產生以下輸出

Division by zero 

ArgumentCountError

當傳遞給使用者定義函式或方法的引數少於其定義中的引數時,PHP 解析器將丟擲 ArgumentCountError。

示例

請看以下示例:

<?php
   function add($x, $y) {
      return $x+$y;
   }
   try {
      echo add(10);
   }
   catch (ArgumentCountError $e) {
      echo $e->getMessage();
   }
?>

它將產生以下輸出

Too few arguments to function add(), 1 passed in C:\xampp\php\test.php on line 9 and exactly 2 expected

TypeError

當實際引數型別和形式引數型別不匹配時,會引發此錯誤;返回值型別與宣告的返回值型別不匹配。

示例

請看以下示例:

<?php
   function add(int $first, int $second) {
      echo "addition: " . $first + second;
   }

   try {
      add('first', 'second');
   } 
   catch (TypeError $e) {
      echo $e->getMessage(), "";
   }
?>

它將產生以下輸出

add(): Argument #1 ($first) must be of type int, string given, 
   called in /home/cg/root/63814/main.php on line 7

當向 PHP 的內建函式傳遞不正確的引數數量時,也會丟擲 TypeError。但是,必須在開頭設定“strict_types=1”指令。

示例

請看以下示例:

<?php
   declare(strict_types=1);
   try {
      echo pow(100,2,3);
   }
   catch (TypeError $e) {
      echo $e->getMessage(), "";
   }
?>

它將產生以下輸出

pow() expects exactly 2 parameters, 3 given

PHP 中的異常處理

PHP 具有類似於其他程式語言的異常模型。異常很重要,並提供對錯誤處理的更好控制。

讓我們解釋一下與異常相關的新的關鍵字。

  • Try − 使用異常的函式應位於“try”塊中。如果異常未觸發,則程式碼將照常繼續執行。但是,如果異常觸發,則會“丟擲”異常。

  • Throw − 這是觸發異常的方式。“throw”必須至少有一個“catch”。

  • Catch − “catch”塊檢索異常並建立一個包含異常資訊的 物件。

當丟擲異常時,語句後面的程式碼將不會執行,PHP 將嘗試查詢第一個匹配的 catch 塊。如果未捕獲異常,則將發出 PHP 致命錯誤,並顯示“未捕獲的異常...”。

  • 可以在 PHP 中丟擲並捕獲(“捕獲”)異常。程式碼可以用 try 塊包圍。

  • 每個 try 必須至少有一個相應的 catch 塊。可以使用多個 catch 塊來捕獲不同類別的異常。

  • 可以在 catch 塊中丟擲(或重新丟擲)異常。

示例

以下是程式碼片段,請將此程式碼複製貼上到檔案中並驗證結果。

<?php
   try {
      $error = 'Always throw this error';
      throw new Exception($error);
      
      // Code following an exception is not executed.
      echo 'Never executed';
   }catch (Exception $e) {
      echo 'Caught exception: ',  $e->getMessage(), "";
   }
   
   // Continue execution
   echo 'Hello World';
?>

在上面的示例中,$e->getMessage 函式用於獲取錯誤訊息。以下函式可從Exception類中使用。

  • getMessage() − 異常訊息

  • getCode() − 異常程式碼

  • getFile() − 原始檔名

  • getLine() − 原始碼行號

  • getTrace() − backtrace() 的陣列

  • getTraceAsString() − 格式化的跟蹤字串

建立自定義異常處理程式

您可以定義自己的自定義異常處理程式。使用以下函式設定使用者定義的異常處理程式函式。

string set_exception_handler ( callback $exception_handler )

這裡exception_handler是當發生未捕獲異常時要呼叫的函式的名稱。此函式必須在呼叫 set_exception_handler() 之前定義。

示例

請看以下示例:

<?php
   function exception_handler($exception) {
      echo "Uncaught exception: " , $exception->getMessage(), "\n";
   }
	
   set_exception_handler('exception_handler');
   throw new Exception('Uncaught Exception');
   
   echo "Not Executed";
?>

檢視完整的錯誤處理函式集,請訪問 PHP 錯誤處理函式

PHP Try…Catch

在 PHP 中,提供try、catch、throwfinally關鍵字來處理異常。錯誤是意外的程式結果,程式本身無法處理,程式必須使用 die() 或設定自定義錯誤處理程式終止。

另一方面,異常是指可以以某種方式處理的意外情況,這樣程式可以在將異常丟擲其正常流程後繼續執行。

可以在 PHP 程式碼中使用 catch 關鍵字丟擲和捕獲異常。可能容易發生異常的程式碼塊用try塊包圍。每個try必須至少有一個對應的catch或finally塊。

Try、Throw、Catch 和 Finally

這四個與異常相關的關鍵字具有以下作用:

  • Try − 可能發生某些異常的程式碼塊放在“try”塊中。如果異常未觸發,則程式碼繼續執行。但是,如果發生異常,則會“丟擲”異常。執行將停止,PHP 將查詢匹配的“catch”塊。如果未捕獲異常,PHP 將發出致命錯誤。

  • Throw − 這是觸發異常的方式。“throw”必須至少有一個“catch”或“finally”塊。

  • Catch − 一個檢索異常並建立包含異常資訊的 物件的塊。可以使用多個 catch 塊來捕獲不同的異常。

  • Finally − finally 塊中的程式碼總是在 throw 或 catch 塊之後執行。

示例

這是一個異常處理技術的示例。程式碼在瀏覽器上呈現兩個文字欄位,並要求使用者輸入兩個數字以執行它們的除法。如果第二個數字(分母)為 0,則會丟擲異常,程式進入 catch 塊並列印異常訊息。否則,將顯示除法的結果。

<html>
<body>
   <form action="<?php echo $_SERVER['PHP_SELF'];?>" method="post">
      <h3>First No: <input type="text" name="first"/></h3>
      <h3>Second No: <input type="text" name="second"/></h3>
      <input type="submit" value="Submit" />
   </form>

   <?php
      if ($_SERVER["REQUEST_METHOD"] == "POST") {
         $x = $_POST['first'];
         $y = $_POST['second'];
         echo "$x $y";
         try {
            if ($y == 0) {
               throw new Exception("Division by Zero");
            }
            $z = $x/$y;
            echo "<h3>x = $x y = $y Division = $z<br>";
         }
         catch (Exception $e) {
            echo "<h3> Exception: " . $e->getMessage();
         }
      }
   ?>
</body>
</html>

它將產生以下輸出

Case 1: x = 10 y = 5 Division = 2

Case 2: x = 10 y = 0
Exception: Division by Zero

Exception 類

PHP 丟擲Exception 類的物件。在 PHP 中,Exception 類是使用者異常的基礎。它實現了 throwable 介面。

此類定義了以下方法:

getMessage()

此函式將異常訊息作為字串返回:

final public Exception::getMessage(): string

getCode()

此函式返回 Exception 中的異常程式碼作為int

final public Exception::getCode(): int

來看下面的示例

try {
   throw new Exception("Some error message", 30);
} 
catch(Exception $e) {
   echo "The exception code is: " . $e->getCode();
}

getFile()

此函式返回建立異常的檔名:

final public Exception::getFile(): string

來看下面的示例

try {
   if ($y == 0) {
      throw new Exception("Division by Zero");
   }
   $z = $x/$y;
   echo "<h3>x = $x y = $y Division = $z<br>";
}
catch (Exception $e) {
   echo "<h3> Exception: " . $e->getMessage(). " in " . $e->getFile();
}

它將產生以下輸出

Exception: Division by Zero in C:\xampp\htdocs\hello.php

getLine()

此函式返回建立異常的行號:

final public Exception::getLine(): int

示例

請看以下示例:

<?php
   if ($_SERVER["REQUEST_METHOD"] == "POST") {
      $x = $_POST['first'];
      $y = $_POST['second'];
      echo "$x $y";
      try {
         if ($y == 0) {
            throw new Exception("Division by Zero");
         }
         $z = $x/$y;
         echo "<h3>x = $x y = $y Division = $z<br>";
      }
      catch (Exception $e) {
         echo "<h3> Exception: " . $e->getMessage(). " in " . $e->getLine() . " of " . $e->getFile();
      }
   }
?>

它將產生以下輸出

Exception: Division by Zero in 21 of C:\xampp\htdocs\hello.php

多個 Catch 塊

PHP 允許在 try 塊之後使用一系列 catch 塊來處理不同的異常情況。可以使用多個catch塊來處理預定義的異常和錯誤以及使用者定義的異常。

示例

以下示例使用catch塊來處理 DivisioByZeroError、TypeError、ArgumentCountError 和 InvalidArgumentException 條件。還有一個catch塊用於處理常規 Exception。

<?php
   declare(strict_types=1);
   function divide(int $a, int $b) : int {
      return $a / $b;
   }
   $a=10;
   $b=0;
   try {
   if (!$b) {
      throw new DivisionByZeroError('Division by zero.');
      if (is_int($a)==FALSE || is_int($b)==FALSE)
      throw new InvalidArgumentException("Invalid type of arguments");
      $result=divide($a, $b);
      echo $result;
   }
   
   // if argument types not matching
   catch (TypeError $x) {
      echo $x->getMessage();
   }

   // if denominator is 0
   catch (DivisionByZeroError $y) {
      echo $y->getMessage();
   }

   // if number of arguments not equal to 2
   catch (ArgumentCountError $z) {
      echo $z->getMessage();
   }

   // if argument types not matching
   catch (InvalidArgumentException $i) {
      echo $i->getMessage();
   }

   // any uncaught exception
   catch (Exception $ex) {
      echo $ex->getMessage();
   }	
?>

首先,由於分母為 0,將顯示“除以 0”錯誤:

Division by 0

設定$b=3將導致 TypeError,因為 divide 函式預期返回整數,但除法結果為float

divide(): Return value must be of type int, float returned

如果僅將一個變數傳遞給 divide 函式,透過更改$res=divide($a);這將導致ArgumentCountError

Too few arguments to function divide(), 1 passed in C:\xampp\htdocs\hello.php on line 16 and exactly 2 expected

如果其中一個引數不是整數,則為InvalidArgumentException的情況。將$b更改為字串:

Invalid type of arguments

Finally 塊

也可以在catch塊之後或代替catch塊指定finally塊。finally塊中的程式碼將在trycatch塊之後始終執行,無論是否已丟擲異常,以及在正常執行恢復之前。

try {
   if ($y == 0) {
      throw new Exception("Division by Zero");
   }
   $z = $x/$y;
   echo "<h3>x = $x y = $y Division = $z </h3><br>";
}
catch (Exception $e) {
   echo "<h3> Exception: " . $e->getMessage(). "</h3>";
}
finally {
   echo "<h3>End of try - catch - finally</h3>";
}

它將產生以下輸出:

情況 1:

x = 10 y = 5 Division = 2
End of try - catch – finally

情況 2:

X=10 y=0
Exception: Division by Zero
End of try - catch – finally

帶有 Return 的 Finally

try塊或catch塊(或兩者)包含return語句時,finally 塊有一個特殊的行為。通常,return語句會導致程式的控制返回到呼叫位置。但是,對於具有帶有return的 try/catch 塊的函式,finally塊中的語句將在返回之前先執行。

示例

在下面的示例中,div() 函式具有“try-catch-finally”結構。try塊在沒有異常的情況下返回除法的結果。如果發生異常,則catch塊返回錯誤訊息。但是,無論哪種情況,finally塊中的語句都將首先執行。

<?php
   function div($x, $y) {
      try {
         if ($y==0)
         throw new Exception("Division by 0");
         else
         $res=$x/$y;;
         return $res;
      } 
      catch (Exception $e) {
         return $e->getMessage();
      }
      finally {
         echo "This block is always executed\n";
      }
   }
   $x=10;
   $y=0;
   echo div($x,$y);
?>

它將產生以下輸出

This block is always executed
Division by 0

PHP 除錯Bug

PHP 程式碼中的錯誤是指程式中的錯誤,會導致意外結果或崩潰。在使用者發現錯誤之前找到錯誤的系統方法稱為除錯。本章介紹了一些在 PHP 程式碼中跟蹤錯誤的重要技巧。

程式很少第一次就能正常工作。程式中可能會出現許多問題,這些問題會導致 PHP 直譯器生成錯誤訊息。您可以選擇這些錯誤訊息的去向。這些訊息可以與其他程式輸出一起傳送到 Web 瀏覽器。它們也可以包含在“Web 伺服器錯誤日誌”中。

要在瀏覽器中顯示錯誤訊息,請將“display_errors”配置指令設定為 ON。確保在“php.ini”檔案中啟用了以下設定。

display_errors=On
display_startup_errors=On

您還可以使用ini_set() 函式覆蓋“pnp.ini”配置:

ini_set('display_errors', 1)
ini_set('display_startup_errors', 1)

要將錯誤傳送到 Web 伺服器錯誤日誌,請將“log_errors”設定為 ON。如果您希望錯誤訊息同時出現在兩個位置,則可以將它們都設定為 On。

PHP 定義了一些常量,您可以使用這些常量來設定error_reporting的值,以便僅報告特定型別的錯誤:

  • E_ALL(所有錯誤,除了嚴格提示)

  • E_PARSE(解析錯誤)

  • E_ERROR(致命錯誤)

  • E_WARNING(警告)

  • E_NOTICE(提示)

  • E_STRICT(嚴格提示)

編寫PHP程式時,最好使用支援PHP的編輯器,例如BBEdit或Emacs。這些編輯器的特殊功能之一是語法高亮顯示。它會根據程式不同部分的內容更改其顏色。例如,字串為粉色,if和while等關鍵字為藍色,註釋為灰色,變數為黑色。

微軟的VS Code也是編輯PHP程式碼的好選擇。如果安裝VS Code擴充套件Intelephense,您將在編輯器視窗輸入PHP語句時獲得型別提示和錯誤訊息。

另一個功能是引號和括號匹配,這有助於確保引號和括號平衡。當您輸入一個閉合分隔符,例如"}"時,編輯器會突出顯示與其匹配的開啟"{"。

除錯程式碼時需檢查的要點

除錯程式程式碼時,需要驗證以下幾點:

缺少分號

每個PHP語句都以分號 (;) 結尾。PHP不會停止讀取語句,直到它到達分號。如果您省略一行末尾的分號,PHP將繼續讀取下一行的語句。

等號不足

在比較語句中詢問兩個值是否相等時,需要使用兩個等號 (==)。使用一個等號是一個常見的錯誤。

變數名拼寫錯誤

如果拼寫錯誤變數名,PHP會將其理解為一個新變數。記住:對PHP來說,$test與$Test不是同一個變數。

缺少美元符號

變數名中缺少美元符號很難發現,但至少通常會導致錯誤訊息,以便您知道在哪裡查詢問題。

令人困擾的引號

引號可能過多、過少或型別錯誤。因此,請檢查引號數量是否平衡。

缺少括號和花括號

它們應該總是成對出現。

陣列索引

PHP中的陣列是專案的集合,每個專案都分配一個從0開始遞增的索引。

此外,請正確處理所有錯誤並將所有跟蹤訊息定向到系統日誌檔案,以便如果發生任何問題,它將被記錄到系統日誌檔案中,並且您可以除錯該問題。

面向C開發人員的PHP

如果您具備C程式設計的先驗知識,學習PHP就會容易得多,尤其是基礎知識。儘管PHP與C非常相似,但它包含了許多特定於Web的庫,所有這些庫都直接連線到您最喜歡的Web伺服器。

理解PHP最簡單的方法是將其視為可以嵌入HTML文件中的解釋型C。PHP指令碼也可以像C程式一樣從命令列執行。

語句和函式定義的語法應該很熟悉,只是變數前面總是帶有$,並且函式不需要單獨的原型。

讓我們來看看PHP和C的一些異同:

C和PHP之間的相似之處

語法 - 廣義地說,PHP語法與C相同,如果您已經熟悉C,這使得學習PHP更容易。

與C類似,PHP程式碼不區分空格,語句以分號結尾。

函式呼叫具有相同的結構

my_function(expression1, expression2) {
   Statements;
}

花括號用於將多個語句放入塊中。

PHP支援C和C++風格的註釋(/* */以及//),以及Perl和shell指令碼風格(#)。

運算子 - 賦值運算子(=, +=, *=, 等等),布林運算子(&&, ||, !),比較運算子(<,>, <=, >=, ==, !=),以及基本算術運算子(+, -, *, /, %)在PHP中的行為與在C中相同。

控制結構 - 基本控制結構(if, switch, while, for)的行為與在C中相同,包括支援break和continue。一個顯著的區別是PHP中的switch可以接受字串作為case識別符號。

PHP還具有foreach迴圈結構,該結構遍歷集合,例如陣列。

函式名 - 當您仔細閱讀文件時,您會看到許多函式名似乎與C函式相同。

C和PHP之間的區別

美元符號 - 所有變數名都以一個前導$為字首。變數不需要在賦值之前宣告,並且它們沒有內在型別。PHP是一種動態型別語言,而C是一種靜態型別語言。

型別 - PHP只有兩種數值型別:整數(對應於C中的long)和雙精度浮點數(對應於C中的double)。在PHP中,float與double同義。字串的長度是任意的。PHP中沒有單獨的char型別,就像C中那樣。

型別轉換 - C是一種強型別語言,因為變數的型別必須在使用之前宣告,並且型別在編譯時進行檢查。另一方面,PHP是一種弱型別語言,型別在編譯時不進行檢查,並且型別錯誤通常也不會在執行時發生。相反,變數和值會根據需要自動在型別之間轉換。

陣列 - 陣列的語法表面上與C的陣列語法類似,但它們的實現完全不同。在C中,陣列是相似資料型別的集合。在PHP陣列中,專案可以是不同型別的。PHP陣列實際上是關聯陣列或雜湊表,索引可以是數字或字串。它們不需要預先宣告或分配。

沒有結構體型別 - C中的struct關鍵字用於定義新的資料型別。PHP中沒有struct關鍵字或其等價物,部分原因是陣列和物件型別一起使其變得不必要。PHP陣列的元素不必具有一致的型別。

沒有指標 - 指標是C中的一個重要概念。PHP中沒有指標,儘管無型別的變數扮演著類似的角色。與C不同,PHP支援變數引用。您還可以模擬函式指標到某種程度,因為函式名可以儲存在變數中,並透過使用變數而不是文字名稱來呼叫。

沒有原型 - 函式不需要在其實現定義之前宣告,只要定義可以在當前程式碼檔案或包含檔案中找到即可。相反,C函式必須在使用之前定義。

沒有main() - 在C程式中,main()函式是入口點,無論它在程式碼中的哪個位置。另一方面,PHP程式從指令碼中的第一條語句開始執行。

記憶體管理 - PHP引擎實際上是一個垃圾收集環境(引用計數),在小型指令碼中無需進行任何釋放。您可以隨意分配新的結構——例如新的字串和物件例項。在PHP5中,可以為物件定義解構函式,但是沒有像C/C++中的free或delete關鍵字。當最後一個對物件的引用消失之前,在記憶體被回收之前,會呼叫解構函式。

編譯和連結 - PHP是一種解釋型語言。因此,不會建立PHP指令碼的編譯版本。C程式首先編譯以獲得目的碼,然後將其連結到所需的庫以構建可執行檔案。PHP指令碼沒有單獨的編譯步驟。PHP指令碼不能轉換為自執行檔案。

寬容性 - 一般來說,PHP比C(尤其是在其型別系統中)更寬容,因此它會讓您擺脫新型錯誤。意外結果比錯誤更常見。

面向Perl開發人員的PHP

Perl是一種動態型別、高階和通用的程式語言。通常認為Perl是Practical Extraction and Reporting Language的首字母縮寫。另一方面,PHP也是一種通用的指令碼語言。最初PHP是Personal Home Page的縮寫,但如今它已被認為是遞迴縮寫“PHP: Hypertext Preprocessor”。

本章列出了PHP和Perl之間的一些主要異同。這將幫助Perl開發人員快速理解PHP並避免常見錯誤。

Perl和PHP之間的相似之處

Perl和PHP都是指令碼語言。它們不用於在執行之前構建本機獨立可執行檔案。

早期的PHP版本受到Perl的啟發。PHP的基本語法與Perl非常相似。兩者都與C共享許多語法特性。它們的程式碼不區分空格,每個語句都以分號結尾。

PHP和Perl都使用花括號將多個語句組織成單個塊。在兩種情況下,函式呼叫都以函式名稱開頭,後跟括在括號中並用逗號分隔的實際引數。

  • PHP中的所有變數都像Perl中的標量變數:前面帶美元符號 ($) 的名稱。

  • 由於這兩種語言都是動態型別的,因此您不需要在使用PHP和Perl變數之前宣告其型別。

  • 在PHP中,與Perl一樣,變數除了它們當前持有的值之外沒有內在型別。您可以將數字或字串儲存在相同型別的變數中。

  • PHP和Perl都比單引號字串('string')對雙引號字串("string")進行更多的解釋。

Perl和PHP之間的區別

PHP可以嵌入HTML中。儘管可以從命令列執行PHP指令碼,但它更常用作Web伺服器上的伺服器端指令碼語言,並用於生成網頁。

如果您習慣於使用Perl編寫CGI指令碼,PHP中的主要區別在於您不再需要使用print或heredoc語句顯式列印大塊靜態HTML,而可以直接在PHP程式碼塊之外編寫HTML本身。

沒有@或%變數 - PHP只有一種變數,它以美元符號 ($) 開頭。語言中的任何資料型別都可以儲存在這些變數中,無論是標量還是複合型別。在Perl中,陣列變數以@符號為字首。此外,雜湊變數以%符號為字首。

與Perl不同,PHP有一種名為陣列的單一資料型別,它可以是索引陣列關聯陣列,這類似於Perl中的雜湊

PHP 中的函式呼叫看起來非常類似於PERL 中的子程式呼叫。另一方面,PHP 中的函式定義通常需要某種形式引數列表,就像 C 或 Java 中那樣,而 PERL 中則不是這樣。

PERL 中變數的作用域預設情況下是全域性的。這意味著頂級變數在子程式內是可見的。通常,這會導致在函式之間濫用全域性變數。在 PHP 中,函式定義內變數的作用域預設情況下是區域性的。

PHP 本身沒有模組系統。在 PHP 中,普通程式碼檔案和用作匯入庫的程式碼檔案之間沒有真正的區別。

Break 和 continue 而不是 next 和 last —— PHP 更像 C 語言,使用 break 和 continue,而不是像 PERL 中那樣使用 next 和 last 語句。

沒有 elsif —— 一個小的拼寫差異:Perl 的 elsif 是 PHP 的 elseif。

除了 Perl 風格的 (#)單行註釋之外,PHP 還提供 C 風格的多行註釋 (/* comment */) 和 Java 風格的單行註釋 (// comment)。

正則表示式——PHP 本身沒有針對正則表示式的特定語法,但在其“Perl 相容”的正則表示式函式中具有大部分相同的功能。

PHP – 框架

PHP 生態系統有很多 Web 框架。一些流行的 PHP Web 框架包括 Laravel、Yii、CakePHP 等。雖然可以使用核心 PHP 來構建 Web 應用程式,但開發人員越來越傾向於使用 Web 框架來進行快速應用程式開發。

什麼是軟體框架?

在計算機程式設計中,軟體框架是一組庫和類,它們提供通用功能,允許開發人員更多地關注應用程式邏輯,而不是編寫例行但繁瑣的低階過程的程式碼。

框架提供了一個可重用的軟體環境,可以快速構建一個最小的可執行模板應用程式。開發人員可以修改這些模組以實現其他功能。

每個框架都是為了幫助開發人員構建特定型別的應用程式而構建的。例如,Web 框架(有時也稱為“Web 應用程式框架”)用於開發 Web 應用程式,包括 Web 服務、Web 資源和 Web API。

在本章中,讓我們簡要概述一些流行的 PHP 框架。

FuelPHP

FuelPHP (https://fuelphp.com/) 基於模型-檢視-控制器 (MVC) 並具有創新的外掛。FuelPHP 支援基於路由的理論,您可以在其中直接路由到更接近輸入 URI 的位置,使閉包成為控制器並賦予其進一步執行的控制權。

PHP Frameworks 1

CakePHP

CakePHP (https://cakephp.org/) 是一個構建簡單而強大的 Web 應用程式的絕佳資源。PHP 中的一些內建強大功能包括輸入驗證和 SQL 注入防護,可確保您的應用程式安全可靠。

PHP Frameworks 2

FlightPHP

FlightPHP (https://flightphp.com/) 對建立 RESTful Web 服務非常有幫助,並且它是 MIT 許可的。

PHP Frameworks 3

Symfony

Symfony 適用於高階專業開發人員,用於使用 PHP 元件(例如 Drupal、PHPBB、Laravel、eX、OROCRM 和 Piwik)構建網站。

PHP Frameworks 4

Yii Framework

Yii Framework (https://www.yiiframework.com/) 基於 Web 2.0,具有高階安全性。它包括輸入驗證、輸出過濾和 SQL 注入防護。

PHP Frameworks 5

Laravel

Laravel (https://laravel.club.tw/) 最適用於 RESTful 路由和輕量級刀片模板引擎。Laravel 集成了經過良好測試和可靠程式碼的一些強大元件。

PHP Frameworks 6

Zend

Zend (https://framework.zend.com/) 是一個用於執行高階 Web 應用程式的現代框架。它基於加密和安全的編碼工具。Zend Framework 是一個包含 5.7 億多次安裝的專業 PHP 包集合。

它可以用於使用 PHP 5.6+ 開發 Web 應用程式和服務,並使用廣泛的語言特性提供 100% 面向物件的程式碼。

PHP Frameworks 7

CodeIgniter

CodeIgniter 對於需要簡單優雅的工具包來建立創新型 Web 應用程式的開發人員來說,易於開發小型應用程式。

PHP Frameworks 8

Phalcon PHP

Phalcon (https://phalcon.io/en-us) 是一個基於 MVC 並集成了創新架構以實現更快效能的 PHP 框架。

PHP Frameworks 9

PHPixie

PHPixie (https://phpixie.com/) 基於 MVC,旨在快速可靠地開發網站。

PHP Frameworks 10

Agavi

Agavi 是一個功能強大且可擴充套件的 PHP5 應用程式框架,它遵循 MVC 模型。Agavi 可以幫助 PHP 開發人員編寫簡潔易維護的程式碼。

核心 PHP 與框架

PHP 是迄今為止最流行的用於 Web 應用程式開發的伺服器端程式語言,幾乎 75% 的網站使用 PHP 的核心形式或可用的 PHP 框架之一。為了在使用“核心 PHP”還是框架進行 Web 開發之間做出選擇,我們需要了解兩者的優缺點。

簡單來說,僅使用核心 PHP 開發 Web 應用程式就像手動解決數學問題一樣,需要在紙上寫下每一個步驟。另一方面,使用框架類似於使用計算器等工具來解決問題。正如計算器一樣,框架是快速應用程式開發的有用工具。

核心 PHP 與框架——優缺點

Web 框架,尤其是 PHP 框架,是一個或多個 PHP 庫和類的集合。它提供通用功能,允許開發人員更多地關注應用程式邏輯,而不是從頭編寫程式碼。它提供可重用的軟體環境,可以快速構建最小的可執行模板應用程式。

僅用核心 PHP 開發 Web 應用程式有其自身的優點和缺點——

  • 它使開發人員能夠更好地控制和靈活操作。

  • 同時,對於僅使用核心 PHP 開發的大型應用程式而言,可能會變得笨拙、難以管理和維護。

現在,讓我們來看一下使用 PHP 框架的優缺點——

  • 像 Symfony、Laravel 或 Yii 這樣的 PHP 框架為 Web 應用程式開發提供了一種更標準化的方法。透過框架處理大部分例行和重複的部分,開發人員可以更多地關注應用程式邏輯。因此,在除錯上浪費的時間更少。

  • 另一方面,與核心 PHP 相比,框架的靈活性較差。框架可以隨時提供應用程式的骨架模板,開發人員只需在框架定義的範圍內自定義功能即可。

MVC 架構

大多數 Web 應用程式框架都採用MVC(模型、檢視和控制器)架構,透過將邏輯與樣式分離,使編寫高質量、健壯的程式碼變得容易得多。

PHP Core PHP Vs Frameworks

如果您希望將核心 PHP 功能用於應用程式開發,您可以自由地採用面向物件方法或模組化方法,無論哪種方法適合您。

內建安全措施

PHP 框架提供內建的安全措施,可以將其整合到 Web 應用程式中。

  • 如果您選擇使用核心 PHP 開發應用程式,則必須明確提供安全措施。

  • 但是,大多數框架都有一些外部依賴項,這可能會使應用程式比自包含的核心 PHP 應用程式更容易受到攻擊。

與核心 PHP 應用程式相比,基於框架的應用程式在效能方面可能會稍慢一些,特別是對於較小的應用程式。

比較:核心 PHP 與框架

兩者之間的比較可以總結如下——

  • 對於小型應用程式,核心 PHP 比框架更可取。

  • 框架提供快速開發和程式碼重用。

  • 框架的靈活性較差。

  • 使用核心 PHP 功能,開發人員可以完全控制。

  • 對於大型應用程式,MVC 架構很有幫助。

  • 框架提供整合的授權和身份驗證支援。在核心 PHP 應用程式中,需要明確定義安全規則。

PHP – 設計模式

在軟體工程理論中,“設計模式”一詞通常是指可重用的解決方案,可以用作開發應用程式的模板,以解決常見問題。您可以將軟體設計模式視為開發軟體解決方案時的正式最佳實踐。

大多數標準設計模式都可以非常有效地應用於 PHP 應用程式的開發中。在本章中,我們將學習如何在開發 PHP 應用程式中應用一些流行的設計模式。

單例模式

當您希望將某個類的物件的例項化限制為只有一個例項時,單例設計模式非常有用。“單例模式”這個名稱來自數學中的單例概念。單例模式確保只有一個例項,並在整個應用程式中對其進行全域性訪問。

單例模式的典型應用是建立資料庫連線物件,該物件必須在應用程式的生命週期中建立一次。

示例

在以下程式碼中,DataBaseConnector 類只能例項化一次,否則將發出禁止重複物件的提示。

<?php
   class DataBaseConnector {				
      private static $obj;				
      private final function __construct() {
         echo __CLASS__ . " object created for first time ". PHP_EOL;
      }
      public static function getConnect() {
         if (!isset(self::$obj)) {
            self::$obj = new DataBaseConnector();
            return self::$obj;
         } else {
            echo "connection object could not be created again" . PHP_EOL;
         }
      }
   }

   $obj1 = DataBaseConnector::getConnect();
   $obj2 = DataBaseConnector::getConnect();

   var_dump($obj1 == $obj2);
?>

它將產生以下輸出:

DataBaseConnector object created for first time 
connection object could not be created again
bool(false)

工廠模式

這是最常用的設計模式之一。在此模式中,您不會直接宣告所需類的物件,而是提供另一個類的靜態方法來建立所需的物件。

示例

以下示例演示了工廠設計模式的工作原理——

<?php
   class Automobile {
      private $bikeMake;
      private $bikeModel;

      public function __construct($make, $model) {
         $this->bikeMake = $make;
         $this->bikeModel = $model;
      }

      public function getMakeAndModel() {
         return $this->bikeMake . ' ' . $this->bikeModel;
      }
   }

   class AutomobileFactory {
      public static function create($make, $model) {
         return new Automobile($make, $model);
      }
   }

   $pulsar = AutomobileFactory::create('ktm', 'Pulsar');
   print_r($pulsar->getMakeAndModel());
?>

它將產生以下輸出:

ktm Pulsar

策略模式

策略模式建議一種方法,在該方法中,您可以封裝特定系列的演算法,從而允許負責例項化特定演算法的客戶端類。實現該模式的類不知道實際的實現。

示例

這是一段演示策略模式用法的程式碼。我們有一個介面,其 case() 方法由兩個不同的類以不同的方式實現。testdata 類的物件透過其自身的 process() 方法間接呼叫相應的 case() 方法。

<?php
   interface example {
      public function case($str);
   }

   class ucase implements example {
      public function case($str) {
         return strtoupper($str);
      } 
   }

   class lcase implements example {
      public function case($str) {
         return strtolower($str);
      }
   }

   class testdata {
      private $data;

      public function __construct($input) {
         $this->data = $input;
      }
      public function process(example $type) {
         return $this->data = $type->case($this->data);
      }
   }
   $str = "hello";
   $obj = new testdata($str);
   echo $obj->process(new ucase) . PHP_EOL;  
   $str = "HELLO";
   echo $obj->process(new lcase);
?>

它將產生以下輸出

HELLO
Hello

MVC 設計模式

MVC(代表模型、檢視和控制器)是一種非常流行的軟體架構模式。大多數 PHP 網路(例如 Laravel、Symfony 等)都實現了 MVC 架構。

應用程式中每一層角色的分離如下——

  • 模型——指的是資料結構。在這種情況下,指的是資料庫。

  • 檢視——指的是使用者介面。HTML 和 CSS。

  • 控制器——進行處理的“中間人”。接受來自檢視的輸入,並與模型一起工作。不言而喻,PHP 指令碼和庫本身。

檢視充當 GUI,模型充當後端,控制器充當介面卡。在這裡,三個部分相互連線。它將在彼此之間傳遞資料和訪問資料。

示例

讓我們在下面的示例中使用純PHP、JavaScript和HTML實現MVC設計模式。

應用程式的表示層是view.php,它渲染一個HTML表單。使用者將資料提交給控制器指令碼。控制器返回的結果透過一些JavaScript在網頁上呈現。

view.php

<!DOCTYPE html>
<html>
<head>
   <title>View (User Interface)</title>
   <link rel="stylesheet" href="style.css">
</head>
<body>
   <form id="mysearch" action="controller.php" method="POST">
      <input type="text" id = "nm" name="search" required>
      <input type="submit" value="Search">
   </form>
   <div id="results"></div>
   <script>
      let results = document.getElementById("results");
      results.innerHTML = "";
   </script>
   <?php
      session_start();
      if (isset($_SESSION['result'])) {
         $arr=$_SESSION['result'];

         foreach ($arr as $obj) {?>
            <script>
               results.innerHTML += "<div><?php echo $obj['id'] . "-" . 
			      $obj['name'] . "</div>"; ?>";
            </script>
            <?php
         }
      }
   ?>
</body>
</html>

控制器指令碼需要model.php,並使用資料庫物件,呼叫select方法從資料庫中提取資料。結果儲存在當前會話中,以便可以在檢視頁面訪問它。

controller.php

<?php
   session_start();
   require "model.php";
   $results = $_DB->select(
      "SELECT * FROM `users` WHERE `name` LIKE ?",
      ["%{$_POST["search"]}%"]
   );
   $_SESSION['search'] = $_POST['search'];
   $_SESSION['result'] = $results;
   Header("Location: view.php", true);
?>

應用程式的模型層在“model.php”中編碼。它使用PDO擴充套件連線名為mydb的mysql資料庫。

model.php

<?php
   class DB {
      public $error = "";
      private $pdo = null;
      private $stmt = null;
      var $dsn="localhost";  
      var $dbName="myDB";  
      var $username="root";       
      var $password=""; 
      function __construct () {
         $this->pdo = new PDO("mysql:host=$this->dsn;dbname=$this->
		    dbName",$this->username,$this->password); 
      }
      function __destruct () {
         if ($this->stmt!==null) { $this->stmt = null; }
         if ($this->pdo!==null) { $this->pdo = null; }
      }
      function select ($sql, $data=null) {
         $this->stmt = $this->pdo->prepare($sql);
         $this->stmt->execute($data); 
         return $this->stmt->fetchAll();
      }
   }
   $_DB = new DB();
?>

後端mydb資料庫必須有一個包含ID和NAME欄位的使用者表。

-- Table structure for table `users`
--
CREATE TABLE `users` (
   `id` bigint(20) NOT NULL,
   `name` varchar(255) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;

--
-- Dumping data for table `users`
--
INSERT INTO `users` (`id`, `name`) VALUES
(21, 'Ahmad Shaikh'),
(24, 'Akshay Wadkar'),
(26, 'Bridget Wooten'),
(10, 'Coby Kelleigh'),
(20, 'Dashan Shah'),
(12, 'Elizabeth Taylor'),
(41, 'Issac Newton'),
(34, 'Julia Roberts'),
(31, 'Junior Mahmood'),
(32, 'Kailas Bende'),
(47, 'Karan Sharma'),
(16, 'Kenneth Sanders'),
(28, 'Kirstie Thomas'),
(33, 'Lawrence Murphy'),
(14, 'Leah Shan'),
(51, 'Marcus Best'),
(29, 'Maya Pande'),
(50, 'Nathaniel Khan'),
(6, 'Richard Breann'),
(54, 'Rowan Avalos'),
(3, 'Rusty Terry'),
(37, 'Sacha Gross'),
(27, 'Sally Castillo'),
(11, 'Sarah Sanders'),
(18, 'Seth Sonnel'),
(38, 'Shannon Peterson'),
(25, 'Shayan Clements'),
(49, 'Shoaib Vickers'),
(43, 'Simran Kaur'),
(35, 'Sulaiman Gilmour'),
(44, 'Taran Morin'),
(48, 'Taran Morin'),
(22, 'Thelma Kim'),
(8, 'Tillie Sharalyn'),
(36, 'Virgil Collier');

在瀏覽器中訪問“https:///view.php”啟動應用程式。輸入與具有所需字母的名稱相對應的搜尋詞。

PHP Design Patterns

PHP – 過濾器

在PHP應用程式中處理客戶端請求形式接收到的輸入資料之前,驗證輸入資料非常重要。為了執行輸入驗證,PHP中的過濾器擴充套件提供了許多過濾器函式,由預定義的過濾器常量和標誌支援。PHP庫的過濾器擴充套件還有助於清理透過GET或POST方法接收到的輸入。

過濾器擴充套件是一個強大的功能,有助於防止安全漏洞,例如SQL注入和跨站點指令碼。擴充套件有兩種型別的過濾器:

驗證過濾器

驗證過濾器檢查資料是否符合特定條件。例如,您希望確保使用者已在HTML表單中正確輸入電子郵件欄位。FILTER_VALIDATE_EMAIL將確定資料是否為有效的電子郵件地址。但是,驗證過濾器不會更改資料本身。

清理過濾器

清理是指從輸入中刪除不需要的字元的過程。因此,它可能會透過刪除不需要的字元來更改資料。例如,傳入FILTER_SANITIZE_EMAIL將刪除電子郵件地址中不應包含的不合適的字元,而無需執行驗證。

過濾器標誌

PHP中的過濾器擴充套件定義了許多過濾器標誌,如下所示:

序號 ID & 描述
1

FILTER_FLAG_STRIP_LOW

刪除數值<32的字元。

2

FILTER_FLAG_STRIP_HIGH

刪除數值>127的字元。

3

FILTER_FLAG_STRIP_BACKTICK

刪除反引號字元。

4

FILTER_FLAG_ALLOW_FRACTION

允許使用句點(.)作為數字的小數分隔符。

5

FILTER_FLAG_ALLOW_THOUSAND

允許使用逗號(,)作為數字的千位分隔符。

6

FILTER_FLAG_ALLOW_SCIENTIFIC

允許使用e或E表示數字的科學計數法。

7

FILTER_FLAG_NO_ENCODE_QUOTES

如果存在此標誌,則不會編碼單引號(')和雙引號(")。

8

FILTER_FLAG_ENCODE_LOW

編碼所有數值<32的字元。

9

FILTER_FLAG_ENCODE_HIGH

編碼所有數值>127的字元。

10

FILTER_FLAG_ENCODE_AMP

編碼與符號(&)。

11

FILTER_NULL_ON_FAILURE

對於無法識別的值,返回null

12

FILTER_FLAG_ALLOW_OCTAL

將以零(0)開頭的輸入視為八進位制數。

13

FILTER_FLAG_ALLOW_HEX

將以0x或0X開頭的輸入視為十六進位制數。

14

FILTER_FLAG_EMAIL_UNICODE

允許電子郵件地址的本地部分包含Unicode字元。

15

FILTER_FLAG_IPV4

允許IP地址為IPv4格式。

16

FILTER_FLAG_IPV6

允許IP地址為IPv6格式。

17

FILTER_FLAG_NO_PRIV_RANGE

對於以下專用IPv4範圍,驗證失敗:10.0.0.0/8、172.16.0.0/12和192.168.0.0/16。

18

FILTER_FLAG_NO_RES_RANGE

對於以下保留的IPv4範圍,驗證失敗:0.0.0.0/8、169.254.0.0/16、127.0.0.0/8和240.0.0.0/4。

對於以下保留的IPv6範圍,驗證失敗:::1/128、::/128、::ffff:0:0/96和fe80::/10。

19

FILTER_FLAG_GLOBAL_RANGE

對於非全域性IPv4/IPv6範圍,驗證失敗。

20

FILTER_FLAG_SCHEME_REQUIRED

要求URL包含方案部分。

21

FILTER_FLAG_HOST_REQUIRED

要求URL包含主機部分。

22

FILTER_FLAG_PATH_REQUIRED

要求URL包含路徑部分。

23

FILTER_FLAG_QUERY_REQUIRED

要求URL包含查詢字串。

24

FILTER_REQUIRE_SCALAR

要求值為標量。

25

FILTER_REQUIRE_ARRAY

要求值為陣列。

26

FILTER_FORCE_ARRAY

如果值為標量,則將其視為只有一個標量值作為元素的陣列。

過濾器函式

過濾器擴充套件包含以下過濾器函式

序號 ID & 描述
1

filter_has_var()

檢查指定型別的變數是否存在

2

filter_id()

返回屬於命名過濾器的過濾器ID

3

filter_input_array()

獲取外部變數並對其進行可選過濾

4

filter_input ()

按名稱獲取特定的外部變數並對其進行過濾

5

filter_list()

返回所有支援的過濾器的列表

6

filter_var_array()

獲取多個變數並對其進行可選過濾

7

filter_var()

使用指定的過濾器過濾變數

預定義常量

上述函式使用一個名為input_type的引數,它是預定義的列舉常量之一,表示輸入是如何為過濾目的提供給PHP指令碼的。

常量 型別
INPUT_POST (int)

POST變數

INPUT_GET (int)

GET變數

INPUT_COOKIE (int)

COOKIE變數

INPUT_ENV (int)

ENV變數

INPUT_SERVER (int) SERVER變數
INPUT_SESSION (int) SESSION變數
INPUT_REQUEST (int) REQUEST變數

filter_has_var()函式

filter_has_var()函式檢查指定型別的變數是否存在。

filter_has_var(int $input_type, string $var_name): bool

input_type是預定義常量INPUT_GET、INPUT_POST、INPUT_COOKIE、INPUT_SERVER或INPUT_ENV之一;而var_name引數是要檢查的變數的名稱。函式在成功時返回true,失敗時返回false。

示例

訪問XAMPP伺服器上的以下PHP指令碼。

<?php
   if (!filter_has_var(INPUT_GET, "email")) {
      echo("Email not found");
   } else {
      echo("Email found");
   }
?>

它將產生以下輸出

訪問https:///hello.php?email=abc@example.com

Email found

filter_input()函式

filter_input()函式獲取特定外部變數的名稱並根據應用的過濾器常量對其進行過濾。

filter_input(
   int $type,
   string $var_name,
   int $filter = FILTER_DEFAULT,
   array|int $options = 0
): mixed

type引數是常量INPUT_GET、INPUT_POST、INPUT_COOKIE、INPUT_SERVER或INPUT_ENV之一。第二個引數是var_name,要獲取的變數的名稱。您可以使用要應用的過濾器。使用任何預定義的過濾器標誌。如果省略,將使用FILTER_DEFAULT。

函式在成功時返回請求變數的值,如果過濾器失敗則返回false,如果var_name變數未設定則返回null。

示例

請看以下示例:

<?php
   if (!filter_input(INPUT_GET, "email", FILTER_VALIDATE_EMAIL)) {
      echo("Email is not valid");
   } else {
      echo("Email is valid");
   }
?>

它將產生以下輸出

如果您使用URLhttps:///hello.php?email=abc@example.com

Email is valid

如果URL是https:///hello.php?email=a b c@example.com

Email is not valid

您還可以使用INPUT_POST型別來驗證透過POST方法接收到的輸入:

<?php
   if (!filter_input(INPUT_POST, "email", FILTER_VALIDATE_EMAIL)) {
      echo("Email is not valid");
   } else {
      echo("Email is valid");
   }
?>

要使用POST請求傳遞資料,請開啟命令提示符,並使用以下CURL命令

curl -X POST -d "{\"email\": \"a@b.com\"}" https:///hello.php

filter_list()函式

filter_list()函式返回所有支援的過濾器的列表。

filter_list(): array

示例

該函式返回所有支援的過濾器的名稱陣列,如果沒有此類過濾器,則返回空陣列。

<?php
   print_r(filter_list());
?>

它將產生以下輸出

Array
(
   [0] => int
   [1] => boolean
   [2] => float
   [3] => validate_regexp
   [4] => validate_domain
   [5] => validate_url
   [6] => validate_email
   [7] => validate_ip
   [8] => validate_mac
   [9] => string
   [10] => stripped
   [11] => encoded
   [12] => special_chars
   [13] => full_special_chars
   [14] => unsafe_raw
   [15] => email
   [16] => url
   [17] => number_int
   [18] => number_float
   [19] => add_slashes
   [20] => callback
)

filter_input_array()函式

filter_input_array()獲取外部變數並對其進行可選過濾。

filter_input_array(int $type, array|int $options = FILTER_DEFAULT, 
   bool $add_empty = true): array|false|null

此函式可用於檢索許多值,而無需重複呼叫filter_input()。

type引數是INPUT_GET、INPUT_POST、INPUT_COOKIE、INPUT_SERVER或INPUT_ENV之一。

options引數是一個定義引數的陣列。有效的鍵是包含變數名的字串,有效的值是過濾器型別,或者是一個可選地指定過濾器、標誌和選項的陣列。此引數也可以是一個包含過濾器常量的整數。然後,輸入陣列中的所有值都將透過此過濾器進行過濾。

該函式在成功時返回一個包含請求變數值的陣列。如果type指定的輸入陣列未填充,則如果未給出FILTER_NULL_ON_FAILURE標誌,則函式返回null,否則返回false。對於其他錯誤,返回false。

示例

要在HTTP請求中包含陣列,我們在“hello.html”中使用以下HTML表單,並透過POST方法傳送。

<!DOCTYPE html>
<html>
<body>
   <h1>Filter Input Array</h1>
   <form action="hello.php" method="POST">
      <p><label for="email">Enter your email:</label>
      <input type="text" id="email" name="email"></p>
      <p><label for="age">Enter your age<label>
      <input type = "text" id="age" name="age"></p>
      <input type="submit">
   </form>
</body>
</html>

驗證輸入陣列的PHP指令碼如下:

<?php
   $filters = array (
      "age" => array ("filter"=>FILTER_VALIDATE_INT, 	
         "options"=>array("min_range"=>20,"max_range"=>40) ),
      "email" => FILTER_VALIDATE_EMAIL
   );
   print_r(filter_input_array(INPUT_POST, $filters));
?>

開啟HTML表單並輸入30作為年齡,abc@example.com作為電子郵件,結果將是一個數組,驗證這兩個輸入:

Array ( [age] => 30 [email] => abc@example.com )

嘗試輸入無效的輸入,例如“age=15”。輸出陣列將顯示age鍵的空值。

Array ( [age] => [email] => abc@example.com )

PHP – JSON

PHP的標準發行版預設情況下啟用了JSON支援。PHP擴充套件實現了JavaScript物件表示法(JSON)資料交換格式。PHP解析器中的JSON擴充套件處理JSON資料。

JSON(JavaScript物件表示法)是一種輕量級、基於文字的、與語言無關的資料交換格式。JSON定義了一小組用於結構化資料的可移植表示的格式規則。它是一種基於文字的資料格式,易於人和機器讀取。

PHP 5.2及更高版本中的JSON擴充套件提供了一些預定義常量、JSON相關函式以及JsonException類。

PHP JSON函式

PHP具有以下JSON函式:

json_encode()

此函式返回一個包含提供的值的JSON表示的字串。如果引數是陣列或物件,它將被遞迴地序列化。

json_encode(mixed $value, int $flags = 0, int $depth = 512): string|false

json_decode()

此函式獲取JSON編碼的字串並將其轉換為PHP值。

json_decode(
   string $json,
   ?bool $associative = null,
   int $depth = 512,
   int $flags = 0
): mixed

當此函式的關聯引數為true時,JSON物件將作為關聯陣列返回;當為false時,JSON物件將作為物件返回。

編碼/解碼操作受提供的標誌影響。預定義常量及其整數值如下:

預定義常量
JSON_HEX_TAG 1
JSON_HEX_AMP 2
JSON_HEX_APOS 4
JSON_HEX_QUOT 8
JSON_FORCE_OBJECT 16
JSON_NUMERIC_CHECK 32
JSON_UNESCAPED_SLASHES 64
JSON_PRETTY_PRINT 128
JSON_UNESCAPED_UNICODE 256

json_last_error_msg()

此函式返回上次json_encode()或json_decode()呼叫的錯誤字串。

json_last_error_msg(): string

如果沒有發生錯誤,則返回“無錯誤”訊息。

json_last_error()

此函式返回一個整數。

json_last_error(): int

該函式返回一個整數,對應於以下常量之一:

序號 常量與含義
1

JSON_ERROR_NONE

未發生錯誤

2

JSON_ERROR_DEPTH

已超出最大堆疊深度

3

JSON_ERROR_STATE_MISMATCH

無效或格式錯誤的JSON

4

JSON_ERROR_CTRL_CHAR

控制字元錯誤,可能編碼不正確

5

JSON_ERROR_SYNTAX

語法錯誤

6

JSON_ERROR_UTF8

格式錯誤的UTF-8字元,可能編碼不正確

7

JSON_ERROR_RECURSION

待編碼值中存在一個或多個遞迴引用

8

JSON_ERROR_INF_OR_NAN

待編碼值中存在一個或多個NANINF

9 JSON_ERROR_UNSUPPORTED_TYPE

給定了一個無法編碼的型別的值

10

JSON_ERROR_INVALID_PROPERTY_NAME

給定了一個無法編碼的屬性名

11

JSON_ERROR_UTF16

UTF-16 字元格式錯誤,可能編碼錯誤

示例

下面的 PHP 程式碼將給定的陣列編碼為 JSON 表示形式,並將 JSON 字串解碼回 PHP 陣列。

<?php
   $arr = array('a' => 1, 'b' => 2, 'c' => 3, 'd' => 4, 'e' => 5);
   $encoded = json_encode($arr);
   echo "The initial array: " . PHP_EOL;
   var_dump($arr);
   echo "Encoded JSON: $encoded" . PHP_EOL;

   $decoded = json_decode($encoded);
   echo "Array obtained after decoding: " . PHP_EOL;
   var_dump($decoded);
?>

它將產生以下輸出

The initial array: 
array(5) {
   ["a"]=>
   int(1)
   ["b"]=>
   int(2)
   ["c"]=>
   int(3)
   ["d"]=>
   int(4)
   ["e"]=>
   int(5)
}
Encoded JSON: {"a":1,"b":2,"c":3,"d":4,"e":5}
Array obtained after decoding: 
object(stdClass)#1 (5) {
   ["a"]=>
   int(1)
   ["b"]=>
   int(2)
   ["c"]=>
   int(3)
   ["d"]=>
   int(4)
   ["e"]=>
   int(5)
}

PHP – 異常

在 PHP 7 之前,PHP 解析器用於響應各種條件報告錯誤。每個錯誤都屬於某種預定義型別。PHP 7 改變了錯誤報告機制。大多數錯誤不再透過傳統的錯誤報告方式報告,而是透過丟擲異常來報告。

PHP 中的異常處理機制與許多其他語言類似,並使用try、catch、throwfinally關鍵字實現。

Throwable 介面

PHP 中的異常實現了Throwable 介面。Throwable 介面作為任何可以透過 throw 語句丟擲的物件的基類,包括 Error 和 Exception 物件。

使用者定義的類不能直接實現 Throwable 介面。相反,要宣告使用者定義的異常類,必須擴充套件Exception 類

包含潛在異常的 PHP 程式碼被包圍在一個try塊中。如果發現異常,則會丟擲一個異常物件,以便捕獲潛在的異常。每個try塊必須至少對應一個catchfinally塊。此外,可能有多個 catch/finally 塊對應於一個try塊。

try { 

   // throw errors in the try-block 
   // if an error occurs we can throw an exception
   throw new Exception('this is an error.'); 
}
catch(Exception $e) { 

   // catch the throws in the catch-block 
   // do something with the exception object, eg.  
   // display its message
   echo 'Error message: ' .$e->getMessage(); 
}

如果丟擲異常且沒有catch塊,則異常將“冒泡”直到找到匹配的catch塊。如果呼叫堆疊一直展開到全域性範圍而沒有遇到匹配的 catch 塊,則將呼叫全域性異常處理程式(如果已設定),否則程式將以致命錯誤終止。

set_exception_handler

如果異常未在 try/catch 塊中捕獲,此函式將設定預設的異常處理程式。回撥執行後,程式執行將停止。

set_exception_handler(?callable $callback): ?callable

$callback 引數是要在發生未捕獲異常時呼叫的函式的名稱。必須在呼叫 set_exception_handler() 之前定義此函式。此處理程式函式需要接受一個引數,該引數將是丟擲的異常物件。

該函式返回先前定義的異常處理程式的名稱,或錯誤時返回 NULL。如果未定義先前的處理程式,則也返回 NULL。

示例

請看以下示例:

<?php
   function handler($ex) {
      echo "Uncaught exception is : " , $ex->getMessage(), "\n";
   }

   set_exception_handler('handler');
   throw new Exception('Not Found Exception');
   echo "not included Executed\n";
?>

它將產生以下輸出

Uncaught exception is : Not Found Exception

SPL 異常

標準 PHP 庫包含預定義的異常:

序號 預定義異常
1

LogicException

表示程式邏輯錯誤的異常。

2

BadFunctionCallException

如果回撥引用未定義的函式或缺少某些引數,則丟擲此異常。

3

BadMethodCallException

如果回撥引用未定義的方法或缺少某些引數,則丟擲此異常。

4

DomainException

如果值不符合定義的有效資料域,則丟擲此異常。

5

InvalidArgumentException

如果引數不是預期型別,則丟擲此異常。

6

LengthException

如果長度無效,則丟擲此異常。

7

OutOfRangeException

請求非法索引時丟擲此異常。

8

RuntimeException

如果發生只能在執行時發現的錯誤,則丟擲此異常。

9

OutOfBoundsException

如果值不是有效的鍵,則丟擲此異常。

10

OverflowException

向已滿容器新增元素時丟擲此異常。

11

RangeException

丟擲此異常以指示程式執行期間的範圍錯誤。除下溢/上溢之外的算術錯誤。

12

UnderflowException

對空容器執行無效操作(例如刪除元素)時丟擲此異常。

13

UnexpectedValueException

如果值與一組值不匹配,則丟擲此異常。

使用者定義的異常

您可以定義一個擴充套件基 Exception 類的自定義異常類。以下指令碼定義了一個名為 myException 的自定義異常類。如果 $num 的值小於 0 或大於 100,則會丟擲此型別的異常。

示例

Exception 類的 getMessage() 方法返回錯誤訊息,getLine() 方法返回出現異常的程式碼行。

<?php
   class myException extends Exception {
      function message() {
         return "error : ". $this->getMessage(). "in line no". $this->getLine();
      }
   }
   $num=125;
   try {
      if ($num>100 || $num<0)
      throw new myException("$num is invalid number");
      else
      echo "$num is a valid number";
   }
   catch (myException $m) {
      echo $m->message();
   }
?>

使用$num=125$num=90執行上述程式碼以獲取錯誤訊息和有效數字的訊息:

error : 125 is invalid number in line no 10

PHP – 特殊型別

PHP 的兩種資料型別——resourceNULL——被歸類為特殊型別。resource 型別物件引用外部資源,例如資料庫連線、檔案流等。另一方面,NULL 資料型別是一個沒有任何資料分配給它的變數。本章,我們將學習更多關於這些型別的知識。

資源型別

PHP 程式通常需要與外部環境(例如資料庫或磁碟檔案等)互動。這些在 PHP 中被視為資源。資源是一種特殊的資料型別,它引用任何此類外部資源。PHP 使用相關函式建立這些資源。例如,fopen() 函式開啟一個磁碟檔案,其引用儲存在一個資源變數中。

PHP 的 Zend 引擎使用引用計數系統。因此,引用計數為零的資源將由垃圾收集器自動銷燬,並且不需要手動釋放資源資料型別使用的記憶體。

不同的內建 PHP 函式返回各自的資源變數。隨後,PHP 使用它們與相應的外部環境互動。例如,fopen() 函式返回一個檔案資源,它充當檔案控制代碼,並且透過此資源變數來促進檔案的讀/寫操作。

下表總結了返回資源變數的不同函式:

資源型別 內建函式 定義
已生成 已售出
bzip2 bzopen() bzclose() Bzip2 檔案
curl curl_init() curl_close() Curl 會話
ftp ftp_connect(), ftp_close() FTP 流
mssql 連線 mssql_connect() mssql_close() 到 Microsoft SQL Server 資料庫的連線
mysql 連線 mysql_connect() mysql_close() 到 MySQL 資料庫的連線
mysql 結果 mysql_db_query(), mysql_free_result() MySQL 結果
oci8 連線 oci_connect() oci_close() 到 Oracle 資料庫的連線
ODBC 連線 odbc_connect() odbc_close() 到 ODBC 資料庫的連線
pdf 文件 pdf_new() pdf_close() PDF 文件
opendir() closedir() 目錄控制代碼
fopen(), tmpfile() fclose() 檔案控制代碼
套接字 socket_create() Socket_close() 套接字控制代碼
xml xml_parser_create() xml_parser_free() XML 解析器
zlib gzopen() gzclose() gz 壓縮檔案
zlib.deflate deflate_init() None() 增量解壓縮上下文
zlib.inflate inflate_init() None() 增量壓縮上下文

PHP 有 get_resource_type() 函式,它返回變數的資源型別。

get_resource_type ( resource $handle ) : string

其中 $handle 是要獲取其型別的資源變數。此函式返回與資源型別對應的字串。

還有一個 get_resource_id() 函式,它為給定的資源提供一個整數識別符號。

get_resource_id(resource $resource): int

示例

此函式提供了一種型別安全的方式來為給定的資源生成整數識別符號。

<?php
   $fp = fopen("hello.php", "r");
   $resource = get_resource_type($fp);
   $id = get_resource_id($fp);
   echo "The resource type is : $resource The resource ID is : $id";
?>

它將產生以下輸出

The resource type is : stream The resource ID is : 5

NULL 型別

在 PHP 中,沒有值的變數被稱為 null 資料型別。此類變數的值定義為 NULL。可以使用 unset() 函式將變數顯式賦值為 NULL 或將其值設定為 null。

$var=NULL;

可以將其他型別的變數轉換為 null,儘管從 PHP 7.2 開始已棄用將 null 轉換為其他型別。在早期版本中,轉換是使用 (unset)$var 語法完成的。

示例

以下示例顯示如何將 NULL 分配給變數

<?php
   $var=NULL;
   var_dump($var);
?>

它將產生以下輸出

NULL

示例

以下示例將 null 變數轉換為其他主要變數:

<?php
   $var = NULL;
   var_dump( (int)   $var);
   var_dump((float)$var);
   var_dump((bool)  $var) ;
   var_dump( (boolean) $var);
?>

它將產生以下輸出

int(0)
float(0)
bool(false)
bool(false)

PHP – 雜湊

術語“雜湊”表示加密資料(特別是文字)以獲得固定長度值的技術。PHP 庫包含許多函式,這些函式可以透過應用不同的雜湊演算法(例如 md5、SHA2、HMAC 等)對資料執行雜湊運算。獲得的加密值稱為原始金鑰的雜湊值。

雜湊處理是一個單向過程,這意味著不可能反轉雜湊以獲得原始金鑰。

雜湊的應用

雜湊技術有效地用於以下目的:

密碼認證

我們經常註冊各種線上應用程式,例如 gmail、Facebook 等。您需要填寫一個表單,在其中為線上帳戶建立密碼。伺服器會對您的密碼進行雜湊處理,並將雜湊值儲存在資料庫中。登入時,提交的密碼將被雜湊處理並與資料庫中的密碼進行比較。這可以保護您的密碼不被盜。

資料完整性

雜湊的一個重要用途是驗證資料是否未被篡改。當從網際網路下載檔案時,會顯示其雜湊值,您可以將其與下載的檔案進行比較,以確保檔案未損壞。

雜湊過程

雜湊過程可以用下圖表示:

PHP Hashing

PHP 中的雜湊演算法

PHP 支援多種雜湊演算法:

  • MD5 – MD5 是一種 128 位雜湊函式,廣泛用於軟體中以驗證傳輸檔案的完整性。128 位雜湊值通常表示為 32 位十六進位制數字。例如,單詞“frog”始終生成雜湊“8b1a9953c4611296a827abf8c47804d7”

  • SHA – SHA 代表安全雜湊演算法。它是美國國家標準與技術研究院 (NIST) 制定的標準系列。SHA 是 MD5 的修改版本,用於對資料和證書進行雜湊處理。SHA-1 和 SHA-2 是該演算法的兩個不同版本。SHA-1 是一個 160 位雜湊值。SHA-2 實際上是一個“系列”雜湊值,並且具有各種長度,最常用的是 256 位。

  • HMAC – HMAC(基於雜湊的訊息驗證碼)是一種加密身份驗證技術,它使用雜湊函式和金鑰。

  • HKDF – HKDF 是一種基於 HMAC 訊息驗證碼的簡單金鑰派生函式 (KDF)。

  • PBKDF2 – PBKDF2(基於密碼的金鑰派生函式 2)是一種雜湊演算法,它從密碼建立加密金鑰。

PHP 中的雜湊函式

PHP 庫包含多個雜湊函式:

hash_algos 函式

此函式返回一個數值索引陣列,其中包含受支援的雜湊演算法列表。

hash_algos(): array

hash_file 函式

該函式返回一個字串,其中包含計算出的訊息摘要(小寫十六進位制)。

hash_file(
   string $algo,
   string $filename,
   bool $binary = false,
   array $options = []
): string|false

algo 引數是所選雜湊演算法的型別(例如,“md5”、“sha256”、“haval160,4”等)。filename 是描述要雜湊檔案的 URL;支援 fopen 包裝器。

示例

請看以下示例:

<?php
   /* Create a file to calculate hash of */
   $fp=fopen("Hello.txt", "w");
   $bytes = fputs($fp, "The quick brown fox jumped over the lazy dog.");
   fclose($fp);
   echo hash_file('md5', "Hello.txt");
?>

它將產生以下輸出

5c6ffbdd40d9556b73a21e63c3e0e904

hash() 函式

hash() 函式生成雜湊值(訊息摘要)−

hash(
   string $algo,
   string $data,
   bool $binary = false,
   array $options = []
): string

algo 引數是所選雜湊演算法的型別(例如,“md5”、“sha256”、“haval160,4”等)。data 引數是要雜湊的訊息。如果 binary 引數為“true”,則輸出原始二進位制資料;“false”輸出小寫十六進位制。

示例

該函式返回一個字串,其中包含計算出的訊息摘要(小寫十六進位制)。

<?php
   echo "Using SHA256 algorithm:" . hash('sha256', 'The quick brown fox jumped over the lazy dog.'). PHP_EOL;
   echo "Using MD5 algorithm:",hash('md5', 'The quick brown fox jumped over the lazy dog.'), PHP_EOL;
   echo "Using SHA1 algorithm:" . hash('sha1', 'The quick brown fox jumped over the lazy dog.');
?>

它將產生以下輸出

Using SHA256 algorithm:68b1282b91de2c054c36629cb8dd447f12f096d3e3c587978dc2248444633483
Using MD5 algorithm:5c6ffbdd40d9556b73a21e63c3e0e904
Using SHA1 algorithm:c0854fb9fb03c41cce3802cb0d220529e6eef94e

PHP – 加密

早期版本的 PHP 包含 mcrypt 擴充套件,該擴充套件提供加密/解密功能。由於缺乏維護,mcrypt 擴充套件已棄用,並從 PHP 7.2 版本開始移除。PHP 現在包含 OpenSSL 庫,該庫具有廣泛的功能來支援加密和解密功能。

OpenSSL 支援各種加密演算法,例如 AES(高階加密標準)。所有受支援的演算法都可以透過呼叫 openssl_get_cipher_methods() 函式獲得。

OpenSSL 擴充套件中的兩個重要函式是 −

  • openssl_encrypt() − 加密資料

  • openssl_decrypt() − 解密資料

openssl_encrypt() 函式

此函式使用給定的方法和金鑰加密給定的資料,並返回原始或 base64 編碼的字串 −

openssl_encrypt(
   string $data,
   string $cipher_algo,
   string $passphrase,
   int $options = 0,
   string $iv = "",
   string &$tag = null,
   string $aad = "",
   int $tag_length = 16
): string|false

該函式具有以下引數

序號 引數 & 說明
1

data

要加密的明文訊息資料。

2

cipher_algo

密碼方法。

3

passphrase

密碼短語。如果密碼短語短於預期,則用 NULL 字元填充;如果密碼短語長於預期,則將其截斷。

4

options

options 是標誌 OPENSSL_RAW_DATA 和 OPENSSL_ZERO_PADDING 的按位析取。

5

iv

非 NULL 初始化向量。

6

tag

使用 AEAD 密碼模式(GCM 或 CCM)時按引用傳遞的身份驗證標記。

7

aad

附加身份驗證資料。

8

tag_length

身份驗證標記的長度。對於 GCM 模式,其值可以在 4 到 16 之間。

函式在成功時返回加密的字串,在失敗時返回false

openssl_decrypt() 函式

此函式獲取原始或 base64 編碼的字串,並使用給定的方法和金鑰對其進行解密。

openssl_decrypt(
   string $data,
   string $cipher_algo,
   string $passphrase,
   int $options = 0,
   string $iv = "",
   ?string $tag = null,
   string $aad = ""
): string|false

openssl_decrypt() 函式使用與openssl_encrypt 函式相同的引數。

此函式在成功時返回解密的字串,在失敗時返回 false。

示例

請看以下示例:

<?php
   function sslencrypt($source, $algo, $key, $opt, $iv) {
      $encstring = openssl_encrypt($source, $algo, $key, $opt, $iv);
      return $encstring;
   }

   function ssldecrypt($encstring, $algo, $key, $opt, $iv) {
      $decrstring = openssl_decrypt($encstring, $algo, $key, $opt, $iv);
      return $decrstring;
   }

   // string to be encrypted
   $source = "PHP: Hypertext Preprocessor";

   // Display the original string
   echo "Before encryption: " . $source . "\n";
   $algo = "BF-CBC";
   $opt=0;
   $ivlength = openssl_cipher_iv_length($algo);
   $iv = random_bytes($ivlength);
   $key = "abcABC123!@#"; 

   // Encryption process
   $encstring = sslencrypt($source, $algo, $key, $opt, $iv);

   // Display the encrypted string
   echo "Encrypted String: " . $encstring . "\n";

   // Decryption process
   $decrstring = ssldecrypt($encstring, $algo, $key, $opt, $iv);

   // Display the decrypted string
   echo "Decrypted String: " . $decrstring;
?>

它將產生以下輸出

Before encryption: PHP: Hypertext Preprocessor
Encrypted String: 
Decrypted String:

PHP is_null() 函式

PHP 將 NULL 定義為其特殊資料型別之一。它表示某個變數尚未分配任何特定資料型別的值。它是 PHP 中的內建常量,用於指示故意缺少任何物件或值。可以使用unset() 函式將變數顯式分配為 NULL 或將其值設定為 null。

is_null() 函式

PHP 提供了一個布林函式is_null() 來檢查變數是否確實是 NULL 型別。

is_null(mixed $value): bool

示例 1

如果任何變數都顯式分配了 NULL,則is_null() 函式顯然返回true

<?php
   $x = NULL;
   echo "Variable \$x is null? ";
   var_dump(is_null($x));
?>

它將產生以下輸出

Variable $x is null? bool(true)

示例 2

如果取消設定具有某個值的變數,則 is_null() 函式也會返回 true,但會發出警告

<?php
   $x = "Hello";
   unset($x);
   echo "Variable \$x is null?\n";
   var_dump(is_null($x));
?>

它將產生以下輸出

Variable $x is null?
bool(true)

PHP Warning:  Undefined variable $x in /home/cg/root/89262/main.php on line 5

示例 3

同樣,如果您只是宣告一個變數,而沒有為其賦值,則 is_null() 函式會返回true 併發出警告 −

<?php
   $y;
   echo "Variable \$y is null?\n";
   var_dump(is_null($y));
?>

它將產生以下輸出

Variable $y is null?
bool(true)
Warning: Undefined variable $y in hello.php on line 9

示例 4

您還可以使用等號運算子 (==) 來檢查變數是否為 NULL。

<?php
   $x = NULL;
   if ($x === NULL) {
      echo '$x is NULL';
   } else {
      echo '$x is not NULL';
   }
?>

它將產生以下輸出

$x is NULL

示例 5

空字串 "" 不被認為等於 NULL。因此,is_null() 函式以及 "==" 運算子都返回false。請看下面的示例 −

<?php
   $y = "";
   if ($y === NULL) {
      echo '$y is NULL';
   } else {
      echo '$y is not NULL';
   }
   echo "$y is null?\n";
   var_dump(is_null($y));
?>

它將產生以下輸出

$y is not NULL is null?
bool(false)

PHP 中與 is_null() 函式相關的另外兩個函式是isset() 函式和empty() 函式。

isset() 函式

isset() 函式確定變數是否已宣告且不同於 NULL。

isset(mixed $var, mixed ...$vars): bool

示例

分配為 NULL 的變數被認為是未設定的。

<?php
   $x = NULL;
   echo '$x is set? ';
   var_dump(isset($x));
?>

它將產生以下輸出

$x is set? bool(false)

請注意,空字元 ("\0") 不等效於 PHP 空常量。

empty() 函式

empty() 函式檢查變數是否被認為為空。如果變數不存在或其值為 NULL,則該變數被認為為空。如果變數不存在,empty() 不會生成警告。

示例 1

請看以下示例:

<?php
   $x = NULL;
   echo '$x is empty? ';
   var_dump(empty($x));
   $y;
   echo '$y is empty? ';
   var_dump(empty($y));
?>

它將產生以下輸出

$x is empty? bool(true)
$y is empty? bool(true)

示例 2

如果變數設定為“0”、“NULL”或根本未設定,則 empty() 函式返回true

<?php
   $var = 0;
   if (empty($var)) {
      echo '$var is either 0, empty, or not set at all';
   }
?>

它將產生以下輸出

$var is either 0, empty, or not set at all

PHP – 系統呼叫

PHP 的內建函式庫包括一類函式,這些函式處理從 PHP 程式碼內部呼叫作業系統實用程式和外部程式。在本章中,我們將討論用於執行系統呼叫的 PHP 函式。

system() 函式

system() 函式類似於 C 中的 system() 函式,它執行給定的命令並輸出結果。

system(string $command, int &$result_code = null): string|false

如果 PHP 作為伺服器模組執行,則 system() 呼叫會嘗試在每一行輸出後自動重新整理 Web 伺服器的輸出緩衝區。它在成功時返回命令輸出的最後一行,在失敗時返回 false。

示例

以下 PHP 程式碼段呼叫 Windows 作業系統的 DIR 命令,並顯示當前目錄中的檔案列表。

<?php
   echo '<pre>';

   // Outputs all the result of DOS command "dir", and returns
   // the last output line into $last_line. Stores the return value
   // of the shell command in $retval.
   $last_line = system('dir/w', $retval);

   // Printing additional info
   echo '
   </pre>
   <hr />Last line of the output: ' . $last_line . '
   <hr />Return value: ' . $retval;
?>

它將產生以下輸出

Volume in drive C has no label.
Volume Serial Number is 7EE4-E492

Directory of C:\xampp\htdocs
[.]                 [..]                applications.html   bitnami.css
[dashboard]         employee.csv        favicon.ico         hello.csv
hello.html          hello.php           homepage.php        [img]
index.php           [Langi]             menu.php            myform.php
myname.php          new.png             new.txt             test.php
test.zip            [TPcodes]           uploadfile.php      [webalizer]
welcome.png         [xampp]             
                 18 File(s)          123,694 bytes
                 8 Dir(s)            168,514,232,320 bytes free

Last line of the output: 8 Dir(s) 168,514,232,320 bytes free
Return value: 0

shell_exec() 函式

shell_exec() 函式與 PHP 的反引號運算子相同。它透過 shell 執行給定的命令並將完整的輸出作為字串返回

shell_exec(string $command): string|false|null

該函式返回一個包含已執行命令輸出的字串,如果無法建立管道則返回 false,如果發生錯誤或命令沒有產生輸出則返回 null。

示例

在下面的程式碼中,我們使用 shell_exec() 函式獲取當前目錄中副檔名為“.php”的檔案列表 −

<?php
   $output = shell_exec('dir *.php');
   echo "<pre>$output</pre>";
?>

它將產生以下輸出

Volume in drive C has no label.
Volume Serial Number is 7EE4-E492

Directory of C:\xampp\htdocs

10/26/2023  08:27 PM                73 hello.php
10/12/2023  10:40 AM                61 homepage.php
07/16/2015  09:02 PM               260 index.php
10/12/2023  10:39 AM                49 menu.php
09/25/2023  01:43 PM               338 myform.php
10/12/2023  10:49 AM                51 myname.php
10/26/2023  02:00 PM               369 test.php
09/25/2023  01:42 PM               555 uploadfile.php
               8 File(s)          1,756 bytes
               0 Dir(s)           168,517,771,264 bytes free

exec() 函式

exec() 函式將給定的命令作為字串引數執行。

exec(string $command, array &$output = null, 
   int &$result_code = null):string|false

如果指定了$output 引數,則它是一個數組,其中將填充來自命令的每一行輸出。

示例

在這種情況下,我們使用 exec() 函式從程式內部呼叫 whoami 命令。whoami 命令返回使用者名稱。

<?php

   // outputs the username that owns the running php/httpd process
   // (on a system with the "whoami" executable in the path)
   $output=null;
   $retval=null;
   exec('whoami', $output, $retval);
   echo "Returned with status $retval and output:\n";
   var_dump($output);
   
?>

它將產生以下輸出

Returned with status 0 and output: array(1) 
{ [0]=> string(13) "gnvbgl3\mlath" }

passthru() 函式

passthru() 函式執行外部程式並顯示原始輸出。儘管 passthru() 函式與 exec() 或 system() 函式類似,因為它執行命令,但在 OS 命令的輸出是需要直接傳遞迴瀏覽器的二進位制資料時,應使用它來代替它們。

示例

一個使用 passthu() 函式顯示系統 PATH 環境變數內容的 PHP 程式

passthru(string $command, int &$result_code = null): ?false
<?php
   passthru ('PATH');
?>

它將產生以下輸出

PATH=C:\Python311\Scripts\;C:\Python311\;C:\WINDOWS\system32;C:\WINDOWS;
C:\WINDOWS\System32\Wbem;C:\WINDOWS\System32\WindowsPowerShell\v1.0\;
C:\WINDOWS\System32\OpenSSH\;C:\xampp\php;C:\Users\mlath\AppData\Local
\Microsoft\WindowsApps;C:\VSCode\Microsoft VS Code\bin

反引號運算子

PHP 支援一個執行運算子:反引號 (``)。(它們不是單引號!)PHP 將嘗試將反引號的內容作為 shell 命令執行;將返回輸出。反引號運算子的使用與 shell_exec() 相同。

示例

請看以下示例:

<?php
   $output = `dir *.php`;
   echo "<pre>$output</pre>";
?>

它將產生以下輸出

Volume in drive C has no label.
Volume Serial Number is 7EE4-E492

Directory of C:\xampp\htdocs

10/26/2023  08:42 PM                61 hello.php
10/12/2023  10:40 AM                61 homepage.php
07/16/2015  09:02 PM               260 index.php
10/12/2023  10:39 AM                49 menu.php
09/25/2023  01:43 PM               338 myform.php
10/12/2023  10:49 AM                51 myname.php
10/26/2023  02:00 PM               369 test.php
09/25/2023  01:42 PM               555 uploadfile.php
               8 File(s)          1,744 bytes
               0 Dir(s)           168,471,289,856 bytes free

shell_exec() 被停用時,反引號運算子也被停用。

PHP – HTTP 身份驗證

在 PHP 中,header() 函式用於向客戶端瀏覽器傳送“需要身份驗證”訊息,從而使其彈出使用者名稱/密碼輸入視窗。事實上,header() 允許您傳送任何原始 HTTP 標頭。

header(string $header, bool $replace = true, int $response_code = 0): void

字串引數傳遞給 header() 函式。例如

header("HTTP/1.1 404 Not Found");

它用於確定要傳送的 HTTP 狀態程式碼。

您還可以使用 header() 函式將瀏覽器重定向到另一個 URL。

使用者填寫使用者名稱和密碼後,將再次呼叫包含 PHP 指令碼的 URL,並將預定義變數 PHP_AUTH_USER、PHP_AUTH_PW 和 AUTH_TYPE 分別設定為使用者名稱、密碼和身份驗證型別。這些預定義變數位於 $_SERVER 陣列中。僅支援“Basic”和“Digest”身份驗證方法。

<?php

   /* Redirect browser */
   header("Location: http://www.example.com/"); 

   /* Make sure that code below does not get executed when we redirect. */
   exit;
   
?>

可選的 replace 引數指示標頭是否應替換之前的類似標頭,或者新增第二個相同型別的標頭,response_code 引數將 HTTP 響應程式碼強制為指定的值。

為了能夠強制客戶端身份驗證,您需要在文件根目錄資料夾中有一個 .htaccess 檔案。開啟一個新的文字檔案,將以下文字放入其中,並將其儲存為 .htaccess。

CGIPassAuth On

示例

一個強制客戶端在頁面上進行身份驗證的示例指令碼片段如下所示 −

<?php
   if (!isset($_SERVER['PHP_AUTH_USER'])) {
      header('WWW-Authenticate: Basic realm="My Realm"');
      header('HTTP/1.0 401 Unauthorized');
      echo 'User hits Cancel button';7
      exit;
   } else {
      echo "<p>Hello {$_SERVER['PHP_AUTH_USER']}.</p>";
      echo "<p>You entered {$_SERVER['PHP_AUTH_PW']} as your password.</p>";
   }
?>

輸出

當您在瀏覽器中訪問指令碼時,它會彈出一個對話方塊,如下所示 −

PHP HTTP Authentication 1

單擊登入按鈕後,可能會有一個後端指令碼來驗證登入憑據。驗證通過後,將建立兩個伺服器變數,其鍵為 PHP_AUTH_USER 和 PHP_AUTH_PW,可以使用 phpinfo() 函式的輸出進行驗證。

PHP HTTP Authentication 2

PHP – 交換變數

PHP 沒有提供任何內建函式可以交換或互換兩個變數的值。但是,有一些技術可以用來執行交換。

最直接的方法之一是使用第三個變數作為臨時佔位符來促進交換。以特定順序使用算術運算子也很有效。您還可以使用二進位制 XOR 運算子進行交換。在本章中,我們將用 PHP 實現這些交換技術

臨時變數

從邏輯上講,這是最明顯也是最簡單的方法。要交換“a”和“b”的值,請使用第三個變數“c”。將“a”的值賦給“c”,用“b”的現有值覆蓋“a”,然後將“b”設定為儲存在“c”中的“a”的先前值。

示例

請看以下示例:

<?php
   $a = 10;
   $b = 20;
   echo "Before swapping - \$a = $a, \$b = $b". PHP_EOL;
   $c = $a; 
   $a = $b;
   $b = $c;
   echo "After swapping - \$a = $a, \$b = $b". PHP_EOL;
?>

它將產生以下輸出

Before swapping - $a = 10, $b = 20
After swapping - $a = 20, $b = 10

使用加法 (+) 運算子

此解決方案利用了從兩個數字的和中減去一個數字會返回第二個數字這一事實。換句話說,“sum(a+b) – a”等於“b”,反之亦然。

示例

讓我們利用此屬性來交換“a”和“b” −

<?php
   $a = 10;
   $b = 20;
   echo "Before swapping - \$a = $a, \$b = $b". PHP_EOL;
   $a = $a + $b;
   $b = $a - $b;
   $a = $a - $b;
   echo "After swapping - \$a = $a, \$b = $b". PHP_EOL;
?>

它將產生以下輸出

Before swapping - $a = 10, $b = 20
After swapping - $a = 20, $b = 10

您還可以以類似的方式使用其他算術運算子 – 減法 (-)、乘法 (*) 和除法 (/) 來執行交換。

使用 list() 函式

PHP 中的 list() 函式將陣列解包到單獨的變數中。這有助於我們實現交換兩個變數的目標。為此,構建一個包含“a”和“b”的陣列,然後將其解包到“b”和“a”變數以獲得具有互換值的“a”和“b”。

示例

請看以下示例:

<?php
   $a = 10;
   $b = 20;
   echo "Before swapping - \$a = $a, \$b = $b". PHP_EOL;
   $arr = [$a, $b];
   list($b, $a) = $arr;
   echo "After swapping - \$a = $a, \$b = $b". PHP_EOL;
?>

它將產生以下輸出

Before swapping - $a = 10, $b = 20
After swapping - $a = 20, $b = 10

按位 XOR

按位異或 (^) 運算子也可用於交換兩個變數“x”和“y”的值。當兩個運算元中相同位置的兩個位中只有一個為 1 時,它返回 1;否則返回 0。

示例

請看以下示例:

<?php
   $a = 10;
   $b = 20;
   echo "Before swapping - \$a = $a, \$b = $b". PHP_EOL;
   $a = $a ^ $b;
   $b = $a ^ $b;
   $a = $a ^ $b;
   echo "After swapping - \$a = $a, \$b = $b". PHP_EOL;
?>

它將產生以下輸出

Before swapping - $a = 10, $b = 20
After swapping - $a = 20, $b = 10

PHP – Closure::call()

在 PHP 中,閉包是一個匿名函式,它可以訪問其建立範圍內的變數,即使該範圍已關閉。你需要在其中指定 use 關鍵字。

閉包是封裝函式程式碼及其建立範圍的物件。在 PHP 7 中,引入了一種新的 closure::call() 方法,用於將物件範圍繫結到閉包並呼叫它。

Closure 類中的方法

Closure 類包含以下方法,包括 call() 方法:

final class Closure {

   /* Methods */
   private __construct()
   public static bind(Closure $closure, ?object $newThis, object|string|null $newScope = "static"): ?Closure
   public bindTo(?object $newThis, object|string|null $newScope = "static"): ?Closure
   public call(object $newThis, mixed ...$args): mixed
   public static fromCallable(callable $callback): Closure
   
}

call() 方法是 Closure 類的靜態方法。它作為 bind() 或 bindTo() 方法的快捷方式被引入。

bind() 方法使用特定的繫結物件和類範圍複製閉包,而 bindTo() 方法使用新的繫結物件和類範圍複製閉包。

call() 方法具有以下簽名

public Closure::call(object $newThis, mixed ...$args): mixed

call() 方法將閉包臨時繫結到 newThis,並使用任何給定的引數呼叫它。

在 PHP 7 之前的版本中,可以使用 bindTo() 方法,如下所示:

<?php
   class A {
      private $x = 1;
   }

   // Define a closure Pre PHP 7 code
   $getValue = function() {
      return $this->x;
   };

   // Bind a clousure
   $value = $getValue->bindTo(new A, 'A'); 
   print($value());
?>

程式將$getValue(一個閉包物件)繫結到 A 類的物件,並列印其私有變數$x的值——它是 1。

在 PHP 7 中,繫結是透過 call() 方法實現的,如下所示:

<?php
   class A {
      private $x = 1;
   }

   // PHP 7+ code, Define
   $value = function() {
      return $this->x;
   };

   print($value->call(new A));
?>

PHP – 過濾後的 unserialize()

在 PHP 中,內建函式 unserialize() 從 PHP 4 版本開始可用。在 PHP 7 中,添加了傳遞允許的類列表的規定。這允許過濾掉不受信任的來源。unserialize() 函式只對來自受信任類的數進行反序列化。

在 PHP 中,序列化意味著生成值的可儲存表示形式。這對於儲存或傳遞 PHP 值非常有用,而不會丟失其型別和結構。內建的 serialize() 函式用於此目的。

serialize(mixed $value): string

unserialize() 函式從序列化的表示形式中獲取 PHP 值。從 PHP 7 開始,unserialize() 函式遵循以下格式:

unserialize(string $data, array $options = [ ]): mixed

$data 引數是要反序列化的序列化字串。

$options 引數是新引入的。它是一個包含以下鍵的關聯陣列:

序號 名稱和描述

1

allowed_classes

應該接受的類名陣列,

or

false 表示不接受任何類,

or

true 表示接受所有類。

省略此選項與將其定義為 true 相同。

2

max_depth

反序列化期間允許的結構的最大深度。

示例

請看以下示例:

<?php
   class MyClass { 
      var int $x;
      function __construct(int $x) {
         $this->x = $x;
      }
   }
   class NewClass {
      var int $y;
      function __construct(int $y) {
         $this->y = $y;
      }
   }

   $obj1 = new MyClass(10);
   $obj2 = new NewClass(20);

   $sob1 = serialize($obj1);
   $sob2 = serialize($obj2);

   // default behaviour that accepts all classes
   // second argument can be ommited.
   // if allowed_classes is passed as false, unserialize converts all objects into __PHP_Incomplete_Class object
   $usob1 = unserialize($sob1 , ["allowed_classes" => true]);

   // converts all objects into __PHP_Incomplete_Class object except those of MyClass and NewClass
   $usob2 = unserialize($sob2 , ["allowed_classes" => ["MyClass", "NewClass"]]);

   echo $usob1->x . PHP_EOL;
   echo $usob2->y . PHP_EOL;
?>

它將產生以下輸出

10
20

PHP – IntlChar

在 PHP 7 中,引入了一個新的 IntlChar 類。它提供對許多實用程式方法的訪問,這些方法可用於訪問有關 Unicode 字元的資訊。Intl 類中有很多靜態方法和常量。它們與底層 ICU(Unicode 國際元件)庫使用的名稱和行為非常接近。

注意你需要在系統中的 PHP 安裝中啟用 Intl 擴充套件。要啟用,請開啟 php.ini 檔案並取消註釋(刪除行首的分號)

extension=intl

下面用示例解釋了 Intl 類中的一些靜態函式:

IntlChar::charAge

此函式獲取程式碼點的“年齡”。

public static IntlChar::charAge(int|string $codepoint): ?array

“年齡”是程式碼點首次指定(作為非字元或專用用途)或分配字元的 Unicode 版本。

示例

請看以下示例:

<?php
   var_dump(IntlChar::charage("\u{2603}"));
?>

它將產生以下輸出

array(4) {
   [0]=>
   int(1)
   [1]=>
   int(1)
   [2]=>
   int(0)
   [3]=>
   int(0)
}

IntlChar::charFromName

charFromName() 函式按名稱查詢 Unicode 字元並返回其程式碼點值。

public static IntlChar::charFromName(string $name, 
   int $type = IntlChar::UNICODE_CHAR_NAME): ?int

type 引數設定要用於查詢的名稱。可以是以下任何常量:

  • IntlChar::UNICODE_CHAR_NAME(預設)

  • IntlChar::UNICODE_10_CHAR_NAME

  • IntlChar::EXTENDED_CHAR_NAME

  • IntlChar::CHAR_NAME_ALIAS

  • IntlChar::CHAR_NAME_CHOICE_COUNT

示例

請看以下示例:

<?php
   var_dump(IntlChar::charFromName("LATIN CAPITAL LETTER A"));
   var_dump(IntlChar::charFromName("SNOWMAN"));
?>

它將產生以下輸出

int(65)
int(9731)

IntlChar::charName

charName() 函式檢索 Unicode 字元的名稱。

public static IntlChar::charName(int|string $codepoint, 
   int $type = IntlChar::UNICODE_CHAR_NAME): ?string

示例

請看以下示例:

<?php
   var_dump(IntlChar::charName(".", IntlChar::UNICODE_CHAR_NAME));
   var_dump(IntlChar::charName("\u{2603}"));
?>

它將產生以下輸出

string(9) "FULL STOP"
string(7) "SNOWMAN"

IntlChar::isalpha

isalpha() 函式確定指定的程式碼點是否為字母字元。對於通用類別“L”(字母)為 true。

public static IntlChar::isalpha(int|string $codepoint): ?bool

示例

請看以下示例:

<?php
   var_dump(IntlChar::isalpha("A"));
   var_dump(IntlChar::isalpha("1"));
?>

它將產生以下輸出

bool(true)
bool(false)

Intl 類定義了類似的靜態方法,例如 isdigit()、isalnum()、isblank() 等。

IntlChar::islower

islower() 函式確定指定的程式碼點是否具有通用類別“Ll”(小寫字母)。

public static IntlChar::islower(int|string $codepoint): ?bool

示例

請看以下示例:

<?php
   var_dump(IntlChar::islower("A"));
   var_dump(IntlChar::islower("a"));
?>

它將產生以下輸出

bool(false)
bool(true)

類似地,還有諸如 isupper()、istitle()、iswhitespace() 等函式。

IntlChar::toupper

給定字元對映到其大寫等價物。

public static IntlChar::toupper(int|string $codepoint): int|string|null

如果字元沒有大寫等價物,則返回字元本身。

示例

請看以下示例:

<?php
   var_dump(IntlChar::toupper("A"));
   var_dump(IntlChar::toupper("a"));
?>

它將產生以下輸出

string(1) "A"
string(1) "A"

PHP – CSPRNG

CSPRNG 首字母縮寫代表密碼學安全的偽隨機數生成器。PHP 函式庫包含許多生成隨機數的函式。例如:

  • mt_rand() – 透過梅森旋轉演算法隨機數生成器生成隨機值。

  • mt_srand() – 為梅森旋轉演算法隨機數生成器播種。

  • rand() – 生成一個隨機整數。

示例

以下程式碼顯示如何使用mt_rand()函式生成隨機數:

<?php
   # Generates random integer between the range
   echo "Random integer: " . rand(1,100) . PHP_EOL;
   # Generate a random value via the Mersenne Twister Random Number Generator
   echo "Random number: " . mt_rand(1,100);
?>

它將產生以下輸出

Random integer: 45
Random number: 86

請注意,每次執行程式碼時,輸出都可能不同。但是,這些函式生成的隨機數不是密碼學安全的,因為可以猜測其結果。PHP 7 引入了一些生成安全隨機數的函式。

以下函式是新新增的,它們是密碼學安全的:

  • random_bytes() – 生成密碼學安全的偽隨機位元組。

  • random_int() – 生成密碼學安全的偽隨機整數。

random_bytes() 函式

random_bytes() 生成任意長度的密碼學隨機位元組字串,適用於密碼學用途,例如生成鹽、金鑰或初始化向量。

string random_bytes ( int $length )

引數

  • length – 以位元組為單位應返回的隨機字串的長度。

該函式返回一個包含請求數量的密碼學安全隨機位元組的字串。

如果找不到合適的隨機源,將丟擲異常。如果給出無效引數,將丟擲 TypeError。如果給出無效的位元組長度,將丟擲 Error。

示例

請看以下示例:

<?php
   $bytes = random_bytes(5);
   print(bin2hex($bytes));
?>

它可能會產生以下輸出(每次可能不同):

6a85eec950

random_int() 函式

random_int() 生成密碼學隨機整數,適用於對無偏結果至關重要的場合。

int random_int ( int $min , int $max )

引數

  • min – 要返回的最低值,必須大於或等於 PHP_INT_MIN。

  • max – 要返回的最高值,必須小於或等於 PHP_INT_MAX。

該函式返回 min 到 max(包括 min 和 max)範圍內的密碼學安全隨機整數。

如果找不到合適的隨機源,將丟擲異常。如果給出無效引數,將丟擲 TypeError。如果 max 小於 min,將丟擲 Error。

示例

請看以下示例:

<?php
   print(random_int(100, 999));
   print("\n");
   print(random_int(-1000, 0));
?>

它可能會產生以下輸出(每次都不同):

495
-563

PHP – 斷言

斷言是對舊assert()函式向後相容的增強。斷言允許在生產程式碼中進行零成本斷言,並在斷言失敗時提供丟擲自定義異常的能力。

assert()現在是一個語言結構,其中第一個引數是一個表示式,而不是要測試的字串或布林值。

assert() 的配置指令

下表列出了 assert() 函式的配置指令:

指令 預設值 可能的值
zend.assertions 1

1 – 生成並執行程式碼(開發模式)

0 – 生成程式碼,但在執行時跳過它

-1 – 不生成程式碼(生產模式)

assert.exception 0

1 – 當斷言失敗時丟擲異常,可以透過丟擲作為異常提供的物件來丟擲,或者如果未提供異常則丟擲新的AssertionError物件。

0 – 使用或生成如上所述的可丟擲物件,但僅基於該物件生成警告,而不是丟擲它(與 PHP 5 行為相容)

引數

  • 斷言 – 斷言。在 PHP 5 中,這必須是要評估的字串或要測試的布林值。在 PHP 7 中,這也可以是返回值的任何表示式,該表示式將被執行,其結果用於指示斷言成功還是失敗。

  • 描述 – 如果斷言失敗,則包含在失敗訊息中的可選描述。

  • 異常 – 在 PHP 7 中,第二個引數可以是 Throwable 物件而不是描述性字串,在這種情況下,如果斷言失敗並且啟用了 assert.exception 配置指令,則這是將要丟擲的物件。

返回值

如果斷言為 false,則返回 FALSE,否則返回 TRUE。

示例

請看以下示例:

<?php
   ini_set('assert.exception', 1);
   class CustomError extends AssertionError {}
   assert(false, new CustomError('Custom Error Message!'));
?>

它將產生以下輸出

PHP Fatal error:  Uncaught CustomError: Custom Error Message! In test.php:6

PHP – “use” 語句

PHP 中的“use”關鍵字被發現與多種用途相關聯,例如別名、插入特性和繼承閉包中的變數。

別名

使用 use 運算子實現別名。它允許你使用別名或替代名稱來引用外部完全限定名稱。

示例

請看以下示例:

use My\namespace\myclass as Another;
$obj = new Another;

你也可以按如下方式進行分組使用宣告:

use some\namespace\{ClassA, ClassB, ClassC as C};
use function some\namespace\{fn_a, fn_b, fn_c};
use const some\namespace\{ConstA, ConstB, ConstC};

特性

藉助 use 關鍵字,你可以將特性插入類中。特性類似於類,但僅用於以細粒度和一致的方式分組功能。無法自行例項化特性。

示例

請看以下示例:

<?php
   trait mytrait {
      public function hello() {
         echo "Hello World from " . __TRAIT__ .;
      }
   }

   class myclass {
      use mytrait;
   }

   $obj = new myclass();
   $obj->hello();
?>

它將產生以下輸出

Hello World from mytrait

閉包

閉包也是一個匿名函式,它可以藉助“use”關鍵字訪問其範圍之外的變數。

示例

請看以下示例:

<?php
   $maxmarks=300;
   $percent=function ($marks) use ($maxmarks) {
      return $marks*100/$maxmarks;
   };
   $m = 250;
   echo "marks=$m percentage=". $percent($m);
?>

它將產生以下輸出

marks=250 percentage=83.333333333333

PHP – 整數除法

PHP 引入了一個新的函式 intdiv(),它執行其運算元的整數除法並返回除法結果為整數。

intdiv() 函式返回兩個整數引數的整數商。如果“a/b”的結果是除法為“c”餘數為“r”,則:

a=b*c+r

在這種情況下,intdiv(a,b)返回r

intdiv ( int $x , int $y ) : int

$x 和 $y 是除法表示式的分子和分母部分。intdiv() 函式返回一個整數。如果兩個引數都是正數或都是負數,則返回值為正。

示例 1

如果分子 < 分母,intdiv() 函式返回“0”,如下所示:

<?php
   $x=10;
   $y=3; 
   $r=intdiv($x, $y);
   echo "intdiv(" . $x . "," . $y . ") = " . $r . "\n";
   $r=intdiv($y, $x);
   echo "intdiv(" . $y . "," . $x . ") = " . $r;
?>

它將產生以下輸出

intdiv(10,3) = 3
intdiv(3,10) = 0

示例 2

在下面的示例中,intdiv() 函式返回負整數,因為分子或分母是負數。

<?php
   $x=10;
   $y=-3; 
   $r=intdiv($x, $y);
   echo "intdiv(" . $x . "," . $y . ") = " . $r . "\n";
   $x=-10;
   $y=3; 
   $r=intdiv($x, $y);
   echo "intdiv(" . $x . "," . $y . ") = " . $r . "\n";
?>

它將產生以下輸出

intdiv(10,-3) = -3
intdiv(-10,3) = -3

示例 3

如果分子和分母都是正數或都是負數,intdiv() 函式返回正整數。

<?php
   $x=10;
   $y=3; 
   $r=intdiv($x, $y);
   echo "intdiv(" . $x . "," . $y . ") = " . $r . "\n";

   $x=-10;
   $y=-3; 
   $r=intdiv($x, $y);
   echo "intdiv(" . $x . "," . $y . ") = " . $r ;
?>

它將產生以下輸出

intdiv(10,3) = 3
intdiv(-10,-3) = 3

示例 4

在下面的示例中,分母為“0”。這會導致DivisionByZeroError異常。

<?php
   $x=10;
   $y=0; 
   $r=intdiv($x, $y);
   echo "intdiv(" . $x . "," . $y . ") = " . $r . "\n";
?>

它將產生以下輸出

PHP Fatal error:  Uncaught DivisionByZeroError: Division by zero in hello.php:4

PHP – 已棄用的特性

隨著每個新版本的新增一些新特性,也刪除了一些特性,因為它們被認為已過時。在本章中,我們將介紹 PHP 5 版本之後已棄用的特性。

在 PHP 7 中已棄用

PHP 4 樣式的建構函式

PHP 4 樣式的建構函式(與類名相同的函式)現已棄用,將來會移除。如果 PHP 4 建構函式是類中唯一定義的建構函式,PHP 7 將發出 E_DEPRECATED 警告。實現 __construct() 方法的類不受影響。

示例

請看以下示例:

<?php
   class A {
      function A() {
         print('Style Constructor');
      }
   }
?>

它在瀏覽器上產生以下輸出

Deprecated: Methods with the same name as their class will not be 
constructors in a future version of PHP; A has a deprecated constructor in...

對非靜態方法的靜態呼叫

對非靜態方法的靜態呼叫已棄用,將來可能會移除。

示例

請看以下示例:

<?php
   class A {
      function b() {
         print('Non-static call');
      }
   }
   A::b();
?>

它在瀏覽器上產生以下輸出

Deprecated: Non-static method A::b() should not be called statically in...
Non-static call

password_hash() 的 salt 選項

password_hash() 函式的 salt 選項已棄用,以防止開發者生成自己的(通常不安全的)salt。如果開發者未提供 salt,該函式本身會生成密碼學安全的 salt,因此不再需要自定義 salt 生成。

capture_session_meta SSL 上下文選項

capture_session_meta SSL 上下文選項已棄用。現在透過 stream_get_meta_data() 函式使用 SSL 元資料。

ext/mcrypt

mcrypt 擴充套件已棄用,建議使用 OpenSSL。

未加引號的字串

未加引號且不存在的全域性常量將被視為字串本身。此行為過去會發出 E_NOTICE 警告,現在將發出 E_WARNING 警告。在 PHP 的下一個主要版本中,將丟擲 Error 異常。

__autoload() 方法

__autoload() 方法已棄用,因為它不如 spl_autoload_register() (因為它無法連結自動載入器),並且這兩種自動載入方式之間沒有互操作性。

create_function() 函式

鑑於此函式的安全問題,它現已棄用。建議使用匿名函式作為替代。

each() 函式

此函式會導致某些語言更改的實現問題。因此,它已被棄用。

不區分大小寫的常量

不區分大小寫的常量宣告已棄用。現在,將 true 作為第三個引數傳遞給 define() 將生成棄用警告。

(real) 型別轉換和 is_real() 函式

(real) 型別轉換已棄用,請改用 (float)。is_real() 函式也已棄用,請改用 is_float()。

"parent" 關鍵字

在沒有父類的類中使用 parent 已棄用,將來會引發編譯時錯誤。目前,只有在執行時訪問父類時才會生成錯誤。

PHP 8 中已棄用

如果帶有預設值的引數後面跟著必需引數,則預設值無效。從 PHP 8.0.0 開始,這已被棄用,通常可以透過刪除預設值來解決,而不會改變功能:

<?php
   function test($a = [], $b) {}  // Before
   function test($a, $b) {}      // After
?>

此規則的一個例外是 Type $param = null 形式的引數,其中 null 預設值使型別隱式可為空。此用法仍然允許,但建議改用顯式可空型別:

<?php
   function test(A $a = null, $b) {} 	// Still allowed
   function test(?A $a, $b) {}         // Recommended
?>

將 get_defined_functions() 的 exclude_disabled 顯式設定為 false 已棄用,並且不再有效。get_defined_functions() 永遠不會包含停用的函式。

返回 true 或 false 的排序比較函式現在將丟擲棄用警告,應將其替換為返回小於、等於或大於零的整數的實現。

<?php
   // Replace
   usort($array, fn($a, $b) => $a > $b);
   // With
   usort($array, fn($a, $b) => $a <=> $b);
?>

隱式不相容的 float 到 int 轉換

導致精度損失的 float 到 int 的隱式轉換現已棄用。這會影響陣列鍵、強制模式下的 int 型別宣告以及對 int 進行運算的運算子。

在 Trait 上呼叫靜態元素

直接在 Trait 上呼叫靜態方法或訪問靜態屬性已棄用。靜態方法和屬性只能在使用該 Trait 的類上訪問。

日期函式

date_sunrise() 和 date_sunset() 已棄用。請改用 date_sun_info()。

strptime() 已棄用。請改用 date_parse_from_format()(用於與區域設定無關的解析)或 IntlDateFormatter::parse()(用於與區域設定相關的解析)。

strftime() 和 gmstrftime() 已棄用。您可以改用 date()(用於與區域設定無關的格式化)或 IntlDateFormatter::format()(用於與區域設定相關的格式化)。

動態屬性

建立動態屬性已棄用。請改用允許動態屬性的 stdClass。

PHP – 已移除的擴充套件和 SAPI

PHP 的每個新版本都會新增新功能,同時也會移除某些過時的功能。PHP 7 是一個主要版本,其中刪除了許多 PHP 擴充套件和 SAPI(伺服器端應用程式程式設計介面)。在隨後的 PHP 8 版本中,還刪除了一些擴充套件。

在 PHP 中,擴充套件是用 C/C++ 編寫的庫或外掛,編譯成共享庫以便可以載入到 PHP 直譯器中。PHP 直譯器啟動後,擴充套件中的函式即可供 PHP 指令碼使用。

定期移除擴充套件,因為它們要麼不再維護,要麼已被更新的替代方案取代。例如,與 PHP 7 同時,ereg 擴充套件被 preg 擴充套件取代,mssql 擴充套件被 PDO_MSSQL 擴充套件取代。

已移除的擴充套件

從 PHP 7 開始,已移除以下擴充套件:

  • ereg 擴充套件已由 preg 替代

  • mssql 擴充套件已由 pdo_mssql 替代

  • mysql 擴充套件已由 mysqli 替代

  • sybase_ct 已由 pdo_sybase 替代

從 PHP 8 開始,已移除以下擴充套件:

  • Mcrypt - Mcrypt 擴充套件用於加密和解密,但自 PHP 7.1 起已棄用,並在 PHP 8 中由於安全漏洞而被移除。

  • MDB2 - MDB2 擴充套件以前用於訪問 MDB 資料庫檔案,由於缺乏維護,在 PHP 8 中被移除。

  • Ming - 由於 Flash 現在不再流行,用於生成 Flash 內容的 Ming 擴充套件自 PHP 5.5 起已棄用,並在 PHP 8 中被移除。

  • Phar Data - Phar Data 擴充套件用於訪問 PHAR 存檔中的資料,但在 PHP 8 中被移除,因為還有其他方法可以訪問 PHAR 資料。

  • SNMP - 由於沒有維護,SNMP 擴充套件已在 PHP 8 中移除。

  • Tidy - 由於添加了新的 HTML 驗證庫,Tidy 擴充套件已在 PHP 中移除。

  • Tokenizer - Tokenizer 擴充套件也因同樣的原因在 PHP 8 中被移除。

  • cURL - cURL 擴充套件在 PHP 8.1 中被移除,因為它不再維護。

已移除的 SAPI

SAPI 代表 PHP 中的伺服器端應用程式程式設計介面。SAPI 負責將 PHP 程式碼轉換為 Web 伺服器可以理解的內容。它解析 PHP 程式碼並呼叫相應的 Web 伺服器函式。然後,Web 伺服器生成 HTTP 響應並將其傳送回客戶端。

從 PHP 7 開始,已移除以下 SAPI(伺服器端應用程式程式設計介面):

  • aolserver

  • apache

  • apache_hooks

  • apache2filter

  • caudium

  • cgi

  • cgi-fcgi

  • fastcgi

  • isapi

  • litespeed

  • nsapi

  • pwsapi

  • router

  • thttpd

  • uwsgi

  • webserver

  • apache2filter

  • continuity

  • isapi

  • milter

  • nsapi

  • pi3web

  • roxen

  • thttpd

  • tux

  • webjames

PHP – PEAR

PEAR 是 **PHP Extension and Application Repository** 的縮寫。它是 PHP 包或擴充套件的儲存庫。您可以自由地將 PEAR 中的任何這些擴充套件合併到您的程式碼中。PEAR 專案由 Stig S. Bakken 於 1999 年建立。

大多數 PHP 的預編譯發行版(如 XAMPP)都已捆綁了 PEAR。如果沒有,您可以從 https://pear.php.net/go-pear.phar 下載 go-pear.phar 檔案並執行

php go-pear.phar

Windows 命令提示符以啟動安裝。

根據您對安裝步驟的響應,PEAR 包管理器將安裝在安裝過程中指定的路徑中。

然後,您可以將該安裝路徑新增到您的 PATH 環境變數中。您可以手動執行此操作(開始 > 控制面板 > 系統 > 環境),或者執行(雙擊)現在位於 PHP 源目錄中的新生成的 PEAR_ENV.reg。

現在,您可以透過執行以下命令訪問 PEAR 包管理器:

C:\xampp\php>pear 

在 Windows 命令提示符中。

您將獲得以下 PEAR 命令列表:

C:\xampp\php>pear
Commands:
build                  Build an Extension From C Source
bundle                 Unpacks a Pecl Package
channel-add            Add a Channel
channel-alias          Specify an alias to a channel name
channel-delete         Remove a Channel From the List
channel-discover       Initialize a Channel from its server
channel-info           Retrieve Information on a Channel
channel-login          Connects and authenticates to remote channel server
channel-logout         Logs out from the remote channel server
channel-update         Update an Existing Channel
clear-cache            Clear Web Services Cache
config-create          Create a Default configuration file
config-get             Show One Setting
config-help            Show Information About Setting
config-set             Change Setting
config-show            Show All Settings
convert                Convert a package.xml 1.0 to package.xml 2.0 format
cvsdiff                Run a "cvs diff" for all files in a package
cvstag                 Set CVS Release Tag
download               Download Package
download-all           Downloads each available package from the default channel
info                   Display information about a package
install                Install Package
list                   List Installed Packages In The Default Channel
list-all               List All Packages
list-channels          List Available Channels
list-files             List Files In Installed Package
list-upgrades          List Available Upgrades
login                  Connects and authenticates to remote server [Deprecated in favor of channel-login]
logout                 Logs out from the remote server [Deprecated in favor of channel-logout]
makerpm                Builds an RPM spec file from a PEAR package
package                Build Package
package-dependencies   Show package dependencies
package-validate       Validate Package Consistency
pickle                 Build PECL Package
remote-info            Information About Remote Packages
remote-list            List Remote Packages
run-scripts            Run Post-Install Scripts bundled with a package
run-tests              Run Regression Tests
search                 Search remote package database
shell-test             Shell Script Test
sign                   Sign a package distribution file
svntag                 Set SVN Release Tag
uninstall              Un-install Package
update-channels        Update the Channel List
upgrade                Upgrade Package
upgrade-all            Upgrade All Packages [Deprecated in favor of calling upgrade with no parameters]

使用 PEAR 安裝包非常容易。查詢包的一種方法是使用官方 PEAR 網站 https://pear.php.net/packages.php,然後執行

pear install <package-name>

下一步是在您的程式碼中使用 PEAR 包。為此,您應該使用 include、require、include_once 或 require_once 語句將包的主 PHP 指令碼包含到您的程式中。

<?php
   include "PEARPACKAGE.php";
   . . . . . 
   // rest of the code
   . . . . . 
?>

一個名為 Composer 的較新的 PHP 包管理器是用於管理 PHP 專案包的替代方案。Composer 還支援安裝 PEAR 包。許多人更喜歡使用 Composer 而不是 PEAR 來分發 PHP 包。

PHP – CSRF

"CSRF" 是跨站請求偽造的縮寫。CSRF 是一種網際網路漏洞,涉及受信任的網站使用者發出未經授權的命令。可以透過本章中解釋的措施來為 PHP Web 應用程式提供針對此攻擊的充分保護。

預設情況下,瀏覽器使用“GET”請求方法傳送資料。這通常用作 CSRF 中的漏洞點。為了將命令注入到特定網站,攻擊者使用諸如“IMG”之類的 HTML 標籤。例如,Web 應用程式的 URL 端點(例如“/delete.php?empcode=1234”)會刪除從 GET 請求的 empcode 引數傳遞的帳戶。現在,如果經過身份驗證的使用者在任何其他應用程式中遇到以下指令碼:

<img src="http://example.com/delete.php?empcode=1234" 
   width="0" height="0" border="0">

無意中導致與 empcode=1234 相關的資料被刪除。

解決此問題的常用方法是使用 CSRF 令牌。CSRF 令牌是由嵌入到請求中的隨機字元組成的字串,以便 Web 應用程式可以信任該請求已從預期來源(根據正常工作流程)接收。

實現 CSRF 的步驟

在 PHP 中實現 CSRF 令牌保護的步驟如下:

  • 透過啟動新會話來開始指令碼。

  • 生成一個隨機字元令牌。您可以使用 PHP 提供的幾個內建函式中的任何一個來生成隨機字串。讓我們使用 md5() 函式來獲取生成唯一隨機字串的 uniqueid() 函式的雜湊值。

  • 在要提供給使用者提交資料的 HTML 表單中,包含一個隱藏欄位,其值為上述步驟中生成的隨機令牌。

  • 然後,伺服器在表單提交後根據使用者會話驗證令牌,以消除惡意請求。

  • 您還可以新增另一個會話變數,其值為當前時間,併發送到期時間以進行驗證。

示例

以下是實現 CSRF 令牌驗證機制的 PHP 程式碼。以下指令碼生成令牌並將其嵌入到 HTML 表單中。

<?php
   session_start();
   if(!isset($_SESSION["csrf_token"])) {
   
      // No token present, generate a new one
      $token = md5(uniqid(rand(), true));
      $_SESSION["csrf_token"] = $token;
	  
   } else {
   
      // Reuse the token
      $token = $_SESSION["csrf_token"];        
   }
?>
<html>
<body>
   <form method="get" action="test.php">
      <input type="text" name="empcode" placeholder="empcode" />
      <input type="hidden" name="csrf_token" value="<?php echo $token;?>" />
      <input type="submit" />
   </form>
</body>
</html>

表單提交到以下“test.php”指令碼:

<?php
   session_start();
   echo "hello";
   if ($_GET["csrf_token"] == $_SESSION["csrf_token"]) {

      // Reset token
      echo $_GET["csrf_token"] . "<br>";
      echo $_SESSION["csrf_token"] . "<br>";
      echo "<h3>CSRF token validation successful. Proceed to further action</h3>";
   } else {
      echo "<h3>CSRF token validation failed</h3>";
   }
?>

它將產生以下輸出

PHP Csrf

要模擬 CSRF 驗證失敗,請開啟瀏覽器的檢查工具,手動編輯隱藏欄位中的值,然後提交表單,您將看到令牌不匹配,導致驗證失敗。

PHP – FastCGI 程序

PHP FastCGI 程序管理器 (PHP-FPM) 是處理 PHP 請求(尤其是在高流量環境中)的傳統基於 CGI 的方法的有效替代方案。PHP-FPM 具有許多重要功能。這些功能如下:

降低記憶體消耗

藉助用於處理請求的 worker 程序池,與為每個請求生成新程序的傳統 CGI 方法相比,PHP-FPM 大大降低了記憶體開銷。

效能提升

PHP-FPM 的 worker 程序是持久的。它允許它們處理多個請求。它不需要重複建立和銷燬程序。這導致響應時間更快,並且可以更好地處理高併發。

可擴充套件性增強

PHP-FPM 的 worker 程序池可以根據流量需求動態調整,使其能夠有效地擴充套件以處理不同的工作負載。

高階程序管理

PHP-FPM 提供優雅的啟動和關閉功能。它還對程序管理具有精細的控制,包括緊急重啟和工作程序監控。

環境隔離

PHP-FPM 允許為不同的應用程式或使用者組建立單獨的程序池,從而為每個環境提供更好的隔離和安全性。

可自定義配置

PHP-FPM 使用基於 php.ini 的配置選項。透過這些廣泛的選項,可以微調其行為以匹配特定的應用程式需求。

支援多個 PHP 版本

PHP-FPM 可以同時管理多個 PHP 版本,從而能夠在一臺伺服器上部署不同的 PHP 應用程式。

PHP-FPM 通常與 Nginx 或 Apache 等 Web 伺服器一起使用。它充當處理 PHP 請求的後端處理器。由於其效能、可擴充套件性和可靠性,它已成為在生產環境中管理 PHP 應用程式的首選方法。

PHP – PDO 擴充套件

PDO 是 PHP 資料物件的縮寫。PHP 可以與大多數關係型和 NoSQL 資料庫互動。預設的 PHP 安裝已經安裝並啟用了特定於供應商的資料庫擴充套件。除了特定於某種型別資料庫的資料庫驅動程式(例如 MySQL 的 mysqli 擴充套件)之外,PHP 還支援 PDO 和 ODBC 等抽象層。

PDO 擴充套件定義了一個輕量級、一致的介面,用於在 PHP 中訪問資料庫。每個特定於供應商的擴充套件的功能都各不相同。因此,如果您打算更改某個 PHP 應用程式的後端資料庫(例如,從 PostGreSql 更改為 MySQL),則需要對程式碼進行大量更改。另一方面,PDO API 只需要指定要使用的新的資料庫的 URL 和憑據,而無需進行任何其他更改。

您的當前 PHP 安裝必須具有相應的 PDO 驅動程式才能工作。目前,以下資料庫支援相應的 PDO 介面:

驅動程式名稱 支援的資料庫
PDO_CUBRID Cubrid
PDO_DBLIB FreeTDS / Microsoft SQL Server / Sybase
PDO_FIREBIRD Firebird
PDO_IBM IBM DB2
PDO_INFORMIX IBM Informix Dynamic Server
PDO_MYSQL MySQL 3.x/4.x/5.x/8.x
PDO_OCI Oracle 呼叫介面
PDO_ODBC ODBC v3 (IBM DB2, unixODBC 和 win32 ODBC)
PDO_PGSQL PostgreSQL
PDO_SQLITE SQLite 3 和 SQLite 2
PDO_SQLSRV Microsoft SQL Server / SQL Azure

預設情況下,PDO_SQLITE 驅動程式在 php.ini 的設定中已啟用,因此,如果您希望使用 PDO 與 MySQL 資料庫互動,請確保透過刪除前面的分號取消以下行的註釋。

extension=pdo_mysql

您可以透過呼叫 PDO 類中的 PDO::getAvailableDrivers() 靜態函式來獲取當前可用 PDO 驅動程式的列表。

PDO 連線

PDO 基類的例項表示資料庫連線。建構函式接受用於指定資料庫源(稱為 DSN)的引數,以及可選的使用者名稱和密碼(如果有)。

以下程式碼段是建立與 MySQL 資料庫連線的典型方法:

<?php
   $dbh = new PDO('mysql:host=localhost;dbname=test', $user, $pass);
?>

如果存在任何連線錯誤,將丟擲 PDOException 物件。

示例

請看以下示例:

<?php  
   $dsn="localhost";  
   $dbName="myDB";  
   $username="root";       
   $password="";     
   try{  
      $dbConn= new PDO("mysql:host=$dsn;dbname=$dbName",$username,$password);  
      Echo "Successfully connected with $dbName database";  
   } catch(Exception $e){  
      echo "Connection failed" . $e->getMessage();  
   }
?>

它將產生以下輸出

Successfully connected with myDB database

錯誤情況下:

Connection failedSQLSTATE[HY000] [1049] Unknown database 'mydb'

PDO 類方法

PDO 類定義了以下靜態方法:

PDO::beginTransaction

獲取連線物件後,應呼叫此方法來啟動事務。

public PDO::beginTransaction(): bool

此方法關閉自動提交模式。因此,您需要呼叫 commit() 方法才能對資料庫進行永續性更改。呼叫 rollBack() 將回滾對資料庫的所有更改並將連線返回到自動提交模式。此方法在成功時返回 true,失敗時返回 false。

PDO::commit

commit() 方法提交事務。

public PDO::commit(): bool

由於 BeginTransaction 停用了自動提交模式,因此您應該在事務後呼叫此方法。它提交事務,將資料庫連線返回到自動提交模式,直到下次呼叫 PDO::beginTransaction() 啟動新事務為止。此方法在成功時返回 true,失敗時返回 false。

PDO::exec

exec() 方法執行 SQL 語句並返回受影響的行數

public PDO::exec(string $statement): int|false

exec() 方法在一個函式呼叫中執行 SQL 語句,返回受語句影響的行數。

請注意,它不返回 SELECT 語句的結果。如果您有一個僅在程式中執行一次的 SELECT 語句,請考慮使用 PDO::query()。

另一方面,對於需要多次執行的語句,請使用 PDO::prepare() 準備 PDOStatement 物件,並使用 PDOStatement::execute() 執行語句。

exec() 方法需要一個字串引數,該引數表示要準備和執行的 SQL 語句,並返回由您發出的 SQL 語句修改或刪除的行數。如果未受影響的行,PDO::exec() 返回 0。

PDO::query

query() 方法準備和執行不帶佔位符的 SQL 語句

public PDO::query(string $query, ?int $fetchMode = null): PDOStatement|false

此方法在一個函式呼叫中準備和執行 SQL 語句,並將語句作為 PDOStatement 物件返回。

PDO::rollBack

rollback() 方法回滾由 PDO::beginTransaction() 啟動的事務。

public PDO::rollBack(): bool

如果資料庫設定為自動提交模式,則此函式將在回滾事務後恢復自動提交模式。

請注意,包括 MySQL 在內的一些資料庫在事務中發出 DDL 語句(例如 DROP TABLE 或 CREATE TABLE)時會自動發出隱式 COMMIT,因此它將阻止您回滾事務邊界內的任何其他更改。此方法在成功時返回 true,失敗時返回 false。

示例

以下程式碼在 MySQL 伺服器上的 myDB 資料庫中建立一個 student 表。

<?php  
   $dsn="localhost";  
   $dbName="myDB";  
   $username="root";       
   $password="";     
   try{  
      $conn= new PDO("mysql:host=$dsn;dbname=$dbName",$username,$password);  
      Echo "Successfully connected with $dbName database";  
      $qry = <<<STRING
      CREATE TABLE IF NOT EXISTS STUDENT (
         student_id INT AUTO_INCREMENT,
         name VARCHAR(255) NOT NULL,
         marks INTEGER(3),
         PRIMARY KEY (student_id)
      );
      STRING;
      echo $qry . PHP_EOL;
      $conn->exec($qry);
      $conn->commit();
      echo "Table created\n";
   } 
   catch(Exception $e){  
      echo "Connection failed : " . $e->getMessage();  
   }  
?>

示例

使用以下程式碼在上面示例中建立的 student 表中插入新記錄:

<?php  
   $dsn="localhost";  
   $dbName="myDB";  
   $username="root";       
   $password="";     
   try {  
      $conn= new PDO("mysql:host=$dsn;dbname=$dbName",$username,$password);  
      echo "Successfully connected with $dbName database";  

      $sql = "INSERT INTO STUDENT values(1, 'Raju', 60)";
      $conn->exec($sql);
      $conn->commit();
      echo "A record inserted\n";
   } catch(Exception $e){  
      echo "Connection failed : " . $e->getMessage();  
   }  
?>

示例

以下 PHP 指令碼獲取 student 表中的所有記錄:

<?php  
   $dsn="localhost";  
   $dbName="myDB";  
   $username="root";       
   $password="";   
   try {  
      $conn= new PDO("mysql:host=$dsn;dbname=$dbName",$username,$password);  
      echo "Successfully connected with $dbName database";  
      $sql = "SELECT * from student";
      $statement = $conn->query($sql);
      $rows = $statement->fetchAll(PDO::FETCH_ASSOC);

      foreach ($rows as $row) {
         var_dump($row);
      }        
   } catch(Exception $e){
      echo "Connection failed : " . $e->getMessage();  
   }  
?>

PHP - 函式參考

PHP 在內建函式方面非常豐富。以下是各種重要函式類別的列表。此處未涵蓋其他各種函式類別。

選擇一個類別以檢視與該類別相關的所有函式的列表。

廣告