
4.2 字符串操作
字符串操作在PHP编程中占有重要的地位,几乎所有输入与输出都会用到字符串。尤其在PHP项目开发过程中,为了实现某项功能,经常需要对某些字符串进行特殊处理,如获取字符串的长度、截取字符串、替换字符串等。在本节中将对PHP常用的字符串操作技术进行详细的讲解,并通过具体的实例加深对字符串函数的理解。
4.2.1 去除字符串首尾空格和特殊字符

用户在输入数据时,可能会无意中输入多余的空格,或在一些情况下,字符串前后不允许出现空格和特殊字符,此时就需要去除字符串中的空格和特殊字符。可以使用PHP中提供的trim()函数去除字符串左右两边的空格和特殊字符,也可以使用ltrim()函数去除字符串左边的空格和特殊字符,或使用rtrim()函数去除字符串右边的空格和特殊字符。
1. trim()函数
trim()函数用于去除字符串首尾处的空白字符(或其他字符)。trim()函数语法格式如下:

trim()函数的参数说明如下。
• str:操作的字符串。
• charlist:为可选参数,一般要列出所有希望过滤的字符,也可以使用“..”列出一个字符范围。如果不设置该参数,则所有可选字符都将被删除。如果trim()函数不指定charlist参数,则trim()函数将去除表4.1中的字符。
• 返回值:过滤后的字符串。
表4.1 不指定charlist参数的trim()函数去除的字符

学习笔记
除了以上默认的过滤字符列表,还可以在charlist参数中提供要过滤的特殊字符。
去除搜索框中字符串左右两边的空格
明日学院网站中有搜索课程和社区的功能,当在输入框中输入关键词并单击“搜索”按钮时,程序会先处理用户输入的关键词,将关键词左右的空格去除。使用trim()函数实现该功能,具体代码如下:

运行结果如图4.1所示。

图4.1 trim()函数去除左右空格
2. ltrim()函数
ltrim()函数用于去除字符串左边的空格或指定字符。ltrim()函数参数与trim()函数的参数相同。ltrim()函数语法格式如下:

例如,使用ltrim()函数去除字符串左边的空格及特殊字符“(:@_@”,代码如下:

结果如下:

3. rtrim()函数
rtrim()函数用于去除字符串右边的空格或指定字符。rtrim()函数语法格式如下:

例如,使用rtrim()函数去除字符串右边的空格及特殊字符“@_@:)”,代码如下:

结果如下:

4.2.2 获取字符串的长度

在PHP中常见的计算字符串长度的函数有:strlen()和mb_strlen()。当字符全是英文字符的时候,二者的功能是一样的。但是,当字符串中包含中文字符时,所占字节有所不同。先来了解一下英文字符和中文字符所占字节的情况。
数字、英文、小数点、下画线和空格占1字节,一个汉字可能会占2~4字节,具体占几字节取决于采用的什么编码。汉字在GBK/GB2312编码中占2字节,在UTF-8/unicode中一般占3字节(或2~4字节)。由于本书中所有文件均使用UTF-8编码,即一个汉字占3字节。
下面讲解如何使用strlen()函数和mb_strlen()函数获取指定字符串的长度。
1. strlen()函数
strlen()函数主要用于获取指定字符串的长度。strlen()函数语法格式如下:

参数和返回值如下。
• str:需要计算长度的字符串。
• 返回值:如果成功则返回字符串str的长度;如果str为空,则返回 0。
例如,使用strlen()函数来获取指定字符串的长度,代码如下:

在上述代码中“明日学院官方网站:”均为中文字符,每个中文字符占3字节,共占27字节。“www.mingrisoft.com”均为英文字符,每个英文字符占1字节,共占18字节。上述代码运行结果如下:

2. mb_strlen()函数
由于strlen()函数无法正确处理中文字符串,它得到的只是字符串所占的字节数,因此可以采用mb_strlen()函数来解决这个问题。
mb_strlen()函数主要用于获取指定字符串的长度。mb_strlen()函数语法格式如下:

参数和返回值如下。
• str:需要计算长度的字符串。
• encoding:字符编码。如果省略,则使用内部字符编码。
• 返回值:返回具有encoding编码的字符串$str包含的字符数。多字节的字符被记为1。如果给定的encoding无效则返回FALSE。
mb_strlen()函数的用法和strlen()函数的用法类似,只不过它有第二个可选参数用于指定字符编码。例如得到UTF-8的字符串$str的长度,可以用mb_strlen($str,'UTF-8')。如果省略第二个参数,则会使用PHP的内部编码,内部编码可以通过mb_internal_encoding()函数得到。
学习笔记
mb_strlen()函数并不是PHP核心函数,使用前需要确保在php.ini中加载了php_mbstring.dll,即确保“extension=php_mbstring.dll”这一行代码存在并且没有被注释掉,否则会出现未定义函数的问题。
判断注册的用户名是否为3~18位
明日学院注册页面中,用户注册时输入的用户名必须为3~18位中文字符或英文字符,既可以是全中文字符,又可以是全英文字符或者中英文字符混合。使用mr_strlen()函数实现该功能,代码如下:

运行结果如图4.2所示。

图4.2 判断用户名是否满足条件
4.2.3 截取字符串

PHP对字符串截取可以采用内置函数substr()和mb_substr()实现。通常使用substr()函数截取英文字符,mb_substr()函数截取中文字符或中英文混合字符。
1. substr()函数
substr()函数语法格式如下:

参数和返回值如下。
• str:指定字符串对象。
• start:指定开始截取字符串的位置。如果参数start为负数,则从字符串的末尾开始截取。
• length:可选参数,指定截取字符的个数,如果length为负数,则表示截取到倒数第length个字符。
• 返回值:返回提取的子字符串,或者在失败时返回FALSE。
学习笔记
substr()函数中,参数start的指定位置是从0开始计算的,即字符串中的第一个字符表示为0,如图4.3所示。

图4.3 start开始位置
使用substr()函数截取字符串中指定长度的字符,代码如下:

运行结果如下:

由于在UTF-8编码下,一个汉字占3字节,所以在使用substr()函数时,可能出现截取汉字不完整的情况。例如,使用substr()函数截取字符串“Hi明日科技”,代码如下:

上述代码中,start为0,length为7,即从第一个位置开始,截取7字节,如图4.4所示。由于在第7个字符位置,汉字“日”没有被截取完成,将会出现汉字乱码的情况,运行结果如图4.5所示。

图4.4 substr()函数截取

图4.5 substr()函数截取汉字乱码
2. mb_substr ()函数
针对substr()函数截取汉字乱码的问题,可以使用mb_substr()函数来解决。mb_substr()函数语法格式如下:

参数和返回值如下。
• str:从该string中提取子字符串。
• start:str中要截取的第一个字符的位置。
• length:可选参数,指定截取字符的个数,如果length为负数,则表示取到倒数第length个字符。
• encoding:字符编码。如果省略,则使用内部字符编码。
• 返回值:根据start和length参数返回str中指定的部分。
截取列表页中过长的标题
在明日学院网站“最新动态”专栏中,显示所有最新课程标题的列表。为了保持整个页面的合理布局,需要对一些超长标题进行部分显示,使用substr()函数截取超长文本的部分字符串,剩余的部分用“…”代替。具体代码如下:

运行结果如图4.6所示。

图4.6 mb_substr()函数截取字符串
4.2.4 检索字符串

PHP中提供了很多应用于字符串查找的函数,常用的有strstr()函数和strpos()函数。
1. strstr()函数
获取一个指定字符串在另一个字符串中首次出现的位置到后者末尾的子字符串。strstr()函数语法格式如下:

参数和返回值如下。
• haystack:指定从该字符串中进行搜索。
• needle:指定搜索的对象。如果needle不是一个字符串,那么它将被转化为整型并作为字符的序号来使用。
• before_needle:可选参数,默认为false。若为true,strstr()函数将返回needle在haystack中的位置之前的部分。
• 返回值:返回haystack字符串从needle第一次出现的位置开始到haystack结尾的字符串。
例如,获取“Hi明日科技”字符串中“明日”以后的内容。代码如下:

运行程序,实现结果如下:

学习笔记
strstr()函数区分字母的大小写,如果不区分大小写,则可以使用stristr()函数。
根据邮箱地址获取用户名和服务器名
使用strstr()函数,根据邮箱地址获取用户名和服务器名。代码如下:

运行结果如图4.7所示。

图4.7 strstr()函数获取用户名和服务器名
学习笔记
strstr()函数与其正好相反,该函数是从字符串倒序的位置开始检索字符串的。
2. strpos()函数
查找字符串首次出现的位置,返回数字首次出现的位置。strpos()函数语法格式如下:

参数和返回值如下。
• haystack:必要参数,指定从该字符串中进行搜索。
• needle:必要参数,指定搜索的对象。如果needle不是一个字符串,那么它将被转化为整型并作为字符的序号来使用。
• offset:可选参数,默认为0。如果提供了此参数,那么搜索会从字符串该字符数的起始位置开始统计。
• 返回值:返回needle存在于haystack字符串起始的位置。同时注意字符串位置是从0开始的,而不是从1开始的。如果没找到needle,那么将返回FALSE。
学习笔记
本函数区分字母的大小写,如果不区分大小写,则可以使用stripos()函数。
例如,获取“Hi明日科技”字符串中“明日”以后的内容。代码如下:

程序运行结果如下:

学习笔记
strrpos()函数与其正好相反,该函数用于计算指定字符串在目标字符串中最后一次出现的位置。strrpos()函数也区分大小写,如果不用区分大小写,则可以使用strripos()函数。
4.2.5 替换字符串

通过字符串的替换技术可以实现对指定字符串中的指定字符进行替换。字符串的替换技术可以通过以下两个函数实现:str_replace()函数和substr_replace()函数。
1. str_replace()函数
使用新的子字符串替换原始字符串中被指定要替换的字符串。str_replace()函数语法格式如下:

将所有在参数subject中出现的参数search以参数replace取代,参数&count表示取代字符串执行的次数。本函数区分大小写。
参数和返回值如下。
• search:必要参数,要搜索的值,可以使用array来提供多个值。
• replace:必要参数,指定替换的值。
• subject:必要参数,要被搜索和替换的字符串或数组。
• count:可选参数,如果被指定,则它的值将被设置为替换发生的次数。
• 返回值:替换后的字符串或数组。
例如,将文本中的指定字符串“某某”替换为**,并且输出替换后的结果,代码如下:

运行结果如下:

学习笔记
该函数在执行替换的操作时区分大小写,如果不需要对大小写加以区分,则可以使用str_ireplace()函数。
2. substr_replace()函数
对指定字符串中的部分字符串进行替换。substr_replace()函数语法格式如下:

参数和返回值如下。
• string:指定要操作的原始字符串,可以是字符串或数组。
• replacement:指定替换后的新字符串。
• start:指定替换字符串开始的位置。正数表示替换从字符串的第start位置开始;负数表示替换从字符串的倒数第start位置开始;0表示替换从字符串中的第一个字符开始。
• length:可选参数,指定返回的字符串长度。默认值是整个字符串。正数表示被替换的子字符串的长度;负数表示待替换的子字符串结尾处距离字符串末端的字符个数;0表示将repl插入string的start位置处。
• 返回值:返回结果字符串。如果string是个数组,那么也将返回一个数组。
学习笔记
如果参数start设置为负数,而参数length数值小于或等于start数值,那么length的值自动为0。
将手机号中间4位数字用****替换
明日学院网站举办抽奖活动,活动结束后将获奖用户姓名和手机号公布在网站上,为保护用户隐私,将获奖用户的手机号中间4位用****替换,实现该功能的代码如下:

运行结果如图4.8所示。

图4.8 substr_replace()函数替换手机号
4.2.6 分割字符串、合成字符串

在PHP中提供了分割字符串和合成字符串的函数,它们都与数组相关。数组就是一组数据的集合,把一系列数据组织起来,形成一个可操作的整体。数组的知识会在第5章讲解,先来了解一下如何分割字符串和合成字符串。
1. 分割字符串
explode()函数按照指定的规则对一个字符串进行分割,返回值为数组。explode()函数语法格式如下:

参数和返回值如下。
• delimiter:边界上的分隔字符。
• string:指定将要被进行分割的字符串。
• limit:可选参数,如果设置了limit,则返回的数组最多包含limit个元素,而最后的元素将包含$string的剩余部分。
• 返回值:此函数返回由字符串组成的array,每个元素都是string的一个子串,它们被字符串 delimiter作为边界点分割出来。
输出被@的好友名称
在微博@好友时,输入“@mr @mrsoft @明日科技”(好友名称之间用一个空格区分),即可同时@三个好友,使用explode()函数,输出被@的好友名称。实现该功能的代码如下:

运行结果如图4.9所示。

图4.9 输出被@的好友名称
学习笔记
在默认情况下,数组第一个元素的索引为0。关于数组的相关知识将在第5章中进行详细讲解。
2. 合成字符串
implode()函数可以将数组的内容组合成一个新字符串。implode()函数语法格式如下:

参数和返回值如下。
• glue:指定分隔符。
• pieces:指定要被合并的数组。
• 返回值:返回一个字符串,其内容为由glue分割开的数组的值。
例如,使用implode()函数将数组中的内容以@为分隔符进行连接,从而组合成一个新的字符串,代码如下:

结果为:

学习笔记
implode()函数和explode()函数是两个相对的函数,implode()函数用于合成字符串,explode()函数用于分割字符串。