十年网站开发经验 + 多家企业客户 + 靠谱的建站团队
量身定制 + 运营维护+专业推广+无忧售后,网站问题一站解决
本文实例讲述了thinkphp5框架扩展redis类方法。分享给大家供大家参考,具体如下:
成都创新互联公司10多年成都企业网站建设服务;为您提供网站建设,网站制作,网页设计及高端网站定制服务,成都企业网站建设及推广,对电动窗帘等多个方面拥有丰富设计经验的网站建设公司。
笔者在开发时发现,thinkphp5的自带redis类方法,只有简单的读取缓存、写入缓存的基本方法,远不能满足我们业务的需求。redis本身支持五种数据类型,string(字符串)、hash(哈希)、list(列表)、set(集合)、zset(有序集合)。redis的东西就不必再介绍了,接下来还是让我一起扩展thinkphp5的redis方法吧!
首先我们先找到缓存驱动类里的,handler()方法,这个方法是返回Redis类的实例化对象的。
这就是实例化对象,包括了options配置项、handler资源句柄、tag标签。实际上这里的handler是new
Redis()的对象实例。只要在外部拿到handler资源句柄,则可以对redis的操作进行扩展了。
在cache类里新增一个getHandler方法。
然后我们就可以在控制器调用了
打印的就是这个redis对象了
这里需要注意的是:
一个是调thinkphp5的redis的方法,就是这样用。
一个是如果你要调用原生的redis方法
基本的用法都讲完了。
接下来就愉快的开始扩展redis方法吧。
先找到这个类
这个类里并没有list的相关操作方法,那我们就来扩展list的相关方法。
这里的话,我就举一个例子了。
在控制器里去调用
这样就写入成功了。
更多关于thinkPHP相关内容感兴趣的读者可查看本站专题:《ThinkPHP入门教程》、《thinkPHP模板操作技巧总结》、《ThinkPHP常用方法总结》、《codeigniter入门教程》、《CI(CodeIgniter)框架进阶教程》、《Zend
FrameWork框架入门教程》及《PHP模板技术总结》。
希望本文所述对大家基于ThinkPHP框架的PHP程序设计有所帮助。
您可能感兴趣的文章:针对thinkPHP5框架存储过程bug重写的存储过程扩展类完整实例ThinkPHP行为扩展Behavior应用实例详解ThinkPHP应用模式扩展详解ThinkPHP框架设计及扩展详解ThinkPHP的Widget扩展实例老生常谈ThinkPHP中的行为扩展和插件(推荐)TP5(thinkPHP5)框架mongodb扩展安装及特殊操作示例thinkPHP下的widget扩展用法实例分析thinkPHP3.2.2框架行为扩展及demo示例ThinkPHP5.0框架验证码功能实现方法【基于第三方扩展包】thinkphp5框架实现的自定义扩展类操作示例
PHP基础
Author:陈庆平 (Andych)
E-mail:ahut9923@126.com
一、PHP入门
二、PHP变量
1、php变量的命名
变量由字母,数字,下划线组成
1)变量名区分大小写
2)变量名必须以$开头
3)不能以数字开头
4)不能是系统关键字
$example , $sut_name , $stu_name_2
2、如何申明变量
$stu_name;
$stu_name,$stu_age;
二、PHP变量
3、判断变量是否设置
isset() 判断变量是否设置,返回true或false
4、定义常量
define(“”,常量值)
defined() 判断常量是否设置,返回true 或 false
三、PHP数据类型
变量的数据类型
1)布尔型(boolean)
2) 整型
3)浮点型
4)字符串型
5)数组
6)对象
7)空值
8)资源
三、PHP数据类型
算术运算符
逻辑运算符
比较运算符
赋值运算符
加一/减一运算符
四、运算符
逻辑运算符
赋值运算符
三元运算符
格式: 表达式?结果1:结果2
$c = $a$b ? “good”:”bad”
PHP基础
Author:陈庆平 (Andych)
E-mail:ahut9923@126.com
一、PHP流程控制语句
1、分支结构
格式1:
if语句
if(条件)
{
语句集;
}
一、PHP流程控制语句
格式2:
if(条件){
语句集;
}else{
语句集;
}
一、PHP流程控制语句
格式3:
If(条件1)
{
语句集1;
}else if(条件2)
{
语句集2;
}
一、PHP流程控制语句
多分支结构:
switch语句
格式:
switch(表达式)
{ case 常量: 语句;break;
case 常量2: 语句;break;
……….
default: 语句;break;
}
一、PHP流程控制语句
2、循环结构
While循环
While(表达式)
{
语句集;
}
一、PHP流程控制语句
for循环
for(表达式1; 表达式2; 表达式3)
{
语句集;
}
一、PHP流程控制语句
break 和 continue 语句
break 强行终止当前循环
continue 终止当前执行语句,继续执行循环
的下一句
PHP
Author: 陈庆平(Andych)
E-mail:ahut9923@126.com
PHP
• 数组
分类: 枚举数组、关联数组和多维数组
枚举数组:下标为整数的数组
例如:$stu[1] = “ 张三”
关联数组:用字符串做为下标的数组
例如:$stu[“name”] = “ 张三”
PHP
• 数组初始化
$stu[] = “name”
$stu[] = “sex”
注意:数组下表不需要按顺序分配
例题:排序数组元素(任意10 个数排
序)
PHP
• 使用array 函数
例如:
$stu = array(“james”,”jack”,”Toms”)
数组的起始下标可以不从0 开始
$stu = array(2=”james”,”jack”,”Toms”)
表示下标从2 开始
PHP
$arr = array[“name”=”james”,”sex”=”boy”]
• 数组的应用
1 、unset() 删除数组元素
unset($arr) 删除整个数组
unset($arr[0]) 删除单个数组元素
PHP
2 、foreach() 遍历整个数组
foreach($arr as $value)
输出数组中的元素
foreach($arr as $key=$value)
输出数组中的下标和元素
PHP
• each() 返回数组中当前的键/值对并
将数组指针向前移动一步
返回4个值 0,1,key 和 value
如:$arr = array(4="Test
user","Toms","Andych");
$foo = each($arr);
print_r($foo);
结果:
Array ( [1] = Test user [value] = Test user [0] = 4 [key] = 4 )
PHP
• list() 把数组中的值赋给一些变量
如:list($var) = $arr
注意:list 函数仅用于数组下标从0 开始
的数组
• current() 返回数组中当前元素
如:current($arr)
PHP
next() 将数组的指针移到下一个元素上
如:next($arr)
prev() 将数组的指针移到上一个元素上
如:prev($arr)
range() 自动生成一个包含指定范围单元的
数据
如:range(0,40)
PHP
count() 统计数组中元素个数
如:count($arr)
array_count_values() 统计数组中相同
元素的个数
PHP 函数
• 函数
独立完成特定功能的代码块
• 内置函数
1 、echo() 输出一个或多个字符串
如:echo “ 程序设计基础”
PHP 函数
2 、print() 输出字符串
如:print(“PHP 程序设计”)
用法同echo
注意:
35?print(“ 错误的逻辑”):print(“ 正确的逻辑”)
PHP 函数
Print start
// 任意行文字,可以包含HTML 代码
start;
输出任意行字符串
3 、include() 包含一个文件
如:include(“a.php”)
PHP 函数
include包含的文件中return语句的使用
$b = include(“a.php”);
If($b==“ok”)
{
echo “File is Ok”;
}
a.php文件
?return “ok”?
注意:在包含文件中函数执行到return将会终止。
PHP 函数
4、require() 包含一个文件
如:require(“a.php”)
功能同include方法一样
• 用户自定义函数
1、函数声明
Function func_name($args)
{
//函数体
}
PHP 函数
关键字含义:
function:用于声明自定义函数的关键字
Func_name:声明的函数名
$args:参数名称
1、定义无参函数
function fun()
{
Echo “定义无参数函数”;
}
PHP 函数
2 、定义有参函数
(1 )按值传递
$num = 100;
Function func($a)
{
$a = $a*10;
}
Func($num)
PHP 函数
(2) 按地址传递
$num = 100;
Function func($b)
{
$b = $b + 10;
}
Func($sum);
修改如下参数php.ini
allow_call_time_pass_reference = on
PHP 函数
(3)默认值传递
function func($a,$num=100)
{
return $a*$num;
}
echo func(200)
echo func(200,8);
注意:尽量不要将默认值参数定义在第一个参数
位置,容易造成定义默认值实效
PHP 函数
(4 )、函数的返回值
return value;
返回函数的内容
3 、变量函数
如果一个变量名后有括号,PHP 则搜索与变
量值相同的函数。并且执行它
PHP 函数
Function foo()
{
Echo “ 执行func() 函数” ;
}
$func = ‘foo’;
$func(); // 变量函数
显示结果:执行func() 函数
变量的作用域
• 变量的作用域
1 、global 语句
该语句允许从脚本的任何位置访问函数内部
定义的变量以及从函数内部访问函数外部的
变量
变量的作用域
//$a = 23;
function foo()
{
global $a;
$a = 32;
echo $a;
}
$func = "foo";
$func();
echo $a;
变量的作用域
2 、static 语句
静态变量仅在局部函数中存在,当程序
离开该函数时,它值不会丢失
变量的作用域
function foo()
{
$a = 0;
echo $a;
$a ++;
}
foo(); //0
foo(); //0
foo(); //0
变量的作用域
function foo()
{
static $a = 0;
echo $a;
$a ++;
}
foo(); //0
foo(); // 1
foo(); // 2
日期和时间的处理
• 获取日期和时间
date() 按指定格式返回系统的时间字符串
如:date(“d”) 返回月份中的第几天
具体参数见P103
a - "am" 或是 "pm"
A - "AM" 或是 "PM"
d - 几日,二位数字,若不足二位则前面补零; 如: "01" 至 "31"
D - 星期几,三个英文字母; 如: "Fri"
F - 月份,英文全名; 如: "January"
h - 12 小时制的小时; 如: "01" 至 "12"
H - 24 小时制的小时; 如: "00" 至 "23"
g - 12 小时制的小时,不足二位不补零; 如: "1" 至 12"
G - 24 小时制的小时,不足二位不补零; 如: "0" 至 "23"
i - 分钟; 如: "00" 至 "59"
j - 几日,二位数字,若不足二位不补零; 如: "1" 至 "31"
l - 星期几,英文全名; 如: "Friday"
m - 月份,二位数字,若不足二位则在前面补零; 如: "01" 至 "12"
n - 月份,二位数字,若不足二位则不补零; 如: "1" 至 "12"
M - 月份,三个英文字母; 如: "Jan"
s - 秒; 如: "00" 至 "59"
S - 字尾加英文序数,二个英文字母; 如: "th" ,"nd"
t - 指定月份的天数; 如: "28" 至 "31"
U - 总秒数
w - 数字型的星期几,如: "0" ( 星期日) 至 "6" ( 星期六)
Y - 年,四位数字; 如: "1999"
y - 年,二位数字; 如: "99"
z - 一年中的第几天; 如: "0" 至 "365"
《PHP正则表达式》
PHP 正则表达式
• 正则表达式
正则表达式是一种可以用于模式 匹配和替换的强有力的工具。
正则表达式可以让用户通过使用一系列的特殊字符构建匹配模
式,然后把匹配模式与数据文件、程序输入以及WEB 页面的表单输
入等目标对象进行比较,根据比较对象中是否包含匹配模式,执
行相应的程序。
例: ^http 表示匹配以http 开头的所有字符
[a-z] 匹配所有小写字符
abc 匹配字符串abc
PHP 正则表达式
• 正则表达式的元字符
PHP 正则表达式
• 匹配正则表达式模式
preg_match(pattern,subject)
表示在subject字符串中搜索与pattern给出的正则表达式相匹配的
内容.该函数返回pattern所匹配的次数(0次或1次).0次表示没有匹配
结果,函数返回一个false
例如:
$str = “php is a good language”;
preg_match(“/php/”,$str);
PHP 正则表达式
模式,是正规表达式最基本的元素,它们是一组描述字符串特
征的字符。模式可以很简单,由普通的字符串组成,也可以非常
复杂,往往用特殊的字符表示一个范围内的字符重复出现,或表
示上下文。我们先看一些正则表达式中的特殊字符。
• 字符: ^
意义:表示匹配的字符必须在最前边。
例如:
preg_match(/^A/,”A good language”) // 匹配成功
• 字符: $
意义:与^ 类似,匹配最末的字符。
例如:
preg_match(/t$/,”eat”) // 匹配成功
PHP 正则表达式
• 字符*
意义:匹配* 前面的字符0 次或n 次。
例如: preg_match(“/do*g/”,”doog”) // 匹配成功
• 字符+
意义:匹配+ 号前面的字符1 次或n 次。等价于{ 1, } 。
例如:preg_match(“/do+g”,”dg”) // 不匹配
• 字符?
意义:匹配? 前面的字符0 次或1 次。
例如:preg_match(“/do?g/”,”dg”) // 匹配
PHP 正则表达式
• 字符.
意义:( 小数点) 匹配除换行符外的所有单个的字符。
例如:/.n/ 匹配“nay, an” 中的‘an’ ,但不匹配‘nay’ 。
• 字符(x)
意义:匹配‘x’ 并记录匹配的值。
例如:/(foo)/ 匹配和记录“foo bar.” 中的‘foo’ 。匹配子串能被结果数组中的素[1], ...,[n] 返回
• 字符x│y
意义:匹配'x' 或者'y' 。
例如:/green│red/ 匹配"green apple" 中的'green' 和"red apple." 中的'red' 。
PHP 正则表达式
• 字符{ n }
意义:这里的n是一个正整数。匹配前面的n个字符。
例如:/a{ 2 }/不匹配"candy,"中的'a',但匹配"caandy," 中的所有'a'和"caaandy."中前面的两个'a'。
• 字符{ n, }
意义:这里的n是一个正整数。匹配至少n个前面的字符。
例如:/a{ 2, }不匹配"candy"中的'a',但匹配"caandy"中的所有'a'和"caaaaaaandy."中的所有'a'
• 字符{ n,m }
意义:这里的n和m都是正整数。匹配至少n个最多m个前面的字符。
例如:/a{ 1,3 }/不匹配"cndy"中的任何字符,但匹配 "candy,"中的'a',"caandy," 中的前面两个 'a'和"caaaaaaandy"中前面的三个'a',注意:即使"caaaaaaandy" 中有很多个'a',但只匹配前面的三 个'a'即"aaa"。
PHP 正则表达式
• 字符[xyz]
意义:一字符列表,匹配列出中的任一字符。你可以通过连字符- 指出一个字符范围。
例如:[abcd] 跟[a-d] 一样。它们匹配"brisket" 中的'b' 和"ache" 中的‘a’,’c' 。
• 字符[^xyz]
意义:一字符补集,也就是说,它匹配除了列出的字符外的所有东西。 你可以使用连字符- 指出一 字符范围。
例如:[^abc] 和[^a-c] 等价,它们最早匹配"brisket" 中的'r' 和"chop." 中的'h' 。
• 字符 空格
意义:匹配一个空格( 不要与b 混淆)
PHP 正则表达式
• 预定义字符和字符类
• \d 数字
表示匹配数字0-9中任一字符,功能类似[0-9]
• \D 非数字
表示匹配一个非数字,功能类似[^0-9]
• \w 单词字符
表示匹配一个单词字符.功能类似[a-zA-Z0-9]
• \W 非单词字符
表示匹配一个非单词字符
PHP 正则表达式
• 字符\b
意义:匹配一个单词的分界线,比如一个空格( 不要与空格混淆)
例如:/\bno/ 匹配"noonday" 中的'no' ,/ly\b/ 匹配"possibly yesterday." 中的'ly' 。
PHP
Author: 陈庆平(Andych)
E-mail:ahut9923@126.com
PHP 字符串
• 格式化字符串
1 、trim() 删除字符串开始和结束位置的空格
格式:trim(str)
2 、ltrim() 删除字符串左边的空格
格式:ltrim(str)
PHP 字符串
3 、 rtrim() 删除字符串右边的空格
格式:rtrim(str)
PHP 字符串
4 、strtolower() 字符串转换为小写
格式:strtolower(str)
5 、strtoupper() 字符串转换为大写
格式:strtoupper(str)
6 、ucfirst() 将函数的第一个字符转换为大写
格式:ucfirst(str)
PHP 字符串
7 、ucwords() 将每个单词的首字母转换为大写
格式:ucwords(str)
• HTML 文本格式输出
1 、nl2br() 将字符串中的\n 转换成br
格式:nl2br(str)
str 中包含\n
PHP 字符串
2、htmlspecialchars() HTML字符原样输出
格式:htmlspecialchars(str,quote_style)
str:要转换的字符
quote_style:转换方式,主要对单引号和双引
号进行转换。值如下:
ENT_COMPAT 双引号被转换
ENT_QUOTES 单引号和双引号都被转换
ENT_NOQUOTES 任何一个引号都不被转换
主要用在防止恶意脚本注入和数据库数据的存储
PHP 字符串
3 、strip_tags() 去除字符串中PHP 和HTML 代码
格式:strip_tags(str,[char])
str :要去除的字符串
char :要保留字符串
如:strip_tags(“a href=‘’new/a”,a)
PHP 字符串
• 和数据库相关
1 、addslashes() 按照一定规则将字符串进行转义
格式:addslashes($str)
如:addslashes(“Hello ,’jack’”)
结果:Hello,\’jack\’
magic_quotes_gpc = On 自动对 get post cookie
的内容进行转义
get_magic_quotes_gpc ()检测是否打开
magic_quotes_gpc
PHP 字符串
2 、stripslashes() 去除字符串中的反斜杠
格式:stripslashes($str)
• 字符串的连接和分割
1 、explode() 按指定分割符将字符串分开
格式:explode(str,$str[,limit])
str :分割符
$str :要分割的字符串
limit :分割后数组长度(可选)
PHP 字符串
2 、implode() 将字符串按指定字符连接
成一个字符串
格式:implode(str,$arr)
str :连接符
$arr :字符串数组
注意:implode() 函数有个别名函数join
PHP 字符串
3、strtok() 从指定的字符串中去除指定的字符
格式:strtok($str,str)
注意:若想输出所有内容,则以后函数中不需
要再加$str了。
如:$str = aa@a.com;bb@a.com;cc@a.com
$newstr = strtok($str,”;”)
while($newstr )
{
echo $newstr;
$newstr = strtok(”;”)
}
PHP 字符串
4 、substr() 在指定的字符串中取出规定的字符
串。
格式:substr($str,start[,length])
$str :指定的字符串
strat :起始位置
length :取出的字符串的长度。该参数可选
PHP 字符串
• 字符串比较
1 、strcmp() 字符串比较, 返回值为0 ,正数和负数
格式:strcmp($str1,$str2)
注意:比较的字符串是区分大小写的
2 、strcasecmp() 功能同上,但不区分大小写
PHP 字符串
3 、strnatcmp() 按自然排序比较字符串
格式:strnatcmp($str1,$str2)
如:strnatcmp(“4”,”14”) // 结果小于0
strcmp(“4”,”14”) // 结果大于0
4 、strnatcasecmp() 用法同上,只是不区分大
小写
PHP 字符串
• 字符串查找
1 、strstr() 在指定的字符串中查找指定的字符
格式:strstr($str1,$str2)
如:$email = “ahut9923@126.com";
$domain = strstr($email,"@");
echo $domain; //@126.com
注意:如果含有多个,则从第一次出现的位置
开始输出,若没有则返回FALSE
PHP 字符串
2 、stristr() 功能同strstr ,只是不区分大小写
3 、strrchr() 从最后一次搜索到的字符处返回
用处:取路径中文件名
$path = "c:\\a\\b\\aa\\a.html";
$filename = strrchr($path,"\\");
echo $ filename;
PHP 字符串
• 定位字符串
1 、strpos() 在指定的字符串中查找子字符串第
一次出现的位置,找不到返回false
格式:strpos($str1,$str2)
如:echo strpos(“Hello”,”l”)
2 、strrpos() 功能同上,搜索子字符串最后一次
出现的位置
PHP 字符串
• 字符串替换
1、str_replace() 将新的字符串替换目标字符串
中指定的字符串
格式:str_replace($search,$replace,$subject)
如:
$subject = "Hell jack";
echo str_replace("Hell","Hello:",$subject);
$search:要被替换的字符串
$replace:替换的字符串
$subject:目标字符串
PHP 字符串
2 、substr_replace() 查找和替换子字符串
格式:substr_replace($Str,$rep,$start[,length])
$str :原始字符串
$rep :替换后的新字符串
$start :起始位置
$length :替换的长度,该项可选
如:$subject = "Hell jack";
echo substr_replace($subject,"Hell",1);
// 结果:HHell
PHP函数
Author:陈庆平(Andych)
E-mail:ahut9923@126.com
PHP函数
• 函数
1、定义
独立完成特定功能的代码块
2、特性
1)无须在引用函数之前定义
2)函数不能被重载。(即不能定义名称相同的函数)
3)函数参数个数不能变化
4)PHP支持默认参数函数
PHP函数
• 内置函数
1、echo()函数
功能:输出一行字符串
格式:echo “字符串”;
2、print()函数
功能:输出一行字符串
格式:print ”字符串”;
PHP函数
3、include / require 函数
功能:包含并运行指定的文件 。
格式:include “a.php”;
说明:如果上面的函数用在条件语句中,一定要写在{}内.
被包含的文件中可以使用return 语句。
If($a==$b)
{
include “a.php”;
}else{
include “b.php”;
}
PHP函数
• 自定义函数
1、函数声明
格式:
function func_name($arg1,$arg2…$argn)
{
语句集;
return value;
}
根据函数是否包含参数:无参函数 和 有参函数
PHP函数
2、无参函数
例:定义函数,计算100以内偶数之和
function func_sum()
{
$sum = 0;
for($a=0;$a=100;$a++)
{
if($a%2==0){ $sum += $a;}
}
}
func_sum(); //调用函数
PHP函数
3、有参函数
1)按值传递
例:写一函数,求任何两个数的和
function func_name($a,$b)
{
$sum = $a + $b;
echo $sum;
}
func_name(32,34); //调用函数
PHP函数
2)按地址传递
例:求给定数乘以15以后的结果。
$myNum = 100;
function func_mul($a)
{
echo $a * 15;
}
func_mul($myNum); //函数调用,带地址符号
echo $myNum;
低版本不默认支持地址传递,修改如下参数php.ini
allow_call_time_pass_reference = on
PHP函数
3)默认值函数
定义函数时,给参数赋值;在调用函数若不指定参数内容,
则自动调用参数默认值。
例:
function func_def($style=“默认值”)
{
echo $style;
}
func_def(); //不带参数,输出 “默认值”
func_def(“赋给参数”); //给参数,输出 “赋给参数”
PHP函数
4)函数返回值
功能: 函数返回值
格式: return “值”
例:
function func_returnval()
{
return “return value”;
1、输出。
Python: print 默认换行,不换行要加逗号。
PHP: echo 可以输出多个变量;print ()只输出一个变量,且成功返回值为1,失败为0;print_r() 只输出数组;die() 先输出,后关机;printf() 格式化输出字符串;var_dump()可以判断一个变量的类型与长度,并输出变量的数。
2、数据类型。
PHP:七个数据类型:String,Integer,Float,Boolean,Array,Object,NULL
Python:五个标准的数据类型:Number,String,List,Tuple,Dictionary 其中包括Numberint,long,float,complex
3、访问权限。
PHP:三种访问权限,由高到低为public,protected,private
Python: _foo代表不能直接访问的类属性,需要通过类提供的接口访问;__foo代表类的私有成员;__foo__特殊方法专用的标识
4、定义变量和方法。
PHP: 弱类型语言,用$定义变量,一般情况下变量引用变量时也要带着$(区别于Java), 在类中定义变量时还要加var ,定义方法时 function test (){} 要用function声明。
Python:弱类型语言,定义变量时直接写,除了访问权限修饰符不需要加别的。定义方法时 def __init__(self,name): 要用def声明,self是必须要加的常量,代表该类的对象,方法体不用{}。
列表是 Python 中最常用的序列数据类型之一。
列表中的元素是有序可重复的。
列表中的元素可以是不同数据类型,甚至可以嵌套。
和字符串一样,列表可以被索引和截取,列表被截取后返回一个新列表。
和字符串不一样,列表是可变数据类型,其值可以被改变。
与字符串的索引一样,列表也使用下标索引来访问列表中的值。
列表变量 [ 索引值 ]
列表同样可以被截取
列表变量 [ 头下标:尾下标 ]
列表是可变类型,通过赋值语句直接修改对应位置的元素
列表变量 [ 索引值 ] = 新元素
要删除指定位置的元素,用 pop(i) 方法,其中 i 是索引位置
删除指定位置的元素还可以使用 del 语句
删除指定内容的元素使用 remove(obj) 方法
列表元素也可以是另一个列表,比如 s 只有4个元素,其中 s[2] 又是一个list
要获得 'php' 可以写 s[2][1] ,因此 s 可以看成是一个二维数组
- end -