# 字符串函數
[toc]
## 1. 字符串語法
- 字符串上限: 2G
- 字符串中每個字符使用一個字節表示,僅支持 256 個,不支持`Unicode`
- 有四種方式創建字符串
| 序號 | 方式 | 描述 |
| ---- | ------- | ------------------------ |
| 1 | 單引號 | 全部內容視為純文本 |
| 2 | 雙引號 | 可解析變量和轉義特殊字符 |
| 3 | heredoc | 與雙引號類似 |
| 4 | nowdoc | 與單引號類似 |
### 1.1 單引號
| 單引號 | 轉義符 | 特殊字符 | 變量 |
| ------ | ------ | -------- | ------ |
| 轉義 | 轉義 | 不轉義 | 不解析 |
### 1.2 雙引號
- 雙引號對內容的處理
| 雙引號 | 轉義符 | 特殊字符 | 變量 |
| ------ | ------ | -------- | ---- |
| 轉義 | 轉義 | 轉義 | 解析 |
- 雙引號中的變量, 應該使用大括號`{}`限定標識符識別范圍,如: "{\$email}"
- 雙引號中的特殊字符列表
| 序號 | 特殊字符 | 描述 |
| ---- | -------------------- | ----------------------------------------------------------------- |
| 1 | `\n` | 換行(ASCII 字符集中的 LF 或 0x0A (10)) |
| 2 | `\r` | 回車(ASCII 字符集中的 CR 或 0x0D(13)) |
| 3 | `\t` | 水平制表符(ASCII 字符集中的 HT 或 0x09 (9)) |
| 4 | `\v` | 垂直制表符(ASCII 字符集中的 VT 或 0x0B (11))(自 PHP 5.2.5 起) |
| 5 | `\e` | Escape(ASCII 字符集中的 ESC 或 0x1B (27))(自 PHP 5.4.0 起) |
| 6 | `\f` | 換頁(ASCII 字符集中的 FF 或 0x0C (12))(自 PHP 5.2.5 起) |
| 7 | `\\` | 反斜線 |
| 8 | `\$` | 美元標記 |
| 9 | `\"` | 雙引號 |
| 10 | `\[0-7]{1,3}` | 符合該正則表達式序列的是一個以八進制方式來表達的字符 |
| 11 | `\x[0-9A-Fa-f]{1,2}` | 符合該正則表達式序列的是一個以十六進制方式來表達的字符 |
### 1.3 heredoc
| 雙引號 | 轉義符 | 特殊字符 | 變量 |
| ------ | ------ | -------- | ---- |
| 不轉義 | 不轉義 | 轉義 | 解析 |
### 1.4 nowedoc
| 單引號 | 轉義符 | 特殊字符 | 變量 |
| ------ | ------ | -------- | ------ |
| 不轉義 | 不轉義 | 不轉義 | 不解析 |
示例代碼: `demo7.html`
```php
<?php
# 字符串
// 1. 單引號
// 轉義符反斜線只轉義自身和單引號
// 轉義符不轉義特殊字符
// 不解析內部變量
$str = 'string';
echo 'This \'s a \r\n $str \\';
echo '<hr>';
// 2. 雙引號
// 轉義符反斜線只轉義自身, 雙引號, 特殊字符
// 解析內部變量
echo "This \"s a \r\n {$str} \\";
echo '<hr>';
// 3. heredoc
// 功能與雙引號定義的字符串類似, 內部雙引號不需要轉義
// 標識符HELLO起始與結束符后必須換行,不能有任何輸出,包括空格
// 標識符HELLO的定界符雙引號,可以省略, 默認就是Heredoc
echo <<< "HELLO"
This "s a \r\n $str \\
HELLO;
echo '<hr>';
// heredoc: 特別適合輸出大量的html代碼,例如html與php混編的模板文件
$book = ['id' => 123, 'name' => 'php開發指南', 'price' => 99];
echo <<< BOOK
<ul style="list-style: none;">
<li>ID: {$book['id']}</li>
<li>書名: {$book['name']}</li>
<li>價格: {$book['price']}</li>
</ul>
BOOK;
echo '<hr>';
// 4. nowdoc
// 功能與單引號字符串類似, 內部單引號不需要轉義
// 轉義符就是普通字符
echo <<< 'EOT'
This 's a \r\n $str \;
EOT;
echo '<hr>';
// nowdoc非常適合嵌入大段php代碼或大段不需要轉義特殊字符,也不需要解析變量的文本
// 經常用于初始化類屬性和類常量等需要靜態數據的場合
class Demo
{
const STR = <<< 'FOO'
mail: admin@php.cn <br>
qq: 498668472 <br>
work-unit: php中文網 <br>
FOO;
}
echo Demo::STR;
```
---
## 2. 打印輸出函數
| 序號 | 函數 | 說明 |
| ---- | ------------- | -------------------------------- |
| 1 | echo | 輸出一個或多個字符串 |
| 2 | print | 輸出字符串 |
| 3 | printf | 輸出格式化字符串 |
| 4 | vprintf | 與 printf()區別在于參數在數組中 |
| 5 | sprintf | 返回格式化字符串,存入變量/文件中 |
| 6 | vsprintf | 與 sprintf()區別在于參數在數組中 |
| 7 | fprintf | 將格式化字符串寫入文件流中 |
| 8 | vfprintf | 與 fprintf()區別在于參數使用數組 |
| 9 | sscanf | 根據指定格式解析輸入的字符 |
| 10 | number_format | 以千位分隔符方式格式化一個數字 |
示例代碼: `demo8.php`
```php
# 打印輸出函數
// printf(): 輸出格式化字符串
printf('SELECT * FROM `%s` LIMIT %d', 'staffs', 5);
echo '<br>';
// vprintf(),與printf()區別在于參數使用數組
vprintf('SELECT * FROM `%s` LIMIT %d', ['staffs', 15]);
echo '<hr>';
// sprintf(): 返回格式化字符串,可存入變量或文件中
echo sprintf('SELECT * FROM `%s` LIMIT %d', 'staffs', 25);
echo '<br>';
// vsprintf(): 與sprintf()區別在于參數使用數組
echo vsprintf('SELECT * FROM `%s` LIMIT %d', ['staffs', 35]);
echo '<hr>';
// fprintf(): 將格式化字符串寫入文件流中
$handle = fopen('test.txt', 'w') or die('open file fail');
fprintf($handle, 'SELECT * FROM `%s` LIMIT %d', 'staffs', 45);
echo file_get_contents('test.txt');
echo '<br>';
// vfprintf(): 與fprintf()區別在于參數使用數組,而不是獨立變量
$handle = fopen('test1.txt', 'w') or die('open file fail');
vfprintf($handle, 'SELECT * FROM `%s` LIMIT %d', ['staffs', 55]);
echo file_get_contents('test1.txt');
echo '<hr>';
// sscanf(): 按指定格式輸入數據
// 返回索引數組, 可通過list()將輸入的數據存入變量中
var_dump(sscanf('SN-123456', 'SN-%d'));
list($sn) = sscanf('SN-123456', 'SN-%d');
echo $sn;
echo '<hr>';
// number_format($num, 保留位數, 小數點符, 千位分隔符)
echo number_format(12345.67), '<br>'; // 12.345
echo number_format(12345.67, 2), '<br>'; // 12,345.67
echo number_format(12345.67, 2, '.', ''), '<br>'; // 12345.67
echo number_format(12345.67, 2, '.', ','), '<br>'; // 12,345.67
/**
* SELECT * FROM `staffs` LIMIT 5
* SELECT * FROM `staffs` LIMIT 15
* SELECT * FROM `staffs` LIMIT 25
* SELECT * FROM `staffs` LIMIT 35
* SELECT * FROM `staffs` LIMIT 45
* SELECT * FROM `staffs` LIMIT 55
* array(1) { [0]=> int(123456) } 123456
* 12,346
* 12,345.67
* 12345.67
* 12,345.67
*/
```
---
## 3 分割查詢與替換函數
### 3.1 第一組
| 序號 | 函數 | 說明 |
| ---- | -------------- | ------------------------------ |
| 1 | implode | 將一個一維數組的值轉化為字符串 |
| 2 | join | 別名 implode |
| 3 | explode | 使用一個字符串分割另一個字符串 |
| 5 | substr | 返回字符串的子串 |
| 6 | substr_count | 計算字串出現的次數 |
| 7 | substr_replace | 替換字符串的子串 |
| 8 | str_split | 將字符串轉換為數組 |
| 9 | str_getcsv | 解析 CSV 字符串為一個數組 |
示例代碼: `demo9.php`
```php
# 分割查詢與替換函數
// implode(),一維數組轉字符串
// 用指定字符將數組元素組裝成一個字符串返回
echo implode(', ', ['html', 'css', 'js', 'php']), '<br>';
echo join(', ', ['html', 'css', 'js', 'php']), '<br>';
echo '<hr>';
// explode(), 使用一個字符串分隔另一個字符串
print_r(explode(',', 'localhost,root,root,utf8,3306'));
echo '<br>';
// 只要前3個元素,剩下的全部存入第4個元素中
print_r(explode(',', 'localhost,root,root,utf8,3306', 4));
echo '<br>';
// 與list()配合,將數組元素轉為變量
list($host, $user, $pass) = explode(',', 'localhost,root,root,utf8,3306');
echo "$host, $user, $pass <br>";
echo '<hr>';
// substr($string, $start, $length): 返回字符串子串
echo substr('abcdef', 0), '<br>'; // abcdef
echo substr('abcdef', 2), '<br>'; // cdef
echo substr('abcdef', 2, 2), '<br>'; // cd
// 從最后一個開始返回到結束,即獲取最后一個
echo substr('abcdef', -1), '<br>'; // f
// 從倒數第3個開始,獲取到結束,即獲取最后三個
echo substr('abcdef', -3), '<br>'; // def
// 從倒數第3個開始,獲取2個
echo substr('abcdef', -3, 2), '<br>'; // de
echo '<hr>';
// substr_count($str,$needle, $offset, $length): 統計子串出現的次數
// 'is' 出現2次, 返回2
echo substr_count('This is a test', 'is'), '<br>';
// 從第4個字符開始計算`s is a test`,'is' 只出現1次, 返回1
echo substr_count('This is a test', 'is', 3), '<br>';
// 此時目標字符串中只剩下: `s i`, 'is'不存在了,返回: 0
echo substr_count('This is a test', 'is', 3, 3), '<br>';
echo '<hr>';
// substr_replace($string, $replace,$start,$length): 替換字符串中的子串
// 用子串替換掉原目標字符串
echo substr_replace('html,css,js,java', 'php', 0), '<br>';
// 將子串插入到目標字符串前面
echo substr_replace('html,css,js,java', 'php,', 0, 0), '<br>';
// 替換掉java
echo substr_replace('html,css,js,java', 'php', -4), '<br>';
// 刪除掉css
echo substr_replace('html,css,js,java', '', 5, 4), '<br>';
// 該函數支持數組參數
// 將數組中每一個字符串元素做為目標字符串,用子串統一替換
$res = substr_replace(['id:101', 'id:203', 'id:908'], '0', 3, 3);
// 返回數組,可以轉為字符串,便于查看
print_r($res);
echo implode('; ', $res), '<br>';
// 可以針對每一個元素內容進行個性化定制替換子串,如第2個替換子串是: '2',
$res = substr_replace(['id:101', 'id:203', 'id:908'], [1, 2, 3], 3, 3);
echo implode(';', $res), '<br>';
// 也可針對數組中每一個字符串元素,替換數量不同的字符
// id:101=>id:a01, id:203=>id:b3,替換2位,id:908=>id:c,3位被替換
$res = substr_replace(['id:101', 'id:203', 'id:908'], ['a', 'b', 'c'], 3, [1, 2, 3]);
echo implode(';', $res), '<br>';
echo '<hr>';
// str_split(): 將字符串轉為數組,可指定每個數組元素的寬度
print_r(str_split('php.cn'));
echo '<br>';
print_r(str_split('php.cn', 2));
// 不支持多字符,顯示亂碼
print_r(str_split('php中文網'));
// 中文用3字節表示,3個一組切割, 實際工作中用mb字符擴展解決
print_r(str_split('php中文網', 3));
echo '<hr>';
// str_getcsv()
// 對于外部csv文件,之前通過文件操作函數:fopen()+fgetcsv()完成
$f = fopen('test2.csv', 'r');
while ($res = fgetcsv($f)) {
print_r($res);
echo '<br>';
}
// 現在可以利用這個str_getcsv()同樣可以做到
// str_getcsv(): 返回一個csv字符串各部分內容組成的數組
print_r(str_getcsv('2, peter, peter@php.cn'));
echo '<br>';
// 打開csv將內容全部讀到一個字符串
$csvStr = file_get_contents('test2.csv');
// 將讀取的csv字符串按換行符分割為數組
$csvArr = explode("\n", $csvStr);
print_r($csvArr);
echo '<hr>';
// 遍歷這個csv數組,得到每一個csv數據項
foreach ($csvArr as $csv) {
print_r(str_getcsv($csv));
echo '<br>';
}
// 運行結果
// html, css, js, php
// html, css, js, php
// Array ( [0] => localhost [1] => root [2] => root [3] => utf8 [4] => 3306 )
// Array ( [0] => localhost [1] => root [2] => root [3] => utf8,3306 )
// localhost, root, root
// abcdef
// cdef
// cd
// f
// def
// de
// 2
// 1
// 0
// php
// php,html,css,js,java
// html,css,js,php
// html,js,java
// Array ( [0] => id:0 [1] => id:0 [2] => id:0 ) id:0; id:0; id:0
// id:1;id:2;id:3
// id:a01;id:b3;id:c
// Array ( [0] => p [1] => h [2] => p [3] => . [4] => c [5] => n )
// Array ( [0] => ph [1] => p. [2] => cn ) Array ( [0] => p [1] => h [2] => p [3] => ? [4] => ? [5] => ? [6] => ? [7] => ? [8] => ? [9] => ? [10] => ? [11] => ? ) Array ( [0] => php [1] => 中 [2] => 文 [3] => 網 )
// Array ( [0] => 1 [1] => admin [2] => admin@php.cn )
// Array ( [0] => 2 [1] => peter [2] => peter@php.cn )
// Array ( [0] => 3 [1] => jack [2] => jack@php.cn )
// Array ( [0] => 2 [1] => peter [2] => peter@php.cn )
// Array ( [0] => 1, admin, admin@php.cn [1] => 2, peter, peter@php.cn [2] => 3, jack, jack@php.cn )
// Array ( [0] => 1 [1] => admin [2] => admin@php.cn )
// Array ( [0] => 2 [1] => peter [2] => peter@php.cn )
// Array ( [0] => 3 [1] => jack [2] => jack@php.cn )
```
### 3.2 第二組
| 序號 | 函數 | 說明 |
| ---- | ------------ | ---------------------------------------- |
| 10 | str_pad | 使用另一個字符串填充字符串為指定長度 |
| 11 | str_repeat | 重復一個字符串 |
| 12 | str_replace | 子字符串替換 |
| 13 | str_ireplace | str_replace 的忽略大小寫版本 |
| 14 | strtr | 轉換指定字符 |
| 15 | str_shuffle | 隨機打亂一個字符串 |
| 16 | wordwrap | 打斷字符串為指定數量的字串 |
| 17 | trim | 去除字符串首尾處的空白字符(或者其他字符) |
| 18 | rtrim | 刪除字符串末端的空白字符(或者其他字符) |
| 19 | ltrim | 刪除字符串開頭的空白字符(或其他字符) |
| 20 | chop | rtrim 的別名 |
附錄 1: `trim()/ltrim()/rtrim()`去除的空白符列表
| 序號 | 空白符 | 描述 |
| ---- | -------- | ------------------------------ |
| 1 | `" "` | `(ASCII 32 (0x20))`,普通空格符 |
| 2 | `"\t"` | `(ASCII 9 (0x09))`,制表符 |
| 3 | `"\n"` | `(ASCII 10 (0x0A))` 換行符 |
| 4 | `"\r"` | `(ASCII 13 (0x0D))`回車符 |
| 5 | `"\0"` | `(ASCII 0 (0x00))`空字節符 |
| 6 | `"\x0B"` | `(ASCII 11 (0x0B))`垂直制表符 |
示例代碼: `demo10.php`
```php
# 分割查詢與替換函數: 第二部分
// str_pad(): 將字符串填充到指定長度
echo str_pad('php', 10, '='), '<br>';
// 默認填充到右邊,使用常量表示
echo str_pad('php', 10, '=', STR_PAD_RIGHT), '<br>';
echo str_pad('php', 10, '=', STR_PAD_LEFT), '<br>';
echo str_pad('php', 10, '=', STR_PAD_BOTH), '<br>';
echo '<hr>';
// str_repeat(): 重復一個字符串,用來做一些內容分隔或裝飾
echo str_repeat('-*-|', 10), '<br>';
// str_replace($search,$replace,$subject,$int): 子字符串替換, 非常有用
// 如果命名空間與類文件所有路徑形成了映射,可以用它將類文件路徑解析出來完成自動加載
echo str_replace('\\', DIRECTORY_SEPARATOR, '\app\home\Index.php') . '<br>';
echo str_replace('php', '*', 'php.cn,php,thinkphp', $count) . '<br>';
echo 'php被替換了 ' . $count . ' 次 <br>';
// 支持數組參數
// 例如設置一個違禁詞數組,來替換掉目標字符串的非法內容
// 將第一個參數: 搜索字符串,設置成數組
$search = ['交友', '廣告', '直播', '帶貨'];
echo str_replace($search, '***', '廣告代理, 直播教學,免費帶貨, 異性交友'), '<br>';
// 第二個參數也可以是數組,實現一對一的映射替換
$replace = ['***', '===', '###', '+++'];
echo str_replace($search, $replace, '廣告代理, 直播教學,免費帶貨, 異性交友'), '<br>';
echo '<hr>';
// strtr(): 轉換指定的字符,可使用數組批量轉換
// 'd'=>'p', 'o'=>'i',字符逐個替換
echo strtr('This is dog', 'do', 'pi'), '<br>';
// 第二個參數可以用數組,但鍵名必須是原字符,值為新字符
echo strtr('This is dog', ['d' => 'p', 'o' => 'i']), '<br>';
echo '<hr>';
// str_shuffle(): 隨機打亂一個字符串, 生成驗證碼很方便
echo str_shuffle('abcdefg') . '<br>';
echo '<hr>';
// wordwrap(): 打斷字符串為指定數量的字符串,true:到到達指定寬度之前打斷
echo wordwrap('This is a demo', 4, "<br>\n", true);
echo '<hr>';
// trim() 去掉字符串首尾的空白或指定字符,過濾無效輸入很有用
$str = ' This is a string ';
echo '原始字符串(包括空白) : ' . strlen($str) . '<br>';
echo '去掉空白: ' . strlen(trim($str)) . '<br>';
$str = '123898php.cn php中文網 this is site654312';
// 從字符串首尾去掉'12'
echo trim($str, '12') . '<br>';
// 從首尾去掉所有數字,可以使用范圍符, 如只去掉1到8之間的
echo trim($str, '1..5') . '<br>';
// 去掉所有數字
echo trim($str, '1..9') . '<br>';
// 和trim()類似功能的還有ltrim()和rtrim(),區域在于去掉空白符的方向不同
// ltrim(): 刪除字符串頭部的空白或指定字符, 也支持范圍符..
echo ltrim($str, '1..9') . '<br>';
// rtrim(): 刪除字符串尾部的空白或指定字符
echo rtrim($str, '1..9') . '<br>';
// chop()是rtirm()函數的別名, 只是語義化更強而已,沒卵用
echo chop($str, '1..9') . '<br>';
/*
* php=======
* php=======
* =======php
* ===php====
* -*-|-*-|-*-|-*-|-*-|-*-|-*-|-*-|-*-|-*-|
* /app/home/Index.php
* *.cn,*,think*
* php被替換了 3 次
* ***代理, ***教學,免費***, 異性***
* ===代理, ###教學,免費+++, 異性***
* This is pig
* This is pig
* edgcfba
* This
* is a
* demo
* 原始字符串(包括空白) : 21
* 去掉空白: 16
* 3898php.cn php中文網 this is site6543
* 898php.cn php中文網 this is site6
* php.cn php中文網 this is site
* php.cn php中文網 this is site654312
* 123898php.cn php中文網 this is site
* 123898php.cn php中文網 this is site
*/
```
### 3.3 第三組
| 序號 | 函數 | 說明 |
| ---- | ---------- | ------------------------------------------------------------ |
| 21 | strpos | 查找字符串首次出現的位置 |
| 22 | stripos | 查找字符串首次出現的位置(忽略大小寫) |
| 23 | strripos | 計算指定字符串在目標字符串中最后一次出現的位置(忽略大小寫) |
| 24 | strrpos | 計算指定字符串在目標字符串中最后一次出現的位置) |
| 25 | strstr | 查找字符串的首次出現 |
| 26 | stristr | strstr 函數的忽略大小寫版本 |
| 27 | strrchr | 查找指定字符在字符串中的最后一次出現 |
| 28 | strchr | 別名 strstr |
| 29 | strpbrk | 在字符串中查找一組字符的任何一個字符 |
| 30 | strspn | 計算字符串中全部字符都存在于指定字符集合中的第一段子串的長度 |
| 31 | strtolower | 將字符串轉化為小寫 |
| 32 | strtoupper | 將字符串轉化為大寫 |
| 33 | lcfirst | 使一個字符串的第一個字符小寫 |
| 34 | ucfirst | 將字符串的首字母轉換為大寫 |
| 35 | ucwords | 將字符串中每個單詞的首字母轉換為大寫 |
| 36 | strlen | 獲取字符串長度 |
| 37 | strrev | 反轉字符串 |
| 38 | strip_tags | 從字符串中去除 HTML 和 PHP 標記 |
示例代碼: `demo11.php`
```php
<?php
# 第三組
// strpos():返回指定字符串首次出現的位置,可指定查找起始索引
// 該函數可以用來快速查詢字符串是否存在某個子串
echo strpos('This is a test', 'is'), '<br>';
// 從指定索引位置開始查找,索引3開始,跳過了this
echo strpos('This is a test', 'is', 3), '<br>';
// strpos()大小寫敏感,此時應該換成它的忽略大小寫的版本
var_dump(strpos('This is a test', 'Is', 3));
echo '<br>';
// stripos()是strpos()的忽略大小寫的版本, 依然可以正確查找到
echo stripos('This is a test', 'Is', 3), '<br>';
echo '<hr>';
// strpos():返回指定字符串最后一次次出現的位置, 此時返回5,相當于反向查詢
echo strrpos('This is a test', 'is'), '<br>';
echo '<hr>';
// strstr(): 查詢字符首次出現的位置并返回它/false
// 返回 "."以及后面內容: ".jpg",用來判斷文件類型
echo strstr('images/banner1.jpg', '.'), '<br>';
// true: 返回"."之前的內容"images/banner1"
echo strstr('images/banner1.jpg', '.', true), '<br>';
// 如果只是判斷某個字符是否存在,推薦使用strpos()更快更方便
echo '<hr>';
// strpbrk(): 在字符串中查找一組字符的任何一個字符,返回該字符開始的子字符串
// "es"中, 先匹配到"s",所以返回以"s"起始的字符串
echo strpbrk('This is a test', 'es'), '<br>';
echo '<hr>';
// strspn()計算字符串中全部字符都存在于指定字符集合中的第一段子串的長度
echo strspn("42 is the answer to the 128th question.", "1234567890"), '<br>';
echo strspn("foo", "o", 1, 2), '<br>';
echo strspn('this is a test 0551-6688789', 'this is a') . '<br>';
echo '<hr>';
// strtolower(): 字符串全部轉小寫
// 這個很有用, 例如在switch()判斷,驗證碼轉換等,更多案例在開發實戰講解
echo strtolower('PHP.CN是國內最大的PHP開發資源分享平臺') . '<br>';
echo strtoupper('Hello World') . '<br>';
echo '<hr>';
// lcfirst(): 首字符小寫, 轉換標識符命名風格時會用到
echo lcfirst('UserName') . '<br>';
// ucfirst(): 首字母大寫, 動態生成類名稱時會用到
echo ucfirst('userController') . '.php' . '<br>';
echo '<hr>';
// strrev()反轉字符串
echo strrev('admin888') . '<br>';
// 生成密碼時可以增加復雜度,例如
echo md5(strrev('this is a password')) . '<br>';
echo '<hr>';
// strip_tags(): 刪除html和php標簽,僅保留純文本內容
echo strip_tags('<h2>Hello</h2><?php echo "World";?>');
/*
* 2
* 5
* bool(false)
* 5
* 5
* .jpg
* images/banner1
* s is a test
* 2
* 2
* 11
* php.cn是國內最大的php開發資源分享平臺
* HELLO WORLD
* userName
* UserController.php
* 888nimda
* 6a7b93da1adce2c2c314395f51ba3725
* Hello
*/
```
---
## 4. URL 處理函數
| 序號 | 函數 | 說明 |
| ---- | ---------------- | -------------------------------- |
| 1 | parse_str | 將字符串解析成多個變量,處理 url |
| 2 | parse_url | 解析 URL,返回其組成部分 |
| 3 | http_build_query | 生成 URL-encode 之后的請求字符串 |
| 4 | urldecode | 解碼已編碼的 URL 字符串 |
| 5 | urlencode | 編碼 URL 字符串 |
| 6 | base64_encode | MIME base64 數據解碼 |
| 7 | base64_decode | MIME base64 數據編碼 |
### 附錄 1: `$_SERVER`預定義變量
以 URL 為例: `http://php.io/case/demo12.php/m/admin/c/add?id=5&name=admin`
| 序號 | 變量 | 描述 | 示例 |
| ---- | ---------------------- | ----------------------------------- | ---------------------------------------- |
| 1 | `UNIQUE_ID` | HTTP 請求的唯一標識符 | Xn4DhH8AAAEAAAWiEO0AAAAB |
| 2 | `HTTP_HOST` | HTTP 主機名/域名 | php.io |
| 3 | `SERVER_ADDR` | HTTP 主機名 IP 地址 | 127.0.0.1 / 0:0:0:1 / ::1 |
| 4 | `SERVER_PORT` | Web 服務器使用的端口 | 80 |
| 5 | `REMOTE_PORT` | 用戶機器連接到 Web 服務器的端口號 | 52706 |
| 6 | `SERVER_NAME` | Appcha 配置的 ServerName | php.io |
| 7 | `DOCUMENT_ROOT` | 當前腳本所在的根目錄(配置文件中) | /Documents/web/php/case |
| 8 | `SCRIPT_FILENAME` | 當前執行腳本的絕對路徑 | /Documents/web/php/case/demo1.php |
| 9 | `SCRIPT_NAME` | 當前執行腳本的路徑與文件名 | /case/demo1.php |
| 10 | `PHP_SELF` | 當前腳本名(含 pathinfo) | /case/demo1.php/m/admin/c/add |
| 11 | `PATH_INFO` | 執行腳本與查詢字符串之間的路徑信息 | /m/admin/c/add |
| 12 | `PATH_TRANSLATED` | 腳本所在文件系統路徑(限 pathinfo) | /Documents/web/php/m/admin/c/add |
| 13 | `REQUEST_URI` | 當前訪問的 URL(pathinfo,查詢字符串) | case/demo1.php/m/admin/c/add?id=5&... |
| 14 | `QUERY_STRING` | 查詢字符串(不含前導問號`?`) | id=5&name=admin |
| 15 | `REQUEST_METHOD` | HTTP 請求類型 | POST / GET |
| 16 | `HTTP_REFERER` | 引導用戶進入當前頁面的 URL | 如果是直接進入當前頁,則不存在該值 |
| 17 | `HTTP_USER_AGENT` | 客戶端/瀏覽器信息`get_browser()` | Mozilla/5.0 (Macintosh; Intel Mac ... |
| 18 | `SERVER_SOFTWARE` | web 服務器軟件 | Apache |
| 19 | `SERVER_PROTOCOL` | web 服務器 HTTP 協議 | HTTP/1.1 |
| 20 | `GATEWAY_INTERFACE` | 網關接口:服務器使用 CGI 規范 | CGI/1.1 |
| 21 | `REQUEST_TIME` | HTTP 請求開始的時間戳 | 1585320730 |
| 22 | `REQUEST_TIME_FLOAT` | HTTP 請求開始的時間戳(微秒級) | 1585320730.803 |
| 23 | `argv` | 傳遞給腳本的參數數組 | Array ( [0] => id=5&name=admin ) |
| 24 | `argc` | 傳遞給腳本的參數數量 | 1 |
| 25 | `HTTP_ACCEPT` | 客戶端請求/接受文檔類型 | text/html,application/xhtml+xml,appli... |
| 26 | `HTTP_ACCEPT_ENCODING` | HTTP 壓縮 HTML 的編碼方式 | gzip, deflate |
| 27 | `HTTP_ACCEPT_LANGUAGE` | HTTP 接受的語言 | zh-CN,zh;q=0.9,en;q=0.8,ja;q=0.7 |
### 附錄 2: `urlencode()`:對 url 變量值進行編碼
| 除了`-\_.`之外的所有字符 | 空格 | 編碼方式 |
| ------------------------ | ---- | ----------------------------------- |
| `%`+2 位 16 進制數 | `+` | `application/x-www-form-urlencoded` |
### 附錄 3: `base64_encode()`:用 base64 對 data 進行編碼
- 為了使二進制數據可以通過非純 8-bit 的傳輸層傳輸,例如電子郵件的主體
- 下載鏈接, 圖片等都可以使用它進行加密處理
- 加密之后的數據比原始數據要多占據 33%的空間大小
### 附錄 4: Data URI Scheme(協議)
形如:`data:text/jpeg;base64,/9j/4AAQSkZJRgABA...` 這樣的資源鏈接
| 序號 | 協議 | 說明 |
| ---- | ------------------------------ | --------------------------- |
| 1 | `data:` | 文本數據 |
| 2 | `data:text/plain,` | 文本數據 |
| 3 | `data:text/html,` | HTML 代碼 |
| 4 | `data:text/css;base64,` | css 代碼 |
| 5 | `data:text/javascript;base64,` | javascript 代碼 |
| 6 | `data:image/x-icon;base64,` | base64 編碼的 icon 圖片數據 |
| 7 | `data:image/gif;base64,` | base64 編碼的 gif 圖片數據 |
| 8 | `data:image/png;base64,` | base64 編碼的 png 圖片數據 |
| 9 | `data:image/jpeg;base64,` | base64 編碼的 jpeg 圖片數據 |
示例代碼: `demo12.php`
```php
<?php
# URL處理函數
// parse_str($querystring,$array): 解析出查詢字符串的變量鍵值對
// http://php.io/demo12.php?id=5&name=admin&role=1
echo $querystring = $_SERVER['QUERY_STRING'] . '<br>';
parse_str($querystring, $queryArr);
print_r($queryArr);
echo '<hr>';
// parse_url():解析URL地址,返回協議,主機,腳本路徑和查詢字符串等信息
$url = 'http://php.io/demo12.php/m/admin/c/add?id=5&name=admin';
// echo '<pre>' . print_r($_SERVER, true) . '</pre>';
print_r(parse_url($url));
// Array ( [scheme] => http [host] => php.io [path] => /demo12.php [query] => id=5&name=admin )
echo '<hr>';
// http_build_query(): 生成經過urlencode()處理之后的查詢字符串
echo http_build_query(['name' => 'peter zhu', 'age' => 30]) . '<br>';
// 支持對象中的屬性, 僅轉換public公共屬性
echo http_build_query((new class
{
public $name = 'admin';
public $email = 'admin@php.cn';
private $gender = 'male';
protected $salary = 98989;
})) . '<br>';
echo '<hr>';
// urlencode(): 對url變量值進行編碼后,便于傳到下一頁面
// 除了 -_. 之外的所有非字母數字字符都將被替換成百分號(%)后跟兩位十六進制數
// 因歷史原因, 空格單獨編碼, 用加號"+"表示
// 編碼方式與post中的application/x-www-form-urlencoded一樣
$post = ['name' => 'peter zhu', 'email' => 'peter@php.cn'];
$name = urlencode($post['name']);
$email = urlencode($post['email']);
// 通常轉碼之后, 建議再用htmlentities(), 將html標簽和引號等轉為實體則更安全
$input = htmlentities("name={$name}&email={$email}");
echo $input . '<br>';
echo "<a href=\"register.php?{$input}\">注冊</a>";
// 輸出到控制臺查看一下URL編碼后的結果
echo '<script>console.log(document.querySelector("a").href)</script>';
// http://php.io/case/register.php?name=peter+zhu&email=peter%40php.cn
echo '<hr>';
// urldecode():對已編碼的URL解碼,將%+16進制數和"+"替換成原義字符
echo urldecode($input) . '<br>';
// base64_encode(): 二進制數據進行編碼后加密傳輸, 圖片是典型的2進制,以此為例
echo $img = base64_encode(file_get_contents('girl.jpg'));
// 顯示圖片
// 如果要在<img>標簽中顯示base編碼數據,需要使用HTTP URI Scheme資源鏈接協議
// 這種協議通過用在<a href="">....</a>或者<img src="...>
echo "<img src='data:image/jpeg;base64,{$img}'>" . '<br>';
// 對圖片進行 base64 編碼后,圖片能隨 HTML 一起傳輸到瀏覽器,可以減少 HTTP 請求
// 缺點是文檔體積變大,并且原圖修改后需要重新編碼不利于瀏覽器緩存加速,不利圖片復用等
// 如果一些古老的瀏覽器不支持DataURI,可以使用base64_decode()解碼
file_put_contents('girl2.jpg', base64_decode($img));
echo "<img src='girl2.jpg'>" . '<br>';
echo '<hr>';
```
---
## 5. HTML 相關
| 序號 | 函數 | 說明 |
| ---- | ----------------------- | -------------------------------------- |
| 1 | htmlspecialchars | 將特殊字符轉換為 HTML 實體 |
| 2 | htmlspecialchars_decode | 將特殊的 HTML 實體轉換回普通字符 |
| 3 | htmlentities | 將字符轉換為 HTML 轉義字符 |
| 4 | html_entity_decode | 將 HTML 實體轉換為它們相應的字符 |
| 5 | nl2br | 在字符串所有新行之前插入 HTML 換行標記 |
### 附錄 1: html 實體字符
- 某些字符在 html 文檔中有特殊意義,如`<>`用表示元素標簽,這些都是預留字符,不能直接使用
- 如果要在 html 文檔中正確顯示他們,需要將它們轉為**html 實體字符**,如`<`轉為`<`
- html 實體字符有二種表示方法: 1. 命名表示法,如`<`, 2. 編碼表示法, 如`&60;`
- 常用實體字符列表:
| 序號 | 描述 | 實體名稱 | 實體編碼 |
| ---- | ----- | ----------------- | ---------- |
| 1 | `' '` | 空格 | ` ` | ` ` |
| 2 | `<` | 小于號 | `<` | `<` |
| 3 | `>` | 大于號 | `>` | `>` |
| 4 | `&` | 和號 | `&` | `&` |
| 5 | `"` | 雙引號 | `"` | `"` |
| 6 | `'` | 單引號 | `'` | `'` |
| 7 | `¢` | 分(cent) | `¢` | `¢` |
| 8 | `£` | 鎊(pound) | `£` | `£` |
| 9 | `¥` | 元(yen) | `¥` | `¥` |
| 10 | `€` | 歐元(euro) | `€` | `€` |
| 11 | `§` | 小節 | `§` | `§` |
| 12 | `?` | 版權(copyright) | `©` | `©` |
| 13 | `?` | 注冊商標 | `®` | `®` |
| 14 | `?` | 商標 | `™` | `™` |
| 15 | `×` | 乘號 | `×` | `×` |
| 16 | `÷` | 除號 | `÷` | `÷` |
### 附錄 2: htmlspecialchars()轉換字符列表
| 序號 | 原字符 | 替換成 |
| ---- | ------ | -------- |
| 1 | `&` | `&` |
| 2 | `"` | `"` |
| 3 | `'` | `'` |
| 4 | `<` | `<` |
| 5 | `>` | `>` |
> 如果要轉換的字符超出以上列表,請使用: `htmlentities()`
### 附錄 3: 轉換時的 FLAG 常量
| 序號 | 常量 | 描述 |
| ---- | ---------------- | --------------------------------------- |
| 1 | `ENT_COMPAT` | 會轉換雙引號,不轉換單引號 |
| 2 | `ENT_QUOTES` | 既轉換雙引號也轉換單引號 |
| 3 | `ENT_NOQUOTES` | 單/雙引號都不轉換 |
| 4 | `ENT_SUBSTITUTE` | 替換無效的代碼單元序列為 Unicode 代替符 |
| 5 | `ENT_DISALLOWED` | 為文檔的無效代碼點替換為 Unicode 代替符 |
| 6 | `ENT_HTML401` | 以 HTML 4.01 處理代碼 |
| 7 | `ENT_XML1` | 以 XML 1 處理代碼 |
| 8 | `ENT_XHTML` | 以 XHTML 處理代碼 |
| 9 | `ENT_HTML5` | 以 HTML 5 處理代碼 |
示例代碼: `demo13.php`
```php
# html相關函數
// htmlspecialchars(): 將html標簽和引號等轉為html實體字符
$link = "<a href='edit.php?id=1&p=2'>\"編輯\"</a>";
echo htmlspecialchars($link) . '<br>';
// 默認只轉換雙引號, 不轉換單引號, 和下面語句等效
echo htmlspecialchars($link, ENT_COMPAT) . '<br>';
// <a href='edit.php?id=1&p=2'>"編輯"</a>
// 雙引號, 單引號都轉換,添加常量標志: ENT_QUOTES
echo htmlspecialchars($link, ENT_QUOTES) . '<br>';
// <a href='edit.php?id=1&p=2'>"編輯"</a>
echo '<hr>';
// htmlspecialchars_decode(),執行與 htmlspecialchars()反操作,實體符還原
// 注意, 中間單引號轉義一下,或者外層用雙引號也可以
$entities = '<a href=\'edit.php?id=1&p=2\'>"編輯"</a>';
echo htmlspecialchars_decode($entities);
// 不轉換雙引號: "編輯" (必須打開源代碼查看)
echo htmlspecialchars_decode($entities, ENT_NOQUOTES);
echo '<hr>';
// htmlentities(): 對比 htmlspecialchars()可以轉義更多的html特殊字符,如版權符
// 發現雙引號被轉換成了實體, 而單引號仍被忽略
echo htmlentities('<h3>\'10 × 5\' = 50</h3>"€" ?版權所有') . '<br>';
// <h3>'10 × 5' = 50</h3>"€" ©版權所有
// 與htmlspecialchars()一樣, 添加一個轉換常量就可以
echo htmlentities('<h3>\'10 × 5\' = 50</h3>"€" ?版權所有', ENT_QUOTES) . '<br>';
// <h3>'10 × 5' = 50</h3>"€" ©版權所有
echo '<hr>';
// 同樣, htmlentities()也有一個反操作函數: html_entity_decode();
$html = "<h3>'10 × 5' = 50</h3>"€" ©版權所有";
echo html_entity_decode($html) . '<hr>';
// nl2br()
// php字符串中的換行符\n,會被瀏覽器頁面解析成一個空格,起不到換行的顯示效果
// nl2br()可以將字符串的換行符"\n",替換成"<br>"標簽,起到視覺上的換行效果
$str = "html\ncss\njs\nphp";
// 全部顯示在一行, "\n"用空格代替了,并沒有換行效果
echo $str . '<br>';
// 換行符"\n",替換成了"<br>"標簽,可以正常顯示換行效果了 到源代碼中可以查看到
echo nl2br($str);
```
---
## 6. 轉碼相關函數
| 序號 | 函數 | 說明 |
| ---- | ---------------- | ----------------------------------------------------- |
| 1 | chr | 返回指定的字符 |
| 2 | ord | 轉換字符串第一個字節為 0-255 之間的值 |
| 3 | chunk_split | 將字符串分割成小塊 |
| 4 | bin2hex | 函數把包含數據的二進制字符串轉換為十六進制值 |
| 5 | hex2bin | 轉換十六進制字符串為二進制字符串 |
| 7 | convert_uuencode | 將所有(含 2 進制)字符串轉為可打印字符便于網絡安全傳輸 |
| 6 | convert_uudecode | 將 convert_uuencode 編碼的字符串解析還原(反操作) |
| 8 | count_chars | 返回字符串所用字符的信息(每個字符出現的次數) |
| 9 | quotemeta | 轉義元字符集: `. \ + * ? [ ^ ] ( $ )` |
- `count_chars()` 的模式符:
| 序號 | 模式符 | 說明 |
| ---- | ------ | ------------------------------------------------ |
| 1 | `0` | 以所有的每個字節值作為鍵名, 出現次數作為值的數組 |
| 2 | `1` | 與 0 相同,但只列出出現次數**大于零**的字節值 |
| 3 | `2` | 與 0 相同,但只列出出現次數**等于零**的字節值 |
| 4 | `3` | 返回由所有使用了的字節值組成的字符串 |
| 5 | `4` | 返回由所有未使用的字節值組成的字符串 |
- `quotemeta()`: 預定義的字符前添加反斜線`\`
- 預定義字符列表(在正則中具有特殊語義)
| 序號 | 字符 | 說明 |
| ---- | ------------ | ------ |
| 1 | `.` | 圓點 |
| 2 | `\` | 反斜線 |
| 3 | `+` | 加號 |
| 4 | `*` | 星號 |
| 5 | `?` | 問號 |
| 6 | `[]` | 方括號 |
| 7 | `^` | 脫字符 |
| 8 | `$` | 美元符 |
| 9 | `()` | 圓括號 |
示例代碼: `demo8.php`
```php
<?php
# 轉碼相關的字符串函數
// chr(): 輸出整數ACSII碼對應的字符
echo chr(80) . chr(72) . chr(80) . '<br>';
// ord(): 輸出字符對應的ASCII碼
echo ord('P') . ord('H') . ord('P') . '<br>';
// 隨機產生一個隨機字符串可以用到它,生成一些演示用戶名稱等
function rand_str(int $length): string
{
$str = '';
for ($i = 0; $i < $length; $i++) {
$str .= chr(random_int(97, 122));
}
return $str;
}
echo rand_str(10) . '<hr>';
// chunk_split(): 將字符串分割成指定大小的塊,并插入自定義字符串
// 默認每行76個字符, 未尾自動添加\r\n
// \r: 回到行首, \n: 到下一行,即新行
$str = chunk_split('abcdefghigklmnopqrstuvwxyz', 5);
// 分成5行顯示,
echo $str . '<br>';
// 瀏覽器頁面中看不到換行效果, 可以用nl2br()處理一下
echo nl2br($str);
// 這個函數經常用來將base64_encode()編碼轉成RFC 2045語義字符串
// echo chunk_split(base64_encode(file_get_contents('girl.jpg')));
echo '<hr>';
// bin2hex(): 包含數據的二進制字符串轉換為十六進制值
echo $hex = bin2hex('php.cn') . '<br>';
// 輸出: 7068702e636e
// 可以用pack()還原: H*: 表示高位在前
echo pack("H*", bin2hex('php.cn')) . '<br>';
// hex2bin(): 是bin2hex()反操作, 與pack()功能一樣
echo hex2bin('7068702e636e') . '<hr>';
// convert_uuencode():將所有(含 2 進制)字符串轉為可打印字符便于網絡安全傳輸
echo convert_uuencode("Hello World") . '<br>';
// +2&5L;&\@5V]R;&0` `
// convert_uudecode: convert_uuencode()反操作,還原數據
echo convert_uudecode("+2&5L;&\@5V]R;&0` `") . '<br>';
// convert_uudecode()參數建議使用變量而不是字面量, 以防止來回轉義出現語法錯誤
$url = convert_uuencode("https://www.php.cn");
echo convert_uudecode($url) . '<br>';
echo '<hr>';
// count_chars()
$str = 'this is a test';
// 模式1: 只列出字符串, 出現次數大于0的字節的值
// 鍵名:字符字節值(ASCII或其它編碼)
// 值: 字符出現的次數
echo '原始字符串: ' . $str . ' : <br>';
foreach (count_chars($str, 1) as $code => $count) {
echo chr($code) . ' 出現的次數是 : ' . $count . '<br>';
}
// quotemeta(): 轉義元字符集, `. \ + * ? [ ^ ] ( $ )`, 常用在正則操作中
// 此函數轉義在正則表達式中具有特殊含義的字符, preg_quote()
$id = $id ?? 1;
$salary = $salary ?? 10000;
// 轉義sql語句的元字符
$sql = "SELECT * FROM `staffs` WHERE (`id` > '{$id}' ) AND (`salary` < '{$salary}') LIMIT 5";
echo quotemeta($sql);
```
---
## 7. 哈希相關函數
| 序號 | 函數 | 說明 |
| ---- | --------- | ----------------------------- |
| 1 | md5_file | 計算指定文件的 MD5 散列值 |
| 2 | md5 | 計算字符串的 MD5 散列值 |
| 3 | sha1_file | 計算文件的 sha1 散列值 |
| 4 | sha1 | 計算字符串的 sha1 散列值 |
| 5 | crypt | 單向字符串散列 |
| 6 | crc32 | 計算一個字符串的 crc32 多項式 |
| 7 | str_rot13 | 對字符串執行 ROT13 轉換 |
示例代碼:
```php
// 字符串: 哈希相關函數
// md5_file(): 只要文件被修改過,這個值就會發生變化
echo 'demo8.php的md5 = ' . md5_file('demo8.php') . '<br>';
// md5_file(): 文件唯一標識符
// md5_file(): 判斷文件是否被修改過
// 獲取demo8.php文件的md5
// file_put_contents('md5file.txt', md5_file('demo8.php'));
// 檢查demo8.php是否被修改過,只要修改過,它的md5一定會發生變化
if (md5_file('demo8.php') === file_get_contents('md5File.txt')) {
echo '文件沒有被修改過';
} else {
echo '文件被修改過';
}
// 每個文件的md5完全不同的,所以在處理文件上傳時,可以檢查這個值,判斷是否重復上傳
```
---
## 8. 統計與比較函數
| 序號 | 函數 | 說明 |
| ---- | -------------- | -------------------------------------------------- |
| 1 | strspn | 返回字符串與掩碼中字符串匹配的字符數量 |
| 2 | strcspn | 返回第一個字符串中, 找到與掩碼字符之前的字符數量 |
| 3 | str_word_count | 返回字符串中單詞的使用情況 |
| 4 | substr_compare | 二進制安全比較字符串(從偏移位置比較指定長度) |
| 5 | strcmp | 二進制安全字符串比較 |
| 6 | strncmp | 二進制安全比較字符串開頭的若干個字符 |
| 7 | strcasecmp | 二進制安全比較字符串(不區分大小寫) |
| 8 | strncasecmp | 二進制安全比較字符串開頭的若干個字符(不區分大小寫) |
示例代碼:
```php
<?php
// 統計與比較函數
// strspn() 返回字符串與掩碼中字符串匹配的字符數量
// 第一段`hello`與掩碼字符集`hello`連續匹配上5個, 返回: 5, 'hello' === 'hello'
// 匹配過程
// 第一次, 'hello'中取出'h',在掩碼'hello'中查詢,是否存在,存在返回1
// 第二次, 'hello'中取出'e',在掩碼'hello'中查詢,是否存在,存在返回1, 并累加到前一個結果上
// 直到遇到"第一個掩碼中不存在的字符"(例如空格),則立即終止查詢,并返回與掩碼匹配到字符數量
echo strspn('hello world', 'hello'), '<br>';
// 'hello'中第一個字符'h'在掩碼就匹配失敗, 返回0, 直接退出
echo strspn('hello world', 'weoll'), '<br>';
// 返回5, 為什么?因為'hello'中的'll'與掩碼中的'l'連續匹配2次
echo strspn('hello world', 'aahelo'), '<br>';
// 看上去似乎應該匹配上,實際上卻返回0, 因為第一字符串中的第一個字符'h'在掩碼中就不存豐,直接退出
echo strspn('helloworld', 'world'), '<br>';
// 從第一個字符串的第3個字符開始與掩碼匹配,'l'匹配2次,'o'匹配1次,返回3
echo strspn('hello world', 'lo', 2), '<br>';
// 小案例: 驗證手機號字符合法性,手機號碼必須是"0-9"之間的一個數字字符,只要有一個不滿足就匹配失敗
// 利用第一個字符全部匹配則返回當前字符串長度的特征,做為條件進行判斷
$phone = '13845673456a';
if (strlen($phone) !== strspn($phone, '0123456789')) echo '號碼非法';
echo '<hr>';
// strcspn() 返回第一個字符串中, 找到與掩碼字符之前的字符數量
// 將第一個字符串中的字符依次取出與掩碼比對, 第一次h不匹配,第二次e不匹配, 第三次l匹配成功
// 前此, 在第一個字符串中找到匹配掩碼的'l'之前, 已經查詢過了2次,所以返回2
echo strcspn('hello world', 'l'), '<br>';
// 仍返回2, 原因是'hello world'中, 只比較二次到'l'時, 就在掩碼中找到了'l'匹配完成
echo strcspn('hello world', 'orl'), '<br>';
// 返回4, 在第一個字符串, 檢查到'o'時, 在掩碼字符串匹配成功, 于是返回'o'之前檢測過的字符數量
echo strcspn('hello world', 'wor'), '<br>';
// 也支持索引參數,設置從第一個字符串的起始索引與數量
// 因為在第一個字符串, 索引6就是'w',直接匹配成功,前面沒有比較過其它字符,返回0
echo strcspn('hello world', 'wor', 6), '<br>';
// 咱們稍微修改一下掩碼,去掉w, 此時返回1,是因為在掩碼中找到'o'時,已經檢查過了'w'一個字符
echo strcspn('hello world', 'or', 6), '<br>';
echo '<hr>';
// str_word_count(): 統計字符串單詞使用情部,忽略標點
$str = 'This is a demo.';
echo $str, '<br>';
// 第二個參數默認為0,返回單詞數量
echo '單詞數量: ' . str_word_count($str, 0) . '個. <br>';
echo '單詞數量: ' . str_word_count($str) . '個. <br>';
// 第二個參數:1, 返回單詞組成的索引數組
echo '<pre>' . print_r(str_word_count($str, 1), true) . '</pre>';
// 第二個參數:2, 返回單詞組成的關聯數組, 鍵名是單詞在字符串中的起始索引
echo '<pre>' . print_r(str_word_count($str, 2), true) . '</pre>';
// substr_compare(): 子串比較,檢查第一個字符串參數中是否存在第二個子串, 從偏移位置比較指定長度
// 注意, 一定要在第一個被比較的字符串中取出一定范圍的子串, 與第二個參數進行比較
// 如果第二個參數子串, 存在于第一個主串中, 則返回0, 通常我們只對返回0的結果感興趣
echo substr_compare('hello world', 'hello', 0, 3); // 0
echo substr_compare('hello world', 'hello', 0, 5); // 0
// 從主串索引6開始, 取前3位,與子串進行比較, 當然取5位進行完全匹配也可以
echo substr_compare('hello world', 'world', 6, 3); // 0
echo substr_compare('hello world', 'World', 6, 3); // 32,匹配失敗,因為大小寫敏感
echo substr_compare('hello world', 'World', 6, 3, true); // 參數true, 忽略大小寫比較
echo '<hr>';
// strcmp(): 字符串簡單比較
// 相等, 返回 0
echo strcmp('php', 'php') === 0 ? '相等<br>' : '不相等<br>';
// 大小寫敏感
echo strcmp('php', 'Php') === 0 ? '相等<br>' : '不相等<br>';
echo '<hr>';
// strncmp(): 與strcmp()功能一樣,只不過可以設置比較長度,注意中間多了一個`n`,可理解為`num`
// 只比較前3個字符,當然相等,當然比較前2個也是相等的
echo strncmp('php', 'php.cn', 3) === 0 ? '相等<br>' : '不相等<br>';
echo '<hr>';
// strcasecmp(): 忽略大小寫比較字符串
echo strcasecmp('php', 'Php') === 0 ? '相等<br>' : '不相等<br>';
echo '<hr>';
// strncasecmp(): 忽略大小寫比較字符串, 可以指定比較的字符串長度,與strncmp類似
echo strncasecmp('php', 'Php.cn', 2) === 0 ? '相等<br>' : '不相等<br>';
echo '<hr>';
```