PHP初级面试题

PHP面试题

服务器方面

1、nginx平滑重启

nginx 运行新的工作进程并从容关闭旧的工作进程,通知工作进程关闭监听套接字,但是继续为当前连接的客户提供服务。所有的客户端的服务完成后,旧的工作进程被关闭。如果新的配置文件应用失败,nginx 将继续使用旧的配置文件进行工作。
说简单点就是 nginx会继续处理之前的请求,并且启动一个新的进程来处理新的请求,旧的进程处理完成之后会被kill。

2、获取文件后10行。
tail -10 a.log

3、查看占用系统资源比较多的进程
top
ps:输完top命令之后,按1可以看内存以及cpu使用情况

3、查看关键字出现函数
grep -n ‘我是要查找的关键字’ a.txt | cut -d “:” - f1

统计文件中关键字分别出现的哪一行:
	grep -n "关键字"    “文件路径” | cut -d ":"  -f1

统计文件中关键字出现的最后一行行号:
grep -n “关键字” “文件路径” | tail -n 1 | cut -d “:” -f1

4、在/root/目录下搜索带有关键字“www”的文件,在终端下运行命令:
find /root/ –type f | xargs grep “www

5、统计文件 行数
wc -l a.txt

统计demo目录下,js文件数量:
	find demo/ -name "*.js" |wc -l
统计demo目录下所有js文件代码行数:
	find demo/ -name "*.js" |xargs cat|wc -l 
	 wc -l `find ./ -name "*.js"`|tail -n1
统计demo目录下所有js文件代码行数,过滤了空行:
	find /demo -name "*.js" |xargs cat|grep -v ^$|wc -l

6、实时监控一个文件
tail -f a.log

7、nginx日志中访问最多的100个ip及访问次数
nginx日志中访问最多的100个ip及访问次数
awk ‘{print $1}’ /opt/software/nginx/logs/access.log| sort | uniq -c | sort -n -k 1 -r | head -n 100

8、在编译完成的php,添加新的扩展
-----------------------------------------
源码安装
1、找到php的源码目录
2、跳转到EXT目录下边
3、执行phpize生成configure文件
4、 ./configure --with-php-config=/usr/local/php/bin/php-config
5、编译 make
6、编译安装 make install
7、修改php.ini extension=/usr/local/***.so
8、重启php-fpm

YUM安装:

1、去PHP的官网下载源码 (htpp://pecl.php.net)
2、解压文件
3、执行phpize生成configure文件
4、 ./configure --with-php-config=/usr/local/php/bin/php-config
5、编译 make
6、编译安装 make install
7、修改php.ini extension=/usr/local/***.so
8、重启php-fpm

-----------------------------------------

php优化 nginx优化 mysql优化

php优化:
1、将类的方法定义为static。
2、尽量使用单引号。
3、修改php-fpm进程数。
4、修改单个脚本最大可使用内存。
5、大的数组使用完之后要及时释放。
6、循环的时候,制定最大循环次数
7、不使用@屏蔽错误
8、尽量采用大量的 PHP 内置函数
9、使用require代替require_once

nginx优化:
1、修改nginx的子进程数。 [ 最多65535,不是越多越好 ]
2、开启静态缓存
3、修改主进程数。建议按照cpu 数目来指定,一般为它的倍数 (如,2个四核的cpu计为8)
4、开启gzip输出 [ 开启gzip,ob函数就不能用了 ]
5、keepalive_timeout 设置连接超时时间

mysql优化:
1、避免子查询
2、有顺序的读取
3、避免重复的读写
4、设置自增id
5、避免使用select *
6、合理设置字段类型
7、读写分离
8、分区、分表
9、建立合适的索引
10、避免使用耗费资源的操作 null
11、不要使用rand()
12、尽量不要使用 or 查询
13、查询一条数据的时候加上LIMIT 1
14、开启查询缓存
15、前期对数据进行合理的评估,进行分区、分表
16、避免使用 %前缀的模糊查询
17、避免使用mysql自带函数
18、使用多从解决查询慢的问题

秒杀如何实现?

我们做的秒杀并发量就是十几万、下边的版本是十几万的:

1、专门对秒杀服务器 [ps:量大的话这么说,如果小的话就不用了 ]
2、生成静态页面。 [ ps:如果还很大的可以把这个文件放在 cdn上 ]
3、倒计时以及库存从服务端获取 [ 一段时间内只获取一次,倒计时结束之后会请求下服务端,是否已经开始 ]
4、把要秒杀的数据库存放到redis中 [ key value ] stock=10
5、设置一个redis队列 [ 使用list做队列 ] lpop rpush
6、用户在请求的时候,判断用户是否参与过秒杀,没有参加过把用户数据写入队列中,同时库存减1 ,参加过就提示已经参加过
ps:这块用到了redid的原子性操作、以及事务 multi 和 watch
redis乐观锁 cas ==== 就是设置之前判断下这个值有没有改变
7、库存减0就不能进行秒杀
8、异步脚本处理队列数据 [ crontab + php文件 ]

如果你说是1-3万的话,就不用单独去租服务器了

如果问到业务相关的问题的话,就随机应变吧!!!!

比如说: 10 个用户买了都不支付怎么办?
第一种说法 :
就说当时的产品需求是不支付也没有问题,其它用户也不可以买了,当时在做的和产品讨论了,产品说正常的话用户都会支付,因为比较便宜
第二种说法:
会开启下一轮的秒杀。 比如说小米的 2小时之后还可以继续买!!
第三站说法:
会。。。。

怎么保证不超买 ?
减库存的时候是原子性操作,使用cas乐观锁。测试的时候没有出现过超买的情况

还有就是秒杀的时候就不用购物车了,点击的时候就排队了

Q1:防刷是怎么做的?一般抢购都有很大优惠。如果有人恶意刷,那正常的用户就失去了购买的机会。比如,抢购的商品数为1000,有人恶意刷了900,那只有 100 被正常用户抢到。等恶意抢到的 900 经过后面的支付环节验证后,可能已经过了抢购时间了。就算恶意抢到的 900 都支付成功,那对正常用户也是不公平的。
在这个业务场景中,我们做的是商品展示、商品的购买权的发放,真正产生消费是在第三方。那么,用户刷的问题,需要我们和第三方支付页面一起来控制。在用户通过排队机制,获得了购买名额后,跳转去第三方时候,我们按照和第三方约定的加密方式传递加密信息,第三方按照约定的解密方式解密成功后才允许用户支付,加密解密的过程中可以带具有生命周期的内容。这样,用户在高频请求支付页面获取商品时候,实际只有:1)加密对;2)第一次,才可能获得。不过,第三方都是为了销售出商品,所以这类合作的成功几率不大。恶意刷,的确会在我们的业务层面展示商品没量了。导致想买的用户没了机会,但可以保证第三方不受损。这种刷的情况,若想在我们业务层规避,我想这就是一个通用的防SPAM的问题了。这块自己真懂得不多。

Q2:要想准确的放刷,判断的维度就多,逻辑就复杂;与之矛盾的,抢购要求的是响应迅速。
对的,抢购业务因为请求压力大、热门商品抢购并发高,切忌增加过多逻辑,切忌过多后端依赖,越简单效果越好。我们在设计系统时候,很多事不是咱们一个系统能cover的,多少需要一些前置模块、能力的构建ready后,我们的系统才能run的不错。建议构建帐号体系、用户消费记录这两部分。
Q3:对账只是和第三方去对比商品的库存量吗,金额是否去对比?
对账,其实是对比的消费数据。避免出现我们统计今日产生了X件商品共价值Y的消费,第三方给出的是消费了N件共M价值的消费。避免金额不一致,造成结算、分成等问题的出现。我想你问题中的库存量的diff问题,还得靠第三方定期的通过我们数据层的接口来update他们提供的商品。其实在我们的商品库中,商品不一定只允许第三方提供,也可以允许第三方通过接口减少商品嘛,比如和一个卖水果的第三方合作,第三方上周发布说有100件,但这周线下热销,只剩20件了,我们也应该允许第三方来update到一个低值。但这样,我们的系统中就会复杂挺多。

Q4:防刷,避免第三方的推广效果达不到问题。
对的,用户ID维度、IP维度,都是有效办法。看具体场景。有帐号体系的业务,用用户ID维度效果最好,借助存储记录下每个用户的购买记录,来控制就好。市面上的电商网站,基本是抢购业务都需要登录,并且限制每件商品单人购买数量,其实就是通过存储记录用户的消费,并且再次产生消费前查询并增加代码逻辑来控制。

Q5:每次抢购活动的时候用一套新的验证码?
验证码这个东东,属于图灵测试嘛,只要测试方法好,并且尽可能保证每次产生的验证信息从未出现过且无规律,就是好的验证码啦。

比较好的秒杀系统架构:
http://www.kuqin.com/shuoit/20141203/343669.html

算法题:
http://blog.csdn.net/frimish/article/details/48666485

怎么在海量数据中找出重复次数最多的一个

网站日志中记录了用户的IP,找出访问次数最多的IP

假设有1kw个身份证号,以及他们对应的数据。身份证号可能重复,要求找出出现次数最多的身份证号。

有一个1G大小的一个文件,里面每一行是一个词,词的大小不超过16字节,内存限制大小是1M。返回频数最高的100个词。

有10个文件,每个文件1G,每个文件的每一行存放的都是用户的query,每个文件的query都可能重复。要求你按照query的频度排序。

常见的排序:
http://www.php100.com/html/php/rumen/2013/1029/6333.html

冒泡排序:
原理:
把第一个数字和所有数字进行比较,然后遇到大的交换位置,这样第一次就把最大的放在了最后边,然后继续在比较,第二次比较的时候最后一个数字就不用比较了,因为已经确定它是最大的了,以此类推。

	1. 冒泡排序法 
  • 思路分析:法如其名,就是像冒泡一样,每次从数组当中 冒一个最大的数出来。 
    
  • 比如:2,4,1    // 第一次 冒出的泡是4 
    
  •            2,1,4   // 第二次 冒出的泡是 2 
    
  •            1,2,4   // 最后就变成这样 
    

    时间复杂度:
    冒泡排序是一种用时间换空间的排序方法,最坏情况是把顺序的排列变成逆序,或者把逆序的数列变成顺序。

a r r = a r r a y ( 1 , 43 , 54 , 62 , 21 , 66 , 32 , 78 , 36 , 76 , 39 ) ; f u n c t i o n g e t p a o ( arr=array(1,43,54,62,21,66,32,78,36,76,39); function getpao( arr=array(1,43,54,62,21,66,32,78,36,76,39);functiongetpao(arr)
{
l e n = c o u n t ( len=count( len=count(arr);
//设置一个空数组 用来接收冒出来的泡
//该层循环控制 需要冒泡的轮数
for( i = 1 ; i=1; i=1;i< l e n ; len; len;i++)
{ //该层循环用来控制每轮 冒出一个数 需要比较的次数
for( k = 0 ; k=0; k=0;k< l e n − len- leni;KaTeX parse error: Expected '}', got 'EOF' at end of input: … { if(arr[ k ] > k]> k]>arr[$k+1])
{
t m p = tmp= tmp=arr[$k+1];
a r r [ arr[ arr[k+1]= a r r [ arr[ arr[k];
a r r [ arr[ arr[k]=$tmp;
}
}
}
return $arr;
}

2、选择排序:
http://jingyan.baidu.com/article/f3ad7d0f07516d09c3345b19.html
http://mmm2010.blog.163.com/blog/static/174230348201292273310140/

function select_sort(KaTeX parse error: Expected '}', got 'EOF' at end of input: … 控制的比较次数 //i 当前最小值的位置, 需要参与比较的元素
for($i=0, l e n = c o u n t ( len=count( len=count(arr); i < i< i<len-1; $i++) {
//先假设最小的值的位置
$p = i ; / / i; // i;//j 当前都需要和哪些元素比较, i 后 边 的 。 f o r ( i 后边的。 for( ifor(j=$i+1; j < j< j<len; KaTeX parse error: Expected '}', got 'EOF' at end of input: … //arr[ p ] 是 当 前 已 知 的 最 小 值 i f ( p] 是 当前已知的最小值 if( p]if(arr[$p] > a r r [ arr[ arr[j]) {
//比较,发现更小的,记录下最小值的位置;并且在下次比较时,
// 应该采用已知的最小值进行比较。
$p = KaTeX parse error: Expected 'EOF', got '}' at position 16: j; }̲ } …p中。
//如果发现 最小值的位置与当前假设的位置 i 不 同 , 则 位 置 互 换 即 可 i f ( i不同,则位置互换即可 if( iif(p != $i) {
$tmp = a r r [ arr[ arr[p];
a r r [ arr[ arr[p] = a r r [ arr[ arr[i];
a r r [ arr[ arr[i] = $tmp;
}
}
//返回最终结果
return $arr;
}

3.快速排序法

function quick_sort($arr) {
//先判断是否需要继续进行
l e n g t h = c o u n t ( length = count( length=count(arr);
if($length <= 1) {
return $arr;
}
//如果没有返回,说明数组内的元素个数 多余1个,需要排序
//选择一个标尺
//选择第一个元素
$base_num = $arr[0];
//遍历 除了标尺外的所有元素,按照大小关系放入两个数组内
//初始化两个数组
$left_array = array();//小于标尺的
r i g h t a r r a y = a r r a y ( ) ; / / 大 于 标 尺 的 f o r ( right_array = array();//大于标尺的 for( rightarray=array();//for(i=1; i < i< i<length; KaTeX parse error: Expected '}', got 'EOF' at end of input: …) { if(base_num > a r r [ arr[ arr[i]) {
//放入左边数组
$left_array[] = a r r [ arr[ arr[i];
} else {
//放入右边
$right_array[] = a r r [ arr[ arr[i];
}
}
//再分别对 左边 和 右边的数组进行相同的排序处理方式
//递归调用这个函数,并记录结果
l e f t a r r a y = q u i c k s o r t ( left_array = quick_sort( leftarray=quicksort(left_array);
r i g h t a r r a y = q u i c k s o r t ( right_array = quick_sort( rightarray=quicksort(right_array);
//合并左边 标尺 右边
return array_merge( l e f t a r r a y , a r r a y ( left_array, array( leftarray,array(base_num), $right_array);
}

4、插入排序法
http://blog.csdn.net/hijiankang/article/details/9207735

情景描述:
  紧接冒泡排序,每次同学们都屡试不爽,但是学生越来越多了,老师发现每次排完队,就耽搁了大半节课时了,说道:“咱不用冒泡了,有点OUT了,今天来插入排序”。这时体育老师担任起了数学老师的职责,又给同学们讲了种排队方式–插入排序。

  1. 开始以第一位同学为基准,由第二个同学开始向前和第一位同学比较,个头高了不动,低了换位
  2. 第三个同学要先和自己前面的第二位同学比较,如果低了,和第二换位,然后再向前和第一比较,低了再换,否则阻断,不再比较
  3. 从前往后依次执行步骤2,依次出来一位同学,每次和自己前面的同学进行比较,找到一个合适位置插入,其余学生后移
    合适位置:前一位同学等于或低于自己身高,并且后一位同学高于自己身高
      按照这个方式,同学们一个个依次找准位置,再也不用每次相邻的都比较,而且找到位置后就不必再往前面比较了…

插入排序法思路:将要排序的元素插入到已经 假定排序号的数组的指定位置。
function insert_sort(KaTeX parse error: Expected '}', got 'EOF' at end of input: …排序好的序列 for(i=1, l e n = c o u n t ( len=count( len=count(arr); i < i< i<len; $i++) {
//获得当前需要比较的元素值。
$tmp = a r r [ arr[ arr[i];
//内层循环控制 比较 并 插入
for( j = j= j=i-1; j > = 0 ; j>=0; j>=0;j–) {
// a r r [ arr[ arr[i];//需要插入的元素; a r r [ arr[ arr[j];//需要比较的元素
if($tmp < a r r [ arr[ arr[j]) {
//发现插入的元素要小,交换位置
//将后边的元素与前面的元素互换
a r r [ arr[ arr[j+1] = a r r [ arr[ arr[j];
//将前面的数设置为 当前需要交换的数
a r r [ arr[ arr[j] = $tmp;
} else {
//如果碰到不需要移动的元素
//由于是已经排序好是数组,则前面的就不需要再次比较了。
break;
}
}
}
//将这个元素 插入到已经排序好的序列内。
//返回
return $arr;
}

/**
* 插入排序,默认第一位已经排好序,从第二位开始依次向前比较,确定自己的位置后插入,即前一位小余或等于当前,且后一位大于当前。
* 插入后,自己新位置后面的元素依次向后移位, 完成一轮插入排序
* @param arr
* @return
*/
public static int[] insertSort(int[] arr) {
int len = arr.length;
for (int i = 1; i < len; i++) {
if (arr[i - 1] > arr[i]) {
int k = arr[i];
int j = i;
while (j > 0 && arr[j - 1] > k) {
arr[j] = arr[j - 1];
j–;
}
arr[j] = k;
}
}
return arr;
}

二分查找:

http://www.tuicool.com/articles/2MbAR3q
http://blog.csdn.net/xzjxylophone/article/details/4714326
1,2,3,4,5,6,7
我现在要查找7
我先取出中间数 4
判断下是不是要找的数字,发现小了
就去右边查找
然后取出右边的所有的数
取出她们几个的中间数 6
发现还小了
继续找右边的数组
找到7了 ok了!!!

最差的一种情况就是这个数字不存在 ====

1 <?php
2 #二分查找
3 function binarySearch(Array $arr, $target) {
4 $low = 0;
5 h i g h = c o u n t ( high = count( high=count(arr) - 1;
6
7 while($low <= $high) {
8 m i d = f l o o r ( ( mid = floor(( mid=floor((low + KaTeX parse error: Expected 'EOF', got '#' at position 28: … 9 #̲找到元素 10 …arr[$mid] == $target) return KaTeX parse error: Expected 'EOF', got '#' at position 21: …11 #̲中元素比目标大,查找左部 12…arr[$mid] > $target) $high = KaTeX parse error: Expected 'EOF', got '#' at position 25: …13 #̲重元素比目标小,查找右部 14…arr[$mid] < $target) $low = $mid + 1;
15 }
16
17 #查找失败
18 return false;
19 }
20
21 $arr = array(1, 3, 5, 7, 9, 11);
22 i n x = b i n a r y S e a r c h ( inx = binarySearch( inx=binarySearch(arr, 1);
23 var_dump($inx);
24 ?>

安全方面:
xss :跨站脚本攻击
csrf : 跨站请求伪造
Ddos:用很多机器对网址进行请求,把服务器某方面搞挂。
sql注入: 通过关键字或者非法字符的注入,实现一些对数据库一些非正常的操作

	最简单的demo :
	在用户登陆的时候,用户名和密码的判断,密码后加上 or 1=1

如何防止sql注入:
关键字的过滤
pdo预处理
php 配置文件 php.ini 中的 magic_quotes_gpc选项没有打开,被置为 off
addslashes stripslashes
mysql_real_escape_string
对一些数据类型做强制的校验

如何防止xss攻击?
xss攻击最简单的方式就是通过地址栏输入,这样的话就会在我们的浏览器弹出来1,如果是页面的跳转,或者是一些其它脚本、病毒的话,可能对我们网站的安全造成很大的隐患。

最简单的解决办法
不要相信客户端的任何输入,在程序做严格的判断以及处理
htmlspecialchars进行过滤

csrf :
这个我们在学curl的时候做的模拟登陆就是跨站请求伪造!!!!
最简单的大白话就是:
a网站往b网站请求数据。
加个token防止下就行了,简单,粗暴,有效

Dos和Ddos防止:
阿里云 高防ip
idc机房
放弃一部分请求不处理。

正则方面的问题:

贪婪模式和非贪婪模式的区别:
贪婪模式匹配到内容之后会继续向后匹配
非贪婪模式则不回继续匹配

匹配中文字符的正则表达式: [\u4e00-\u9fa5]
评注:匹配中文还真是个头疼的事,有了这个表达式就好办了
匹配双字节字符(包括汉字在内):[^\x00-\xff]
评注:可以用来计算字符串的长度(一个双字节字符长度计2,ASCII字符计1)
匹配空白行的正则表达式:\n\s*\r
评注:可以用来删除空白行
匹配HTML标记的正则表达式:<(\S*?)[^>]>.?</\1>|<.? />
评注:网上流传的版本太糟糕,上面这个也仅仅能匹配部分,对于复杂的嵌套标记依旧无能为力
匹配首尾空白字符的正则表达式:^\s
|\s*$
评注:可以用来删除行首行尾的空白字符(包括空格、制表符、换页符等等),非常有用的表达式
匹配Email地址的正则表达式:\w+([-+.]\w+)@\w+([-.]\w+).\w+([-.]\w+)*
评注:表单验证时很实用
匹配网址URL的正则表达式:[a-zA-z]+://[^\s]*
评注:网上流传的版本功能很有限,上面这个基本可以满足需求
匹配帐号是否合法(字母开头,允许5-16字节,允许字母数字下划线):1[a-zA-Z0-9_]{4,15}$
评注:表单验证时很实用
匹配国内电话号码:\d{3}-\d{8}|\d{4}-\d{7}
评注:匹配形式如 0511-4405222 或 021-87888822
匹配腾讯QQ号:[1-9][0-9]{4,}
评注:腾讯QQ号从10000开始
匹配中国邮政编码:[1-9]\d{5}(?!\d)
评注:中国邮政编码为6位数字
匹配身份证:\d{15}|\d{18}
评注:中国的身份证为15位或18位
匹配ip地址:\d+.\d+.\d+.\d+
评注:提取ip地址时有用
匹配特定数字:
2\d*KaTeX parse error: Undefined control sequence: \d at position 21: …/匹配正整数 ^-[1-9]\̲d̲*   //匹配负整数
^-?[1-9]\d*KaTeX parse error: Undefined control sequence: \d at position 18: … //匹配整数 ^[1-9]\̲d̲*|0  //匹配非负整数(正整数 + 0)
^-[1-9]\d*|0KaTeX parse error: Undefined control sequence: \d at position 29: …整数 + 0) ^[1-9]\̲d̲*\.\d*|0\.\d*[1…   //匹配正浮点数
^-([1-9]\d*.\d*|0.\d*[1-9]\d*)KaTeX parse error: Undefined control sequence: \d at position 22: …负浮点数 ^-?([1-9]\̲d̲*\.\d*|0\.\d*[1…  //匹配浮点数
3\d*.\d*|0.\d*[1-9]\d*|0?.0+|0KaTeX parse error: Undefined control sequence: \d at position 34: …+ 0) ^(-([1-9]\̲d̲*\.\d*|0\.\d*[1…  //匹配非正浮点数(负浮点数 + 0)
评注:处理大量数据时有用,具体应用时注意修正
匹配特定字符串:
4+     / / 匹 配 由 26 个 英 文 字 母 组 成 的 字 符 串 [ A − Z ] +   //匹配由26个英文字母组成的字符串 ^[A-Z]+   //26[AZ]+  //匹配由26个英文字母的大写组成的字符串
5+     / / 匹 配 由 26 个 英 文 字 母 的 小 写 组 成 的 字 符 串 [ A − Z a − z 0 − 9 ] +   //匹配由26个英文字母的小写组成的字符串 ^[A-Za-z0-9]+   //26[AZaz09]+  //匹配由数字和26个英文字母组成的字符串
^\w+$  //匹配由数字、26个英文字母或者下划线组成的字符串

下面是一些特殊字符:
正则表达式中的特殊字符: (学习参考书-<<精通正则表达式>>)
字符
意义:对于字符,通常表示按字面意义,指出接着的字符为特殊字符,不作解释。
例如:/b/匹配字符’b’,通过在b 前面加一个反斜杠,也就是/b/,则该字符变成特殊字符,表示
匹配一个单词的分界线。
或者:
对于几个字符,通常说明是特殊的,指出紧接着的字符不是特殊的,而应该按字面解释。
例如:是一个特殊字符,匹配任意个字符(包括0个字符);例如:/a/意味匹配0个或多个a。
为了匹配字面上的*,在a前面加一个反斜杠;例如:/a*/匹配’a*’。

字符^
意义:表示匹配的字符必须在最前边。
例如:/^A/不匹配"an A,"中的’A’,但匹配"An A."中最前面的’A’。

字符$
意义:与^类似,匹配最末的字符。
例如:/t$/不匹配"eater"中的’t’,但匹配"eat"中的’t’。

字符*
意义:匹配前面的字符0次或n次。
例如:/bo
/匹配"A ghost booooed"中的’boooo’或"A bird warbled"中的’b’,但不匹配"A goat g
runted"中的任何字符。

字符+
意义:匹配+号前面的字符1次或n次。等价于{1,}。
例如:/a+/匹配"candy"中的’a’和"caaaaaaandy."中的所有’a’。

字符?
意义:匹配?前面的字符0次或1次。
例如:/e?le?/匹配"angel"中的’el’和"angle."中的’le’。

字符.
意义:(小数点)匹配除换行符外的所有单个的字符。
例如:/.n/匹配"nay, an apple is on the tree"中的’an’和’on’,但不匹配’nay’。

字符(x)
意义:匹配’x’并记录匹配的值。
例如:/(foo)/匹配和记录"foo bar."中的’foo’。匹配子串能被结果数组中的素[1], …, [n] 返
回,或被RegExp对象的属性$1, …, $9返回。

字符x|y
意义:匹配’x’或者’y’。
例如:/green|red/匹配"green apple"中的’green’和"red apple."中的’red’。

字符{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”。

字符[xyz]
意义:一字符列表,匹配列出中的任一字符。你可以通过连字符-指出一个字符范围。
例如:[abcd]跟[a-c]一样。它们匹配"brisket"中的’b’和"ache"中的’c’。

字符[^xyz]
意义:一字符补集,也就是说,它匹配除了列出的字符外的所有东西。 你可以使用连字符-指出一
字符范围。
例如:[abc]和[a-c]等价,它们最早匹配"brisket"中的’r’和"chop."中的’h’。

字符
意义:匹配一个空格(不要与b混淆)

字符b
意义:匹配一个单词的分界线,比如一个空格(不要与混淆)
例如:/bnw/匹配"noonday"中的’no’,/wyb/匹配"possibly yesterday."中的’ly’。

字符B
意义:匹配一个单词的非分界线
例如:/wBn/匹配"noonday"中的’on’,/yBw/匹配"possibly yesterday."中的’ye’。

字符cX
意义:这里的X是一个控制字符。匹配一个字符串的控制字符。
例如:/cM/匹配一个字符串中的control-M。

字符d
意义:匹配一个数字,等价于[0-9]。
例如:/d/或/[0-9]/匹配"B2 is the suite number."中的’2’。

字符D
意义:匹配任何的非数字,等价于[^0-9]。
例如:/D/或/[^0-9]/匹配"B2 is the suite number."中的’B’。

字符f
意义:匹配一个表单符

字符n
意义:匹配一个换行符

字符r
意义:匹配一个回车符

字符s
意义:匹配一个单个white空格符,包括空格,tab,form feed,换行符,等价于[ fnrtv]。
例如:/sw*/匹配"foo bar."中的’ bar’。

字符S
意义:匹配除white空格符以外的一个单个的字符,等价于[^ fnrtv]。
例如:/S/w*匹配"foo bar."中的’foo’。

字符t
意义:匹配一个制表符

字符v
意义:匹配一个顶头制表符

字符w
意义:匹配所有的数字和字母以及下划线,等价于[A-Za-z0-9_]。
例如:/w/匹配"apple,“中的’a’,”$5.28,"中的’5’和"3D."中的’3’。

字符W
意义:匹配除数字、字母外及下划线外的其它字符,等价于[^A-Za-z0-9_]。
例如:/W/或者/[^$A-Za-z0-9_]/匹配"50%."中的’%’。

字符n
意义:这里的n是一个正整数。匹配一个正则表达式的最后一个子串的n的值(计数左圆括号)。

php函数方面的问题:
1、数组函数
array_key_exists 判断key是否存在
is_array 判断是否是一个数组
in_array 判断给定的值是否在数据出现
array_count_values 判断值出现的次数
array_search 数组查找
array_merge 数组合并
array_map 对数组每个元素使用用户自定义的函数
array_change_case 改变数组key的大小写
sort数组排序
array_push 在数组尾部插入一个或者多个元素
array_pop 弹出数组最后一个元素
array_unshift 数组开头插入多个元素
array_shift 弹出数组第一个元素
implode 数组转字符串
shuffle 打乱数组的排序
array_rand 随机从数组去处多个单元
array_chunk 数组分割位新的数组
array_diff 差集
array_inestsert 交集
array_flip 交换键值
array_keys 返回数组所有键
count 计算数组长度

2、字符串函数
addcslashes — 为字符串里面的部分字符添加反斜线转义字符
addslashes — 用指定的方式对字符串里面的字符进行转义
bin2hex — 将二进制数据转换成十六进制表示
chop — rtrim() 的别名函数
chr — 返回一个字符的ASCII码
chunk_split — 按一定的字符长度将字符串分割成小块
convert_cyr_string — 将斯拉夫语字符转换为别的字符
convert_uudecode — 解密一个字符串
convert_uuencode — 加密一个字符串
count_chars — 返回一个字符串里面的字符使用信息
crc32 — 计算一个字符串的crc32多项式
crypt — 单向散列加密函数
echo — 用以显示一些内容
explode — 将一个字符串用分割符转变为一数组形式
fprintf — 按照要求对数据进行返回,并直接写入文档流
get_html_translation_table — 返回可以转换的HTML实体
hebrev — 将Hebrew编码的字符串转换为可视的文本
hebrevc — 将Hebrew编码的字符串转换为可视的文本
html_entity_decode — htmlentities ()函数的反函数,将HTML实体转换为字符
htmlentities — 将字符串中一些字符转换为HTML实体
htmlspecialchars_decode —htmlspecialchars()函数的反函数,将HTML实体转换为字符
htmlspecialchars — 将字符串中一些字符转换为HTML实体
implode — 将数组用特定的分割符转变为字符串
join — 将数组转变为字符串,implode()函数的别名
levenshtein — 计算两个词的差别大小
localeconv — 获取数字相关的格式定义
ltrim — 去除字符串左侧的空白或者指定的字符
md5_file — 将一个文件进行MD5算法加密
md5 — 将一个字符串进行MD5算法加密
metaphone — 判断一个字符串的发音规则
money_format — 按照参数对数字进行格式化的输出
nl_langinfo — 查询语言和本地信息
nl2br — 将字符串中的换行符“\n”替换成“

number_format — 按照参数对数字进行格式化的输出
ord — 将一个ASCII码转换为一个字符
parse_str — 把一定格式的字符串转变为变量和值
print — 用以输出一个单独的值
printf — 按照要求对数据进行显示
quoted_printable_decode — 将一个字符串加密为一个8位的二进制字符串
quotemeta — 对若干个特定字符进行转义
rtrim — 去除字符串右侧的空白或者指定的字符
setlocale — 设置关于数字,日期等等的本地格式
sha1_file — 将一个文件进行SHA1算法加密
sha1 — 将一个字符串进行SHA1算法加密
similar_text — 比较两个字符串,返回系统认为的相似字符个数
soundex — 判断一个字符串的发音规则
sprintf — 按照要求对数据进行返回,但是不输出
sscanf — 可以对字符串进行格式化
str_ireplace — 像str_replace()函数一样匹配和替换字符串,但是不区分大小写
str_pad — 对字符串进行两侧的补白
str_repeat — 对字符串进行重复组合
str_replace — 匹配和替换字符串
str_rot13 — 将字符串进行ROT13加密处理
str_shuffle — 对一个字符串里面的字符进行随机排序
str_split — 将一个字符串按照字符间距分割为一个数组
str_word_count — 获取字符串里面的英文单词信息
strcasecmp — 对字符串进行大小比较,不区分大小写
strchr — 通过比较返回一个字符串的部分strstr()函数的别名
strcmp — 对字符串进行大小比较
strcoll – 根据本地设置对字符串进行大小比较
strcspn — 返回字符连续非匹配长度的值
strip_tags — 去除一个字符串里面的HTML和PHP代码
stripcslashes — 反转义addcslashes()函数转义处理过的字符串
stripos — 查找并返回首个匹配项的位置,匹配不区分大小写
stripslashes — 反转义addslashes()函数转义处理过的字符串
stristr — 通过比较返回一个字符串的部分,比较时不区分大小写
strlen — 获取一个字符串的编码长度
strnatcasecmp — 使用自然排序法对字符串进行大小比较,不区分大小写
strnatcmp — 使用自然排序法对字符串进行大小比较
strncasecmp — 对字符串的前N个字符进行大小比较,不区分大小写
strncmp — 对字符串的前N个字符进行大小比较
strpbrk — 通过比较返回一个字符串的部分
strpos — 查找并返回首个匹配项的位置
strrchr — 通过从后往前比较返回一个字符串的部分
strrev — 将字符串里面的所有字母反向排列
strripos — 从后往前查找并返回首个匹配项的位置,匹配不区分大小写
strrpos – 从后往前查找并返回首个匹配项的位置
strspn — 匹配并返回字符连续出现长度的值
strstr — 通过比较返回一个字符串的部分
strtok — 用指定的若干个字符来分割字符串
strtolower — 将字符串转变为小写
strtoupper –将字符串转变为大写
strtr — 对字符串比较替换
substr_compare — 对字符串进行截取后的比较
substr_count — 计算字符串中某字符段的出现次数
substr_replace — 对字符串中的部分字符进行替换
substr — 对字符串进行截取
trim — 去除字符串两边的空白或者指定的字符
ucfirst — 将所给字符串的第一个字母转换为大写
ucwords — 将所给字符串的每一个英文单词的第一个字母变成大写
vfprintf — 按照要求对数据进行返回,并直接写入文档流
vprintf — 按照要求对数据进行显示
vsprintf — 按照要求对数据进行返回,但是不输出
wordwrap — 按照一定的字符长度分割字符串

关于代码规范如何说?

我们在写接口的时候写了一个统一的验证和返回

要求每个文件必须有自己的注释、每个类都有自己的注释、每个方法都必须有注释 、对于不确定的需求或者后期可能遇到的问题 必须加上 todo

关键逻辑必须写上注释

在调用外部接口不能在程序写死,必须单独自己建议一个配置文件,方便后期修改

数据库操作必须写在model里边,不允许在C层写数据库操作。

变量名必须能报清楚的表达自己的意思。

写接口之前必须搞定接口文档。

私有的方法必须加上 _ [ 重要 ,显得自己也是老司机]

类文件都是以.class.php为后缀(这里是指的ThinkPHP内部使用的类库文件,不代表外部加载的类库文件),使用驼峰法命名,并且首字母大写,例如 DbMysql.class.php;

类的命名空间地址和所在的路径地址一致,例如 Home\Controller\UserController类所在的路径应该是 Application/Home/Controller/UserController.class.php;
确保文件的命名和调用大小写一致,是由于在类Unix系统上面,对大小写是敏感的(而ThinkPHP在调试模式下面,即使在Windows平台也会严格检查大小写);
类名和文件名一致(包括上面说的大小写一致),例如 UserController类的文件命名是UserController.class.php, InfoModel类的文件名是InfoModel.class.php, 并且不同的类库的类命名有一定的规范;

函数、配置文件等其他类库文件之外的一般是以.php为后缀(第三方引入的不做要求);

函数的命名使用小写字母和下划线的方式,例如 get_client_ip;

方法的命名使用驼峰法,并且首字母小写或者使用下划线“_”,例如 getUserName,parseType,通常下划线开头的方法属于私有方法;
属性的命名使用驼峰法,并且首字母小写或者使用下划线“
”,例如 tableName、_instance,通常下划线开头的属性属于私有属性;
以双下划线“__”打头的函数或方法作为魔法方法,例如 __call 和 __autoload;

常量以大写字母和下划线命名,例如 HAS_ONE和 MANY_TO_MANY;

配置参数以大写字母和下划线命名,例如HTML_CACHE_ON;

语言变量以大写字母和下划线命名,例如MY_LANG,以下划线打头的语言变量
通常用于系统语言变量,例如 CLASS_NOT_EXIST

对变量的命名没有强制的规范,可以根据团队规范来进行;

ThinkPHP的模板文件默认是以.html 为后缀(可以通过配置修改);

数据表和字段采用小写加下划线方式命名,并注意字段名不要以下划线开头,例
如 think_user 表和 user_name字段是正确写法,类似 _username 这样的数据表字段可能会被过滤。

tp底层看过没有?
1、看过框架的底层没有?
看过tp的数据库驱动相关。 关于配置数据库方面的,在配置文件配置就直接可以使用各种数据库类型,自己简单看了下,主要就是通过一个driver(驱动类)来判断当前连接类型,然后调用对于的数据库操作类。
ps:如果是要我们自己实现的话,可以借助接口,每个数据库的操作类都需要集成一个接口,然后根据具体的配置去调用每个操作类。 就算后期我修改了数据库的类型,也不会导致程序需要改动。
2、看过tp的cache类,和数据库类似,修改过redis的cache类,因为tp的redis操作类不支持认证。
主要就是在redis操作类添加了个认证
$this->handler = new \Redis;
$options[‘timeout’] === false ?
t h i s − > h a n d l e r − > this->handler-> this>handler>func($options[‘host’], $options[‘port’]) :
t h i s − > h a n d l e r − > this->handler-> this>handler>func($options[‘host’], $options[‘port’], $options[‘timeout’]);
$this -> handler->auth( C(‘REDIS_AUTH_KEY’) );
3、看过tp的处理异常类
路径 ThinkPHP/library/Think/Think.class.php

主要使用的是php自带的错误处理相关函数

register_shutdown_function 定义PHP程序执行完成后执行的函数
set_error_handler 设置用户自定义的错误处理程序
set_exception_handler 设置自己的异常处理机制

借助 get_last_error获取最后一次报错的信息
根据报错级别可以自定义写日志
这个地方我们在做接口的时候纪录了一些错误日志,帮助我们排查一些问题。
如果要看文件加载以及调用关系可以借助 print_debug_backtrace获取文件加载的顺序

 // 注册AUTOLOAD方法
  spl_autoload_register('Think\Think::autoload');      
  // 设定错误和异常处理
  register_shutdown_function('Think\Think::fatalError');
  set_error_handler('Think\Think::appError');
  set_exception_handler('Think\Think::appException');

4、简单看了下tp的命名空间自动记载
框架下的核心类都包含进来了,其他的事借助 spl_register_autoload实现

关于缓存穿透的问题:
缓存穿透值得是,访问数据库中不存在的数据,查不到数据之后就不会把数据缓存起来,如果频繁的访问这个数据的话,就会一直访问数据库,导致数据库压力过大甚至数据库崩溃。
解决缓存穿透的问题?
把不存在的key值也做一个缓存,缓存在null值或者是空值。

缓存崩溃的问题:
缓存崩溃之后,会导致数据库压力瞬间变大,如果数据库不能承受这么大的并发量的话,会导致数据库也会因为压力过大导致数据库宕机。数据库宕机之后整个网站也就瘫痪了。
如何解决?
1、多台内存服务器做集群( 其中一台服务器挂掉之后,只会有部分压力到数据库 )
2、做好数据预热脚本。
3、memcache做一个备份( 2台服务器 )
4、redis可以使用redis proxy管理

关于一台服务器搭建负载均衡或者是主从复置?
创建多个实例就可以了。( 负载均衡安装多个nginx,主从复制安装多个mysql )

接口安全怎么保证?
1、appid+appkey做一个访问的校验,只能是合法的请求才去做业务处理。
2、对称加密或者是非对称加密
3、签名校验 ( 注意appid是要传输,appkey是放在签名中的 )
4、接口防刷 ( redis记录访问ip,每次访问给这个ip加1,到指定数量就加入黑名单,指定时间不允许访问 )

关于支付同步回调和异步回调。( 同步通知异步通知 )
同步回调和异步回调,都是在支付时候第三发通知我们网站用的,同步回调一般用于展示页面,异步回调用来维护数据。 支付结果以异步回调为准


  1. a-zA-Z ↩︎

  2. 1-9 ↩︎

  3. 1-9 ↩︎

  4. A-Za-z ↩︎

  5. a-z ↩︎

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

weixin_43875836

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值