PHP工程师面试题+笔试题

R_Jeff

最近在广州找工作,大四狗,读着三本前两年刚升二本的学校,文科生,好像一切条件都非常不利,但我还是毅然选择这条路——拍黄片,人不能固步自封,还是要拓展一下自己的知识面,不能只学php而不拓展视野,还是要学学python、java、前端这些
面试得有点心塞,各种因为学历被刷,校招只投了几个,不是被刷了简历就是没勇气投,默默告诉自己,以后一定要叫自己的儿子多考几分!
她说我最近看起来很疲惫。
对啊因为找工作很多天睡不好了
他说还好,我们现在唯一的目标是找工作,不用考虑其他的。
是啊,就像高考那会一样。
话不多说,下面写一下最近所经历的一些面试题,以后会继续补充的

一、PHP基础

1.对于0,空值,'=','=='等的考察

以下代码输出什么

<?php
    function judge(){
        $num = 0;
        if($num = ''){
            echo 'a';
        }else{
            echo 'b';
        }
    }
?>

输出b,if中的空值赋值给$num,因此if条件必定为false,还有其他一些大同小异的题目,用=和==判断for循环的,只要把握好基本的概念就行了

2.对于emptyisset概念的考察

isset()empty()函数的区别在于,前者只验证一个值是否存在,后者在此基础上还会检验它的值是否非空和非0
注:empty()只检测变量,检测任何非变量的东西都将导致解析错误
isset() 判断一个变量是否已经设置
当设置一个变量值为0,empty() 认为这个变量同等于空,即相当于没有设置

可以定义一个变量,设置值为'',0,null,'aaa'几种不同情况下,用if判断empty、isset看看结果

3.预定义变量

如:php中输出当前脚本文件名的预定义变量是$_SERVER['PHP_SELF']
DOCUMENT_ROOT有关。如:地址为http://baidu.com/test/kkk.php...$_SERVER['PHP_SELF']='/test/kkk.php'
还有一些重要的如$_SERVER['DOCUMENT_ROOT'],输出网站所在的根目录,如'D:/work/www'
$_SERVER['SCRIPT_FILENAME'],输出'D:/work/www//kkk.php'
$_SERVER['HTTP_USER_AGENT'],获取客户端浏览器,操作系统等等
其他一些可以通过print_r($_SERVER)测试获得,当然不止这些,还有其他一些预定义变量,系统常量如__FILE__也是需要稍微去看一下

4.函数、算法考察

主要考察php的原生函数,暂时分为数组函数、字符串处理函数、时间函数、文件操作函数、数据库函数,后面再看看需不需要扩展。注意这些函数一定都要去过一遍。

(1.1)遍历指定文件夹下的所有文件夹及所有子文件夹

确定是文件夹 —— 打开文件夹(产生dh句柄) —— 循环读取文件夹内容(读取句柄的内容,即为file/folder) —— 递归读取上一步判断为folder且文件夹不为'.'或者'..'的文件夹内容

<?php

$dir = "D:/www/project/";
 function readDirectory($dir){
    if(is_dir($dir)){        //
         if ($dh = opendir($dir)) {
             while (($file = readdir($dh)) != false) {
                 if (is_dir($dir.$file) && $file!="." && $file!="..") {
                     echo $dir.$file."<br/>";
                     readDirectory($dir.$file."/");
                 }
             }
             closedir($dh);
         }
     }
} 
readDirectory($dir);

?>

(1.2)遍历指定文件夹下的所有文件及其子文件夹中的所有文件

<?php
    $dir = "D:/www/project/";
    function readDirectory($dir){
        if(is_dir($dir)){        //
             if ($dh = opendir($dir)) {
                 while (($file = readdir($dh)) != false) {
                     if (is_file($dir.$file)) {
                         echo "filename:".$file."<br/>";
                         // echo $dir.$file."<br/>";
                         echo "filetype:".filetype($dir.$file)."<br/>";
                     } 
                     if (is_dir($dir.$file) && $file!="." && $file!="..") {
                         readDirectory($dir.$file."/");
                     }
                 }
                 closedir($dh);
             }
         }
    }
    readDirectory($dir);

?>

(2)写一个方法获取url中的文件类型

如$url = 'http://www.qq.com/test.php?a=...'; 取出'php'

function getFileName($url){
    $a = explode('?', $url);
    $b = strrpos($a[0], '.');   //strrpos(被搜索字符串,要查找字符串,[查找开始的位置])  查找字符串最后一次出现的位置: 找到则返回最后一次出现的位置;未找到则返回false
    $c = substr($a[0], $b+1, 3);  //substr(被操作字符串,开始位置,[结束位置])  返回字符串的一部分
    return $c;
}

(3)接口知识的考察

eg.
用户登录认证,请求地址为http://www.aa.com/user.php,后...,验证是否正确
请求参数:时间戳 Time 什么鬼参数忘了,即为param 还有一个是token,token值是Time+param的MD5加密,中间有加号
返回参数:
成功:res['ret'] = 0; res['msg'] = 'success';
失败:res['ret'] = 1; res['msg'] = 'fail';
返回数据格式:json
下面是我的思路:

function valid(){
    $data = $_GET['data'];
    if(!$data){
        $res['ret'] = 1;
        $res['msg'] = 'fail';
        echo json_encode($res);
    }
    $str = $data['Time'] . '+' . $data['param'];
    if($data['token'] != md5($str)){
        $res['ret'] = 1;
        $res['msg'] = 'fail';
        echo json_encode($res);
    }else{
        $res['ret'] = 0;
        $res['msg'] = 'success';
        echo json_encode($res);
    }
}

其实今天笔试的时候做这道题忘了怎么返回json格式的数据了,就直接用了Thinkphp的ajaxReturn,后来回来的时候查了一下才知道原来直接echo,这么简单,框架还是为辅吧,要多写原生。今天笔试的是一家手游公司,对数据库操作和原生要求比较多。

5.get和post的区别

是http协议的两种请求方式,而http是基于TCP/IP应用层的协议,所以两种都是用的同一个传输层协议
get是将请求信息以键值对的形式放在URL上,post是通过HTTP Header 传递数据
当我们使用get时,所有的信息都会出现在URL地址中,安全性比较低。
使用get最大传递的数据长度是2kb(根据服务器配置以及用户浏览器配置考虑),所以如果在传输量小或者安全性不那么重要的情况下可以使用get
post并没有长度限制,安全性较高
有人说post比get更安全,这只是相对的,但都是可以被抓包的。要想安全传输,就只有加密,也就是 HTTPS

6.cookie和session

(1)cookie数据存放在客户的浏览器上,session数据放在服务器上
(2)cookie不是很安全,别人可以分析存放在本地的COOKIE并进行COOKIE欺骗,如果主要考虑到安全应当使用session
(3)session会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能,如果主要考虑到减轻服务器性能方面,应当使用COOKIE
(4)单个cookie在客户端的限制是3K,就是说一个站点在客户端存放的COOKIE不能3K。
(5)所以:将登陆信息等重要信息存放为SESSION;其他信息如果需要保留,可以放在COOKIE

7.cookie禁用后如何使用session

第一种方式:在每个超链接上添加一个PHPSESSID=$sid

//防止返回初始页产生新的session

if(isset($_GET["PHPSESSID"])){
session_id($_GET["PHPSESSID"]);
}
//启动一个session
session_start();
//获取当前session的session_id()
$sid=session_id();
//在每个链接上添加参数PHPSESSID=$sid
其他页面的获取方式为:
if(isset($_GET["PHPSESSID"])){
//设置当前的session为初始的session,session_id()一致即可
session_id($_GET["PHPSESSID"]) 
}
session_start();

第二种方式:使用 SID 常量替换链接上的 PHPSESSID=$sid (SID的值类似:PHPSESSID=sddg34r593dfdlksrewr)

if(isset($_GET["PHPSESSID"])){
session_id($_GET["PHPSESSID"]);
}
//启动一个session
session_start();

其他页面的获取方式为:
if(isset($_GET["PHPSESSID"])){
//设置当前的session为初始的session,session_id()一致即可
session_id($_GET["PHPSESSID"]) 
}
session_start();

第三种方式:使用session.use_trans_sid=1,php.ini中配置
这种方式会在url上自动加上SID(href,location,action,注意:js跳转不会添加上SID)

8.对缓存的了解

分布式缓存了解一下

9.PHP7升级遇到的问题(针对简历)

相关的问题还有PHP7性能提升了,为什么

10.PHP常用到的拓展

curl(连接通讯各种服务器、使用各种协议)、gd(图像生成和处理)、mcrypt(加密扩展库)、mysqli(跟mysql系统函数的区别:mysqli是mysql系统函数的增强版,更稳定更高效更安全,与mysql_query()对应的有mysqli_query(),属于面向对象,用对象的方式操作驱动mysql数据库。mysqli是永远连接函数,mysqli多次运行mysqli将使用同一连接进程,从而减少了服务器的开销。) openssl(对称/非对称加解密)、pcre(正则,相关的问题还有常用的正则库PCRE/POSIX)

11.常见的错误级别有哪些,解决方案

notice、warning、error、exception等
————————————————

二、mysql数据库知识

1.数据库的基本增删查改

基本的增删改查语句,关联语句,函数等过一遍就行,可以过一下imooc的教程
慕课网——与MySQL的零距离接触

2.谈谈数据库优化/复杂sql优化的方法

(1)遇到一个页面查询缓慢的时候,因为可能会有多个sql,所以我首先是会去开启慢查询日志,定位到是哪一条sql
(2)确定sql之后,如果是非查询类型的如修改删除就改为查询类型。
(3)检查sql是不是有一些复杂查询,比如子查询,联合查询等等,将这些可以拆分的sql拆解出来
(4)把拆解出来的sql进行show profiles检查,查看具体每条子sql的执行时间
(5)或者直接explain你的sql语句,
最主要的一个是type类型,可以看到指定的表使用的连接方式,是null,system,const,eq_ref,ref,range,index还是all(各自代表的含义)
比较好的sql查询至少达到range级别,最好达到ref
看看id列,id列表示执行顺序,id越大,则越先执行
(6)一张表的索引最好不超过6个。考虑删除使用不频繁的索引。理想的索引情况下,查询频繁,区分度高(如字段值只有男和女区分度就不高),长度小,尽量能覆盖常用的查询字段
针对列中的值从左往右建立索引,截的越短,重复度越高区分度越小,所以效果越不好
截的越长,区分度越高,索引效果好,但是增删改慢间接影响查询速度
优先考虑在where 和orderby建立索引。

还有其它常见的就

  • 把不需要的字段去掉
  • 给每个字段加默认值,避免使用NULL默认值
  • 字段长度能省则省,
  • 避免使用select *,
  • 减少在where中进行表达式、函数操作和or条件判断
  • 尽可能使用更小的字段类型(因为mysql从磁盘读取数据之后是存到内存当中,这意味着更小的数据类型使得从磁盘读取或者打包到内存效率会更好)等等

(7)字符集的转换:客户端或者应用程序使用的字符集可能和数据库使用的字符集不一致,需要在mysql运行过程中隐含转化
(8)模糊查询优化:
使用FULLTEXT全文搜索(注意前提是MyISAM存储引擎)
FULLTEXT解析器用“ ”(空格)、“,”(逗号)“.”(点号)作为默认的单词分隔符,因此对于不使用这些分隔符的语言如汉语来说,FULLTEXT解析器不能正确的识别单词,对于这种情况需做额外处理。
(9)尽量满足范式(有的情况下要用反范式)下面是三大范式的区别,也要去看一下
第一范式:数据库表的每一列都是不可分割的原子数据项,而不能是集合,数组,记录等非原子数据项。如果实体中的某个属性有多个值时,必须拆分为不同的属性

clipboard.png

第二范式:满足第一范式前提,当存在多个主键的时候,才会发生不符合第二范式的情况。比如有两个主键,不能存在这样的属性,它只依赖于其中一个主键,这就是不符合第二范式

![clipboard.png](/img
clipboard.png

第二范式:满足第一范式前提,当存在多个主键的时候,才会发生不符合第二范式的情况。比如有两个主键,不能存在这样的属性,它只依赖于其中一个主键,这就是不符合第二范式

clipboard.png

第三范式:满足第二范式前提,如果某一属性依赖于其他非主键属性,而其他非主键属性又依赖于主键,那么这个属性就是间接依赖于主键,这被称作传递依赖于主属性。

clipboard.png

3.谈谈Myisam和Innodb存储引擎

(1)MyISAM强调性能,其执行速度比InnoDB类型更快,但不支持事务,而InnoDB提供事务支持以及外部键、行级锁等高级数据库功能
(2)如果增删改操作比较多,或者需要事务支持,则使用Innodb,如果是读的操作比较多,则使用Myisam
(3)MyISAM表锁,Innodb行锁

4.谈谈memcached和redis的异同

(1)memcached只能使用简单的key-value形式进行存储,而redis还支持hash,list,set等等。因此需要其他的数据类型支持的时候用redis更方便
(2)memcached是多核,redis是单核,所以在存储小数据上redis性能更高,反之大数据上memcached的性能比redis要高
(3)memcached不支持持久化操作,数据不能备份,只能用于缓存使用,重启后数据全部丢失。
redis支持持久化操作可以数据备份和数据恢复
(4)redis只能使用单线程,性能受限于cpu性能,memecached是多线程

5.事务应用场景、隔离级别等

(1)事务的四大特性(ACID

Atomicity原子性:事务是一个不可分割的工作单位,要么都发生要么都不发生
Consistency一致性:必须使数据库从一个一致性状态变换到另外一个一致性状态(即开启一个事务之后不能再开启一个事务,除非提交或者新建一个线程)
Isolation隔离性:多个用户并发访问数据库时,数据库为每个用户开启的事务不能被其它事务的操作数据干扰,多个并发事务之间要相互隔离
Durability持久性:未commit之前可以回滚,一旦commit对数据的改变就是永久性的
事务保存点

可以设置多个保存点 savepoint a;savepoint b;savepoint c;
但是回退需要按照顺序回退,即如果回退rollback to b; c保存点就不存在了

(2)事务的隔离级别

①读未提交(read uncommitted)
set session transaction isolation level read uncommitted
②读已提交(read committed)
set session transaction isolation level read committed
③可重复读(repeatable read) 系统默认的隔离级别
set session transaction isolation level repeatable read
④可串行化(serializable)(独占某个线程的时候使用,直到A程序commit后B程序才能成功update,在那之前是在队列中)
set session transaction isolation level serializable
隔离程度,从上到下越来越强

(3)隔离级别带来的问题

①脏读:一个事务读取另一个事务尚未提交的修改
②不可重复读:同一查询在同一事务中多次进行,由于其他提交事务所做的修改或删除,每次返回不同的结果集
③幻读(虚读):同一查询在同一事务中多次进行,由于其他提交事务所做的插入操作,每次返回不同的结果集
image.png

6.mysql分库分表分区

三、算法

1.写一个函数判断数组的深度

function getDepth($arr){


$max_depth = 1;
foreach($arr as $key=>$val){
    if(is_array($val)){
        $depth = getDepth($val) + 1;
        if($depth > $max_depth){
            $max_depth = $depth;
        }
    }
    
}
return $max_depth;

}

四、计算机网络

1.说一下常见的HTTP状态码

(1)消息(临时响应):1字头。
这一类型的状态码,代表请求已被接受,需要继续处理。这类响应是临时响应,只包含状态行和某些可选的响应头信息,并以空行结束。由于 HTTP/1.0 协议中没有定义任何 1xx 状态码,所以除非在某些试验条件下,服务器禁止向此类客户端发送 1xx 响应。
eg.
100: 服务器仅接收到部分请求
101: 服务器已经理解了客户端的请求,并将通过Upgrade 消息头通知客户端采用不同的协议来完成这个请求。
(2)成功:2字头。
代表请求已经被服务器所接收、理解、并接受
eg.
200: 请求成功(其后是对GET和POST请求的应答文档。)
201: 请求被创建完成,同时新的资源被创建。
(3)重定向:3字头。
表示要完成请求,需要进一步操作。 通常,这些状态代码用来重定向。
eg.
300: 多重选择。链接列表。用户可以选择某链接到达目的地。
301: 页面永久重定向
302: 页面临时重定向
304: 资源未被修改,服务器告诉客户,原来缓冲的文档还可以继续使用
(4)请求错误:4字头。
这些状态代码表示请求可能出错,妨碍了服务器的处理
eg.
400: 服务器未能理解请求
401: 被请求的页面需要用户名和密码。
403: 对请求页面的访问被禁止。(通常为没有读权限)
404: 服务器无法找到被请求的页面。
408: 超出服务器等待时间
413: 由于所请求的实体的太大,服务器不会接受请求。
414: 由于url太长,服务器不会接受请求。当post请求被转换为带有很长的查询信息的get请求时,就会发生这种情况。
(5)服务器错误:5字头。
这些状态代码表示服务器在尝试处理请求时发生内部错误。这些错误可能是服务器本身的错误,而不是请求出错
eg.
500: 请求未完成。服务器遇到不可预知的情况。
502: 作为网关或者代理工作的服务器尝试执行请求时,从上游服务器接收到无效的响应。
503: 服务器临时过载或当机。
504: 网关超时。

五、前端

1.考察函数

<input type="text" good="" />
获取input标签中的good属性值所用的函数是getAttribute("good")

2.考察jquery

<div id='table'></div>

用ajax方法,把请求返回的参数(格式是json)填充到table中,以表格形式列出
21号下午一道笔试题,因为需要联系上文有点麻烦,大概讲一下思路吧,主要是考察对jq的ajax函数还有其他一些jq函数的熟悉程度,我直接上代码

var html = '';
$(function(){
    $.ajax({
        type:'post',
        url:'.....',
        data:(忘了发送的参数是什么了,随便写一下){
            a:111,
            b:222
        },
        dataType:json,
        success:function(data){
            var res = jQuery.parseJSON(data);
            for(var i=0;i<res.length;i++){
                html += '<tr><td>' + res[i].Time + '</td><td>' + res[i].num + '</td></tr>'; 
            }
            $('#table').html('<table>' + html + '</table>');
        },
        error:function(){
        }
    })
})

六、服务器相关知识

1.常用指令

随便写些常用指令:mkdir cd chmod rm cp tar make cat vi ps等等
查看文件最后10行:tail 1.txt
最后25行:tail -25 1.txt
头5行:head -5 1.txt

2.文件权限

755 rwxr-xr-x代表含义:
第一位7等于4+2+1,所以就是rwx,所有者有读取、写入、执行的权限
第二位5是4+1,r-x,同组用户具有读取、执行权限,
第三位5,代表其他用户有读取、执行的权限。
从左至右,1-3位代表文件所有者的权限,4-6位代表同组用户的权限,7-9代表其他用户的权限。

3.高并发大数据处理经验

(1)流量优化:

防盗链处理(在nginx上配置),防止图片、资源等被非法调用

(2)前端优化:

①合并一些css、js文件,减少http请求

雪碧图css spirites
前端自动构建工具打包
图片使用base64编码

②启用浏览器缓存和文件压缩

给静态资源文件指定过期时间
文件压缩如把图片压缩小一些,减少流量带宽消耗

③CDN加速

把一些前端资源文件放到cdn中,还可以把数据缓存到cdn节点中
cdn原理:

image.png
④建立独立图片服务器
⑤一些不重要的数据,可以做成ajax异步请求,在需要的时候再进行引入、展示,如js、jquery等等

(3)服务端

①页面静态化,如smarty
②做一些程序上的并发处理,如多线程多进程的异步处理、队列处理等
③队列处理

(4)数据库

①数据库缓存(memcache redis等)
②分库分表、分区操作

垂直拆分、水平拆分
分区

③读写分离

把一些服务器、一些数据完全分开
一些服务器做读操作(查询) 一些服务器做些操作(增删改)

④负载均衡
⑤索引、高并发安全问题加锁

(5)web服务器优化

使用nginx的反向代理来实现负载均衡

4.负载均衡

七、其他

1.遇到问题时怎么解决(错误日志)

我回答的时候举了做项目的时候的例子,先缕一下思路。因为后台这一块,只要思路缕清了,在纸上写出来,接下来一步一步去debug,不断var_dump、print_r、echo,最后exit()一下,其实很好debug
后来发现面试官想问的其实不是这个,而是错误日志,今天特意去搜了一下,研究了一个下午终于会一点点

首先开启错误日志,配置php.ini
error_reporting = E_ALL ;将会向PHP报告发生的每个错误,包括ERROR、NOTICE、WARNING等等
display_errors = Off ;本地测试开启,项目上线要关闭,防止服务器重要信息泄露
log_errors = On ;开启错误日志
log_errors_max_len = 1024 ;设置每个日志项的最大长度
error_log = /www/phpernote/error.log ;指定产生的错误报告写入的日志文件位置

配置完之后重启服务器即可,参考了php的异常和处理文章的一小段代码,自己另外做了测试

<?php
set_error_handler('myErrorHandler');
function myErrorHandler($errno,$errmsg,$file,$line){
    echo "<b>错误代码:</b>[{$errno}] {$errmsg} <br/>".PHP_EOL;
    echo "<b>错误行号:</b>{$file}文件中的第 {$line} 行<br/>".PHP_EOL;
    echo "<b>PHP版本:</b>".PHP_VERSION."(".PHP_OS.") <br/>".PHP_EOL;
    $datetime = date('Y-m-d H:i:s',time()); 
    error_log('时间:' . $datetime  . '错误的信息:' . $errmsg . '错误文件所在位置:' . $_SERVER['SCRIPT_FILENAME']);
 }

echo $test;
test();
 echo 'good';
?>

下面是error.log输出的内容
clipboard.png

网页输出的内容:

clipboard.png

2.常见的安全性问题

  • sql注入:利用用户输入揣测sql语句

    解决方案:addslashes、stripslashes函数、预处理绑定
    
  • xss攻击(跨站脚本攻击):,一种通过嵌入或者发布含有恶意脚本的链接,另一种是通过将恶意脚本提交到被攻击网站的数据库中

    解决方案:strip_tags()、htmlspecialchars()、htmlentities()等函数
  • CSRF(跨站请求伪造):利用用户在其它网站的cookie或session伪造请求

    解决方案:判断请求ip是不是来自本服务器;上面的防范xss攻击的方法也可以使用

mysql数据库备份、主从分离

  • ddos:(多个服务器同时向同一个服务器进行攻击)
    解决方案:防火墙、安装入侵检测工具

手动分割线
在上面提到的内容,其实有一些可以自己去拓展看一下的,比如提到innodb和myisam,前者是使用行锁,后者是使用表锁,那可以去拓展一下,什么是表锁什么事行锁,逐渐增大自己的知识面

先更新到这,明天还得去招聘会碰壁...
2017/03/18

先写到这里。前两天跑了广工招聘会,今天有一家联系明天面试了 ,继续去撞壁...
2017/03/20

今天基本确定offer,去一家手游公司,实习期一天100,转正后6K,包三餐,单双休,上午九点上班,周五周六6点下班,平时都是到8点,8~8.5小时的工作时间,上班时间有点大,不过应届毕业生嘛,学历也一般,其实这样的工作强度加上薪资我觉得已经是可以接受了。hr姐姐今天跟我说其实我笔试成绩一般,面试不错。希望实习期之间表现好一点,争取能够转正吧,希望各位应届毕业生也能有一份好的offer,多去尝试,学历高的固然好,学历低的也不要怕,多去跑一下招聘会宣讲会,还是感谢一直鼓励我去投其他公司的黑妹(男的),多尝试,总会有机会的!昨天刚过完22岁生日,今天确定offer,明天五月天演唱会,一切来得刚刚好。切骄切燥,加油!
2017/03/24

七月底裸辞了,顺便考了驾照,潇洒了一阵子。但是辞职时有多洒脱,现在就有多焦虑,找工作还是需要看缘分,不知道以后会不会继续做技术,还是觉得自己对技术没有太多的天分,很多东西还是比较文科生思维,希望能确定一份好的offer吧,期待那一声铃响。
2019/10/21

阅读 8.3k

网页狗修炼手册
大三狗正踏上web不归途

坚持拍黄片的大四网页狗要成为PHPer

405 声望
21 粉丝
0 条评论

坚持拍黄片的大四网页狗要成为PHPer

405 声望
21 粉丝
文章目录
宣传栏