php面试总结20190114(常用linux命令、http状态码错误、RBAC权限管理,喝水问题)

本文涵盖PHP编程技巧,包括代码片段解析、正则表达式应用、RBAC权限管理原理及SQL查询优化。同时,深入介绍Linux常用命令,如ps、grep、awk、sed等,以及系统资源监控命令free和top的高级用法。

1.代码实现从数组中输出read_num大于200的个数。

$array = [['title'=>'www','read_num'=>564],['title'=>'aa','read_num'=>874],['title'=>'nn','read_num'=>245],['title'=>'sss','read_num'=>64]];
$sum = 0;
foreach($array as $key=>$value){
	
	if($value['read_num']>200){
		$sum = $sum+1;
	}
}
echo $sum;

2.常用的Linux命令。

1)ps:

参数:
-A:所有的进程均显示出来,与-e具有同样的效用;
-a:显示现行终端机下的所有进程,包括其他用户的进程;
-u:以用户为主的进程状态;
x:通常与a这个参数一起使用,可列出较完整的信息。
输出格式规划:
l:较长、较详细的将该PID的信息列出;
j:工作的格式
-f做一个更为完整的输出

2)grep

是三大常用的文本(awk,sed,grep)处理工具之一。
参数:
-E:开启扩展(Extend)的正则表达式。
-i:忽略大小写
-v:反过来,只打印匹配没有的,匹配的反而不打印
-n:显示行号
-w:被匹配的只能是单词,而不是单词中的某一部分,比如文本中有liker,而要找的只是like,就可以使用-w来避免匹配liker
-o:只显示被模式匹配到的字符串
--color:将匹配到的内容以颜色高亮显示
-A  n:显示匹配的字符串所在的行及其后n行,after
-B  n:显示匹配的字符串所在的行及其前n行,before
-C  n:显示匹配的字符串所在的行及其前后各n行,context
模式部分:

直接输入要匹配的字符串这个可用fgrep(fast grep)代替来提高查找速度,比如我要匹配一下hello.c文件中的printf的个数:grep -c "printf" hello.c

使用基本的正则表达式:
匹配字符:
.:任意一个字符
[abc]:表示匹配一个字符,这个字符必须是abc中的一个
[a-zA-Z]表示匹配一个字符,这个字符必须是a-z或者A-Z这52个字母中的一个。
[^123]:匹配一个字符,这个字符是除了1、2、3以外的所有字符

匹配次数:
\{m,n\}:匹配前面出现的字符至少m次,至多n次。
\?:匹配其前面出现的内容0次或者1次,等价于\{0,1\}
*:匹配其前面的内容任意次,等价于\{0,\},所以".*"表述任意字符任意次,即无论什么内容全部匹配。

位置锚定:
^:锚定行首
$:锚定行尾。技巧:"^$"用于匹配空白行。
\b或\<:锚定单词的词首。如"\blike"不会匹配alike,但是会匹配liker
\b或\>:锚定单词的词尾。如\blike\b不会匹配alike和liker,只会匹配like
\B:与\b作用相反。

分组及引用:
\(string\):将string作为一个整体方便后面引用
    \1:引用第一个左括号及其对应的右括号所匹配的内容。
    \n:引用第n个左括号及其对应的右括号所匹配的内容。

3)awk

http://www.ruanyifeng.com/blog/2018/11/awk.html

4)sed

sed是一个很好用的文件处理工具,本身是一个管道命令,主要是以行为单位进行处理,可以将数据行进行替换、删除、新增、选取等特定工作。

参数:
p==print
d:delete
=:打印匹配的行号
-n 取消默认的完整输出,只要需要的
-e 允许多项编辑
-f 直接将sed的动作写在一个档案内,-f filename则可以进行filename内的sed动作
-i 修改文件内容
-r 不需要转义
命令:
a:新增,a的后面可以接字符串,而这些字符串会在新的一行(目前的下一行)出现。(多行时除最后一行外末尾        
  需用"\"续行)
c:取代,用此符号后的新文本替换当前行中的文本。续行同上。
d:删除,删除行
h:复制,把模式空间的内容复制到暂存缓冲区
H:复制,把模式空间的内容追加到暂存缓冲区
i:插入,在当前行之前插入文本。续行同上。
g:把暂存缓冲区里的内容复制到模式空间,覆盖原有的内容
G:把暂存缓冲区里的内容复制到模式空间,追加在原有的内容后面
p:列印,打印行。
q:结束或退出sed
s:取代,用一个字符串替换另一个

5)free

free命令显示系统内存的使用情况,包括物理内存、交换内存(swap)和内核缓冲区内存
参数:
-h 将内存数值变成带量词的
-h -s n指定内存间隔的秒数


输出内容:
mem 是内存的使用情况
swap 交换空间的使用情况
total 列显示系统总的可用物理内存和交换空间大小
used 列显示已经被使用的物理内存和交换空间
free 列显示还有多少物理内存和交换空间可用
shared 显示被共享使用的区里内存大小
buff/cache 显示被buffer和cache使用的物理内存大小
available 显示还可以被应用程序使用的物理内存大小

6)sort

sort是将文本内容加以排序,sort可针对文件内容以行为单位来排序。

参数:
-b 忽略每行前面开始处的空格字符
-c 检查文件是否已经按照顺序排序
-d 排序时,处理英文字母、数字及空格字符外,忽略其他字符
-f 排序时,将小写字母视为大写字母
-i 排序时,除了040至176之间的ASCII字符外,忽略其他的字符
-m 将几个排序好的文件进行合并
-M 将前面3个字母按照月份的缩写进行排序
-n 按照数值的大小排序
-o <输出文件>  将排序好的结果存入指定文件
-r 以相反的顺序来排序
-t 指定排序时所用的栏位分隔字符
+ <起始栏位>-<结束栏位> 以指定的栏位来排序,范围由起始栏位到结束栏位的前一栏位。
--version 显示版本信息

常用命令:

cat file|sort 把file 里的数据排序,注意是按照字典排序的,如果想按照数值排,需要加-n参数
cat file|sort -k2 -n -r 按照第二列 数值 倒序 排序,-k指定第几列,-r 反转

7)top

常用命令:
top 列出所有线程负载信息
top -H 列出所有线程的负载信息
top -H -p ${pid} 列出某个pid下所有线程的负载信息

3.正则表达式。

$str = 'id="video" src="/www/home/root/wnsghdthe.mp4"></div><p><span></span></p>';

//$pattern='/id="video" src="(.*)?"/'; 
preg_match('/id="video" src="(.*)?"/',$str,$match);
dump($match);die;

匹配的是啥?.*?分别是什么意思?

结果是:

从id到mp4后的双引号,是匹配以id="video" src="为开头,双引号为结束的字符串

.代表的是任意字符

*代表的是任意次数

?匹配前面的子表达式零次或一次

4.什么情况下代表php-fpm挂了。

当客户端发出请求的时候,页面提示502的时候,此时的nginx错误日志为(用的别人的):

27600#0: *78887 recv() failed (104: Connection reset by peer) while reading response header from upstream, 
client: 192.168.1.101, server: test.com, request: "POST /index.php HTTP/1.1", upstream: "fastcgi://unix:/dev/shm/php-fcgi.sock:", 
host: "test.com", referrer: "http://test.com/index.php"

php-fpm日志(也是别人的):

WARNING:  child 25708 exited on signal 15 (SIGTERM) after 21008.883410 seconds from start

解析:502代表php-fpm进程挂掉了,nginx失去通信

           504 代表gateway timeout 代表超时了,nginx等不到上游信息

502的解决思路:

php.ini参数

max_execution_time 会被request_terminate_timeout覆盖。如果set_time_limit不生效的话是因为设置的max_execution_time

php-fpm

max_children,pool进程是共用的,一个请求一个进程,如果没有足够的进程去处理请求,就会造成nginx等待,时间太长也会导致nginx报错

如果超过request_terminate_timeout这个时间 php-fpm就会杀死php子进程,nginx就会失去通信。

所以将request_terminate_timeout这个时间调成大于nginx的等待时间就可以了。

504的解决思路:

如果只改php.ini参数,执行时间脚本长了错误就会从502变成504,是因为nginx中也有关于上游服务器通信超时时间的配置

相关参数fastcgi_connect/read/send_timeout

499:代表客户端长时间接收不到服务器响应主动断开连接。

配置举例:

location ~ \.php$ {
                root                    /home/cdai/test.com;
                include                 fastcgi_params;
                fastcgi_connect_timeout      180;
                fastcgi_read_timeout            600;
                fastcgi_send_timeout            600;
                fastcgi_pass            unix:/dev/shm/php-fcgi.sock;
                fastcgi_index           index.php;
                fastcgi_param          SCRIPT_FILENAME         /home/cdai/test.com$fastcgi_script_name;
     }

5.403 Forbidden  是在哪设置的?

想要设置某个文件夹下的所有文件不能被访问,可以在nginx.conf文件下的server{}里面加一个location

location /abcd{//这里如果是/abcd/那文件夹abcde也会被禁止访问,如果禁止某文件的话,直接写文件路径
    return 403;
}

 

6.RBAC分角色管理权限的原理?用到了哪些表?外键有哪些?

我用到了auth_group(用户组—用户关系表)、auth_group_access(用户组-权限关系表)、user(用户表)、menu(权限树表)、auth_rule(权限表)。

7.从数据库表stu里取出age大于20的人的个数?按性别分组的age大于20的个数?

select count(age) as count from stu where age>20;

select count(age) as count,sex from stu where age>20 group by sex;

8.单引号和双引号的区别?为什么双引号比单引号的效率低?

单引号是表示一个单纯的字符串,双引号里的变量可以被加载。

因为双引号需要加载,这个我觉得我应该看看《php核心技术与最佳实践》这本书以后再来好好回答,从php的底层原理来回答。

9.编程:1元1瓶水,2个空瓶可以换1瓶水,n元钱可以喝几瓶水?

思路:n元钱已经可以知道可以喝n瓶水了,重要的是空瓶子可以换几瓶水。

比如10瓶水,会有10个空瓶,然后就会有5瓶水 +5个空瓶

5个空瓶,会有5个空瓶,2瓶水 + 3个空瓶(换水后留下的一个),

3个空瓶,1瓶水+2个空瓶(换水后留下的一个)

2个空瓶,1瓶水+1个空瓶

所以一共有 10 +5+2+1+1 = 19瓶水

代码:

function water($sum,$n){
	if($n<2){
		return $sum;
	}else{
		$sum = $sum + intval($n/2);
		return water($sum,intval($n/2)+$n%2);//向water()传入当前已经喝到的水瓶数和当前的空瓶数
	}
}
echo(water(0,6)+6);

扩展:1元钱喝1瓶水,2个空瓶可以换一瓶水,3个瓶盖可以换一瓶水,n元钱可以喝到几瓶水。(假如空瓶不包括瓶盖)

假如有10元钱,则此时会有10个空瓶。

10个空瓶  10个瓶盖  可以喝到5+3瓶水 剩8个空瓶 和 8+1个瓶盖

8个空瓶  9个瓶盖   可以喝到4+3瓶水  剩7个空瓶7个瓶盖

7个空瓶 7个瓶盖  可以喝到3+2瓶水 剩5+1个空瓶 5+1个瓶盖

6个空瓶 6个瓶盖   可以喝到3+2瓶水 剩5个空瓶  5个瓶盖

5个空瓶   5个瓶盖 可以喝到 2+1瓶水 剩3+1个空瓶 5个瓶盖

4个空瓶  5个瓶盖 可以喝到 2+1瓶水 剩3个空瓶 5个瓶盖

3个空瓶  5个瓶盖 可以喝到1+1瓶水  剩3个空瓶 4个瓶盖

3个空瓶  4个瓶盖 可以喝到 1+1瓶水 剩 3个空瓶 3个瓶盖

3个空瓶 3个瓶盖 可以喝到 1+1瓶水 剩 3个空瓶 2个瓶盖

3个空瓶 2个瓶盖 可以喝到 1瓶水 剩 2个空瓶  1+2(剩下2个没有兑换)个瓶盖

2个空瓶 3个瓶盖 可以喝到 1+1瓶水  剩2个空瓶 2个瓶盖

2个空瓶 2个瓶盖 可以喝到 1瓶水 剩 1个空瓶 3个瓶盖

1个空瓶 3个瓶盖可以喝到 1瓶水 剩2个空瓶 1个瓶盖

2个空瓶 1个瓶盖  1瓶水  剩 1个空瓶 2个瓶盖

结束,一共可以喝到43+10瓶水

代码:

function water($sum,$m,$n){
	//echo $m."---".$n."<br/>";
	if($m<3 && $n<2){
		return $sum;
	}else{
		if($m>=3){
			$sum = $sum + intval($m/3);
		}
		if($n>=2){
			$sum = $sum + intval($n/2);
		}
		return water($sum,intval($m/3)+intval($n/2)+$m%3,intval($n/2)+$n%2+intval($m/3));
	}
}
echo 10+water(0,10,10);

输出:

10.接口和继承的区别,如果一个类想要继承多个父类里面的特性怎么办?

1)php 不支持多继承,接口支持多继承。

2)权限问题,父类中的private方法不可被继承,不可被重写,protected方法可以被继承,被重写,但是不能被实例化对象调用,而接口的类的方法权限都是public。

想要继承多个父类里面的特性,可以多层次继承,比如:

class A{
}
class B extends A{
}
class C extends B{
}

 

聊得很好,只是自己基础有些差,面试官一直说让我多看书,不能需要啥学啥,确实大学没有好好上课,基础特别差,以后要慢慢补上来,多看书。

 

 

另外一家是笔试,后悔没有照照片。

1.写出冒泡排序。这个之前写过很多次了。

2.输出下面程序的结果。

$count = 5;
function get_count(){
	static $count = 0;
	return $count++;
}
++$count;
get_count();
echo get_count();

结果等于1,因为最后输出的是get_count(),里面的$count的作用域是在这个函数内的,在输出之前运行了一次get_count(),所以此时get_count()里面的$count= 1,而外面那个$count 是全局变量。

3.写出匹配邮箱和URL的正则表达式。

匹配邮箱地址:

^[A-Za-z\d]+([-_.][A-Za-z\d]+)*@([A-Za-z\d]+[-.])+[A-Za-z\d]{2,4}$

匹配URL地址:

 /^(?:([A-Za-z]+):)?(\/{0,3})([0-9.\-A-Za-z]+)(?::(\d+))?(?:\/([^?#]*))?(?:\?([^#]*))?(?:#(.*))?$/

4.输出下面程序的结果。

echo intval((0.3+0.5)*10);

输出:8

5.写sql语句将数据表里面的name字段由Beijing开头的改为以BJ开头。

update table set name = REPLACE(name,Beijing,BJ);

此处涉及到update 的concat和replace用法

①concat在原有的基础上追加内容

sql 语句:update 表名 set title=concat( title, '123') where id=1;

结果   id   title

    1     abc

更新后   1     abc123

②replace 替换原有字段内容里的值  

sql 语句:update 表名 set title=replace( title, 'abc', 'cdef') where id=1;

结果  id     title

    1   abcggg

更新后 1     cdefggg

6.编程实现页面有个input框导入jpg格式的图片,图片上传到/var/www/images/文件夹中,需要添加图片说明,将说明和导入时间添加进数据库。(id int  description varchar128 uploadDate varchar)

test.html

<form action="test.php" enctype="mutipart/form-date" method="post">
    <input name="file" type="file" >
    <input name="description" type="text">
    <input type="submit" value="提交">
</form>

test.php

if($_FILES){
    $tmp_name = $_FILES['tmp_name'];//临时存储路径
    $filename = $_FILES['name'];//文件名称
    $type = $_FILES['type'];
    if($type != 'jpg'){
        echo "只允许上传jpg格式图片!" ;
        exit();
    }
    if(is_uploaded_file($tmp_name)){//临时文件存在
        move_uploaded_file($tmp_name,'/var/www/images/'.$filename);
    }
}
if($_POST){
    $description = $_POST['description'];
    $uploadDate = date();
}
$sql = "insert into tPic (description,uploadDate) values($description,$uploadDate)";
$mysql = mysql_connect('localhost','root','root');
mysql_select_db('test');

7.下面有四个表。

user :id (int)          员工id                           city:  id (int)           城市id                           position: id(int)                职位ID

           name(varchar) 员工姓名                          name (varchar)  城市名称                                 name(varchar) 职位名称

           birth (date) 出生日期

           position(int)    任职位置id

           workCity(int)  工作城市id

           workDate(date) 入职时间

userPosHistory: id (id)   

                          name (int)    员工id

                          workCity(int)        工作城市

                          workDate(date)    入职时间

                          position(int)          工作职位

根据这四个表用html的table 列出2006年在北京工作的员工姓名、职位、城市,并且按照员工的生日(不是出生日期)排序,在员工的名下列出其曾经工作过的城市、职位,和时间,并且按照入职时间排序。

主要是SQL语句有两个:

$sql1 = "select user.name,position.name as position_name,city.name as city_name from user join city on user.workCity = city.id join position on user.position = position.id join userPosHistory on user.id = userPosHistory.name where (substring(user.workDate,1,4)='2016' AND city.name='北京') OR (substring(userPosHistory.workDate,1,4)='2016' AND city.name='北京') order by substring(`user`.birth,6)";

substring($str,1,4);从第一位开始截取4位

出来结果:

$sql2 = "select user.name,city.name as city_name,position.name as position_name,userPosHistory.workDate from user join city on user.workCity=city.id join position on user.position = position.id join userPosHistory on user.id=userPosHistory.name where user.id='1' order by userPosHistory.workDate";

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值