2020年BAT大厂PHP工程师面试题整理(附带答案)

今天下午来到北京百度科技园进行面试PHP工程师岗位。面试官问了很多问题,因为主要是从事php方面的,所以下面谈的这些面试问题主要都是php方面的,当然其它的语言面试有些问题也会被问到。我大概整理回忆下:PHP开发工程师笔试试卷姓名:一、PHP开发部分1.合并两个数组有几种方式,试比较它们的异同答: 1)array_merge()2)’+’3)array_merge_recursivearray_merge 简单的合并数组array_merge_recursive 合并两个数组,如果数组中有完全一样的数据,将它们递归合并array_combine 和 ‘+’ :合并两个数组,前者的值作为新数组的键 2.请写一个函数来检查用户提交的数据是否为整数(不区分数据类型,可以为二进制、八进制、十进制、十六进制数字)答:其实主要还是is_int和 floor 这个方法if(!is_numeric($jp_total)||strpos($jp_total,".")!==false){    echo "不是整数";}else{    echo "是整数";}3.PHP的strtolower()和strtoupper()函数在安装非中文系统的服务器下可能会导致将汉字转换为乱码,请写两个替代的函数实现兼容Unicode文字的字符串大小写转换答:原因是:中文是由多字节组成的,而只有英文系统的单个英文字符只有一个字节,所以该系统把中文的每一个字节都做了strtolower()处理,改变后的中文字节拼接在一起就成了乱码(新生成的编码映射对应的字符可能就不是中文了)手动解决:用str_split(string string,intstring,intsplit_length = 1)按每个字节切割,像中文能切割成三个字节。对识别到的字节若是英文字母则进行转换。= 97 && $v<= 122){            $v -= 32;        }        $r .= chr($v);    }    return $r;}$a = 'a中你继续F@#$%^&*(BMDJFDoalsdkfjasl';echo 'origin string:'.$a."\n";echo 'result string:';$r = mystrtoupper($a);var_dump($r);4.PHP的is_writeable()函数存在Bug,无法准确判断一个目录/文件是否可写,请写一个函数来判断目录/文件是否绝对可写答:其中bug存在两个方面,1)在windowns中,当文件只有只读属性时,is_writeable()函数才返回false,当返回true时,该文件不一定是可写的。如果是目录,在目录中新建文件并通过打开文件来判断;如果是文件,可以通过打开文件(fopen),来测试文件是否可写。2)在Unix中,当php配置文件中开启safe_mode时(safe_mode=on),is_writeable()同样不可用。读取配置文件是否safe_mode是否开启。/*** Tests for file writability** is_writable() returns TRUE on Windows servers when you really can't write to* the file, based on the read-only attribute. is_writable() is also unreliable* on Unix servers if safe_mode is on.** @access   private* @return   void*/if ( ! function_exists('is_really_writable')){    function is_really_writable($file){    // If we're on a Unix server with safe_mode off we call is_writable    if (DIRECTORY_SEPARATOR == '/' AND @ini_get("safe_mode") == FALSE)    {        return is_writable($file);    }    // For windows servers and safe_mode "on" installations we'll actually    // write a file then read it. Bah...    if (is_dir($file))    {        $file = rtrim($file, '/').'/'.md5(mt_rand(1,100).mt_rand(1,100));        if (($fp = @fopen($file, FOPEN_WRITE_CREATE)) === FALSE)        {            return FALSE;        }        fclose($fp);        @chmod($file, DIR_WRITE_MODE);        @unlink($file);        return TRUE;    } elseif ( ! is_file($file) OR ($fp = @fopen($file, FOPEN_WRITE_CREATE)) === FALSE) {        return FALSE;    }    fclose($fp);    return TRUE;    }}5.PHP处理上传文件信息数组中的文件类型$_FILES[‘type’]由客户端浏览器提供,有可能是黑客伪造的信息,请写一个函数来确保用户上传的图像文件类型真实可靠答:用getimagesize来判断上传图片的类型比$_FILES函数的type更可靠同一个文件,使用不同的浏览器php返回的type类型是不一样的,由浏览器提供type类型的话,就有可能被黑客利用向服务器提交一个伪装撑图片后缀的可执行文件。可以通过getimagesize()函数来判断上传的文件类型,如果是头像文件 会返回这样的一个数组Array(    [0] => 331    [1] => 234    [2] => 3    [3] => width="331" height="234"    [bits] => 8    [mime] => image/png);如果通过getimagesize()函数返回的是这样的一个数组 说明上传的是头像文件。其中索引为2的表示类型1 = GIF,2 = JPG,3 = PNG,4 = SWF,5 = PSD,6 = BMP,7 = TIFF(intel byteorder),8 = TIFF(motorola byte order),9 = JPC,10 = JP2,11 = JPX,12 =JB2,13 = SWC,14 = IFF,15 = WBMP,16 = XBM,你可以通过这个再去限制上传的头像类型6.PHP通过对数据的URL编码来实现与Javascript的数据交互,但是对于部分特殊字符的编解码与Javascript的规则不尽相同,请具体说明这种差异,并针对UTF-8字符集的数据,写出PHP的编解码函数和Javascript的编解码函数,确保PHP编码数据可以被Javascript正确解码 、Javascript编码的数据可以被PHP正确解码答://js  decodeURIComponent   貌似对GB2312编码的格式不识别,必须转为utf-8才可以,然后,如果字符串中有空格的  就转为 +  号了

7.试阐述Memcache的key多节点分布的算法?当任一节点出现故障时PHP的Memcache客户端将如何处置?如何确保Memcache数据读写操作的原子性?答:原理:一致性hash          原子性原子性会导致的问题:简单的说就是A,B都想操作key1,然后都在key1上增加自己的信息,就会有问题memcached是原子的吗?宏观所有的被发送到memcached的单个命令是完全原子的。如果您针对同一份数据同时发送了一个set命令和一个get命令,它们不会影响对方。它们将被串行化、先后执行。即使在多线程模式,所有的命令都是原子的;命令序列不是原子的。如果您通过get命令获取了一个item,修改了它,然后想把它set回memcached,我们不保证这个item没有被其他进程(process,未必是操作系统中的进程)操作过。在并发的情况下,您也可能覆写了一个被其他进程set的item。memcached 1.2.5以及更高版本,提供了gets和cas命令,它们可以解决上面的问题。如果您使用gets命令查询某个key的item,memcached会 给您返回该item当前值的唯一标识。如果您覆写了这个item并想把它写回到memcached中,您可以通过cas命令把那个唯一标识一起发送给 memcached。如果该item存放在memcached中的唯一标识与您提供的一致,您的写操作将会成功。如果另一个进程在这期间也修改了这个 item,那么该item存放在memcached中的唯一标识将会改变,您的写操作就会失败。 8.如何实现PHP的安全最大化?怎样避免SQL注入漏洞和XSS跨站脚本攻击漏洞?答:基本原则:不对外界展示服务器或程序设计细节(屏蔽错误),不相信任何用户提交的数据(过滤用户提交)1)屏蔽错误,将display_errors 设置为off2)过滤用户提交参数,这里需要注意的是不能仅仅通过浏览器端的验证,还需要经过服务器端的过滤这里是需要注意最多的地方,因为所有用户提交的数据入口都在这里,这是过滤数据的第一步。考虑是否过滤select,insert,update,delete,drop,create等直接操作数据的命令语句使用addslashes 将所有特殊字符过滤打开magic_quotes_gpc,开启该参数数后自动将sql语句转换,将 ' 转换成  \'3)可以考虑设置统一入口,只允许用户通过指定的入口访问,不能访问未经许可的文件等内容4)可以考虑对安全性要求高的文件进行来源验证,比如要想执行b.php必须先执行a.php,可以在b.php中判断来自a.php的referer,避免用户直接执行b.php 二、系统相关部分1.请简述Linux/BSD系统下进程间通讯的方式有哪些,并具体说明在PHP下如何实现答:管道(Pipe)及有名管道(namedpipe):管道可用于具有亲缘关系进程间的通信,有名管道克服了管道没有名字的限制,因此,除具有管道所具有的功能外,它还允许无亲缘关系进程间的通信;信号(Signal):信号是比较复杂的通信方式,用于通知接受进程有某种事件发生,除了用于进程间通信外,进程还可以发送信号给进程本身;linux除了支持Unix早期信号语义函数sigal外,还支持语义符合Posix.1标准的信号函数sigaction(实际上,该函数是基于BSD的,BSD为了实现可靠信号机制,又能够统一对外接口,用sigaction函数重新实现了signal函数);报文(Message)队列(消息队列):消息队列是消息的链接表,包括Posix消息队列systemV消息队列。有足够权限的进程可以向队列中添加消息,被赋予读权限的进程则可以读走队列中的消息。消息队列克服了信号承载信息量少,管道只能承载无格式字节流以及缓冲区大小受限等缺点。共享内存:使得多个进程可以访问同一块内存空间,是最快的可用IPC形式。是针对其他通信机制运行效率较低而设计的。往往与其它通信机制,如信号量结合使用,来达到进程间的同步及互斥。信号量(semaphore):主要作为进程间以及同一进程不同线程之间的同步手段。套接口(Socket):更为一般的进程间通信机制,可用于不同机器之间的进程间通信。起初是由Unix系统的BSD分支开发出来的,但现在一般可以移植到其它类Unix系统上:Linux和SystemV的变种都支持套接字。 2.为什么会出现僵死进程(孤儿进程)?怎样查看僵死进程?如何解决僵死进程问题?答:僵尸进程:一个进程使用fork创建子进程,如果子进程退出,而父进程并没有调用wait或waitpid获取子进程的状态信息,那么子进程的进程描述符仍然保存在系统中。这种进程称之为僵死进程。查看:使用ps aux删除:ps aux | grep -e ‘^ [Zz]’ | awk ‘{print $2}’ | xargs kill -93.请描述Apache 2.x版本的MPM(Multi-Processing Module)机制,并具体说明在不同的MPM机制下如何支持PHP?答:常用的应该就只有3个:worker、prefork、perchildprefork:在功能上就是使用Apache的运行方式,一个父进程,然后根据设置以及连接情况生成相应的子进程数。这种模式可靠性和健壮性都是最好的。但是在性能上,开销过大。达不到我们这些“吸血鬼”的要求了_。如果连接数过多的话,会导致我们无法远程登陆,一定要等到连接数下降后才能连接,这也是最让我头痛的事情。worker:混合线程/进程的MPM。一个父进程,后面是带有线程的子进程。每个子进程的线程数是固定且相同的。这是最“平庸”的一个模式,但也是使用人最多的一种模式。因为它性能等各方面比较均衡。性能上要比prefork好一些,只是牺牲了一点点的健壮性和可靠性而已。一般推荐使用这个选项。perchild:也是混合线程/进程的MPM。当启动perchild MPM时,它会建立指定数量的子进程,且每个子进程都具有指定数量的线程,如负载增加了,那它不会建立新的进程(子进程是固定的),只是在子进程下建立新的线程。它还有一个特点就是可以为每一个子进程配置不同的用户和组。也可以为每个虚拟主机指定一个子进程。这种模式性能是最佳的,但是可靠性和健壮性就相对是最差的。各取所需,我个人觉得这种模式也不错,如果你不用第三方的模块的话_。 4.请简述PHP在Apache下的几种运行方式并加以比较?如何让PHP在Linux+Apache下以Fast CGI方式运行?答:php在apache有3中运行方式:CGI模式、FastCGI模式、Apache 模块DLL。比较:Cgi模式和模块dll加载方式比较:Cgi模式下,apache调用外部执行器php.exe执行php代码,并将解释后生成的html代码和原html整合,再传递给apache服务器,其在执行时每次都需要重新解析php.ini、重新载入全部dll扩展并重初始化全部数据结构,运行速度非常慢,但因为是外部加载执行器,php代码执行出错不会导致apache崩溃。在模块化(DLL)中,PHP是与Web服务器一起启动并运行的。所以从某种角度上来说,以apache模块方式安装的 PHP4有着比CGI模式更好的安全性以及更好的执行效率和速度。Cgi和fastcgi模式比较:Fastcig是cgi的升级版,Cgi和fastcgi工作模式大抵相同,但fastcgi模式中fastcgi的进程管理器可用来管理cgi解释器,该管理器在cgi解释器完成请求后,会处于挂起状态,用以等待接下来的请求,因为向比较cgi每次都需要重新解析php.ini、重新载入全部dll扩展并重初始化全部数据结构,fastcig模式明显要快很多。 5.请写出让PHP能够在命令行下以脚本方式执行时安装PHP所必须指定的configure参数,并说明如何在命令行下运行PHP脚本(写出两种方式)同时向PHP脚本传递参数?答:由于 –enable-cli 和 –enable-cgi 同时默认有效,因此,不必再配置行中加上 –enable-cli 来使得 CLI 在 make install 过程中被拷贝到 {PREFIX}/bin/phpphp -f “index.php”php -r “print_r(get_defined_constants());”试题二:1、请列举你能想到的UNIX信号,并说明信号用途。答:Unix信号量也可以在文件/usr/include/sys/signal.h中查看SIGHUP 进程由於控制终端死去或者控制终端发出起命令SIGINT 键盘中断所产生的信号SIGQUIT 键盘终止 2、请列举、你能想到的所有的字符串查找算法,并加注释简单说明。答:顺序查找二分查找分块查找哈希表查找 3、有一个IP地址(192.168.0.1),请写出其32位无符号整数形式。答:此题是将十进制转换成二进制 采用取余法即可很简单 答案是:11000000.10101000.00000000.00000001 千万不能只记答案哦 4、写出、你能想到的所有HTTP返回状态值,并说明用途(比如:返回404表示找不到页面)答:200 (成功) 服务器已成功处理了请求。通常,这表示服务器提供了请求的网页。301 (永久移动) 请求的网页已永久移动到新位置。服务器返回此响应(对 GET 或 HEAD 请求的响应)时,会自动将请求者转到新位置。302 (临时移动) 服务器目前从不同位置的网页响应请求,但请求者应继续使用原有位置来进行以后的请求。401 (未授权) 请求要求身份验证。对于需要登录的网页,服务器可能返回此响应。403 (禁止) 服务器拒绝请求。404 (未找到) 服务器找不到请求的网页。500 (服务器内部错误) 服务器遇到错误,无法完成请求。501 (尚未实施) 服务器不具备完成请求的功能。例如,服务器无法识别请求方法时可能会返回此代码。502 (错误网关) 服务器作为网关或代理,从上游服务器收到无效响应。503 (服务不可用) 服务器目前无法使用(由于超载或停机维护)。通常,这只是暂时状态。504 (网关超时) 服务器作为网关或代理,但是没有及时从上游服务器收到请求。505 (HTTP 版本不受支持) 服务器不支持请求中所用的 HTTP 协议版本。 基础任务-选作(会得到额外分数):画几个你最熟悉的SERVER端模型出来(格式不重要,尽量将图画清楚,说明思路即可)进阶任务:1、PHP的垃圾收集机制是怎样的?说明:1)如果,你熟悉PHP源码,那么请从源码入手,回答些问题,会获得额外加分2)如果,你不熟悉PHP源码,那么尽你所能,多写点东西,包括利用自己的编程直觉得到的信息,都可以。3)对,则有分,错误不扣,不写无分。答:PHP可以自动进行内存管理,清除不再需要的对象。PHP使用了引用计数(referencecounting)这种单纯的垃圾回收(garbagecollection)机制。每个对象都内含一个引用计数器,每个reference连接到对象,计数器加1。当reference离开生存空间或被设为NULL,计数器减1。当某个对象的引用计数器为零时,PHP知道你将不再需要使用这个对象,释放其所占的内存空间。 2、请写出HTTP头,并符合以下要求:1)这是一个post请求2)目标:http://www.example.com:8080/test3)POST变量:username: testpwd: test2intro: Hello world!4)包含以下COOKIE信息:cur_query: you&me说明:1)如果,你记不得某个HTTP协议中的指令字了,那么,无奈这举是用“汉字”代替。2)如果,你能记住更多的HTTP协议指令字,那么多写几句,总是没坏处,对吧?3)最关键的,只需要画出正确的“轮廓”(还记得httpwatch等工具打印出来的头部吗?那就是“轮廓”的含义),也会有分数,但如果,连“轮廓”都写错了,那么就很遗憾了。答:Accept: text/html 可以接受的数据类型Accept-Encoding: gzip 接受的压缩类型Accept-Language: zh-CN 接受语言Cache-Control: no-cache 是否有缓存Connection : keep-alive 是否保持链接Host:http://www.example.com:8080/testCookie:intro=Hello world!Content-Disposition: form-data; username=”test”&pwd=”test2”&intro=”hello world!”User-Agent: 浏览器信息Referer: 前一个页面地址编程任务:我们碰到了大麻烦,一个新来的传教士惹恼了上帝,上帝很愤怒,要求我们把圣经(bbe.txt)背熟,直至他说哪个单词,我们就要飞快的回答出这个单词在第几行第几个单词位置。听说你是个优秀的程序员,那么帮助我们完成这个不可能的任务吧。要求如下:1)/myworks/example/bbe.txt,98版本英文圣经一本2)输入部分要求如下:php ./example.php [单词]3)输出部分如下:[单词] 1,2 2,4 5,6 表示:此单词在1行2列(第二个单词),2行4列…说明:1)此文本4MB之巨…2)单词的含义:由英文字母(大小写),数字(0-9)组成的串3)提供给你的机器OS为ubuntu 9.10,内存只有1G,而且,很不幸的,其中700M用来做了别的4)上机考试不允许上网,但我装了man文档以及读取CHM以及PDF的阅读器,在电脑的桌面的CHM文件夹中,有相应的PHP参考手册5)算法复杂度要求不能大于O(N^2)(就是N的平方)6)什么?PHP低效且用起来不顺手,好的,你可以用别的语言来实现。但注意:提供给你的机器上只有python 2.4/perl 5.8/gcc[g++] 4.1 答:两份答案感觉还可以 bbe.txt文件咱们没有 想像成是 空格 隔开的算了hello123 hello tim jasonwoaini1 tianjianxiong333 hh aaa/* 此文件用于根据bbe.txt文件对所有单词创建索引,相当于一次预处理 */  ini_set('display_errors','on');set_time_limit(0);$file = file($src); // 数组foreach($file as $i => &$ls){    $a = explode(" ",$ls);    $len = count($a);    if ($len > 0){        for($j=0;$i<$len;$j++){            $data = "此单词".$a[$j]."在".($i+1)."行,".($j+1)."列";            $key = md5(trim(strtolower($a[$j])));            file_put_contents($key,$data);        }    }    //echo $i.". > ".$ls.'
';}example.php:#!/usr/local/bin/php -q   0){    for($i=0;$i<$len;$i++){        echo getKey($arr[$i])."\n";    }}functuion getKey($key){    $str = "没有找到此单词[".$key."]";    if($key){        $fc = md5($key);        $str = file_get_contents($fc));    }    return $str;}?>别人的方法:1)使用ascii码,判断字符所在范围2)只要扫描一遍字符即可,复杂度为O(N)3)利用了php string{$i} 的特性,取字符串内任一字符4)todo:改为fgetc版本,可以完全不需要使用以上php特性5)字符串匹配算法:http://wendell07.blog.hexun.com/14112681_d.html,目前看来最快的方法:Sunday,由于本题是单词匹配,问题更简单,只要找到头尾……$word = $argv[1];$lines = 0;$handle = @fopen("bbe.txt", "r");if ($handle) {    while (!feof($handle)) {        $line = fgets($handle, 4096);        $local = local_word($line, $word);        $lines++;        if( !empty($local) ){            echo "$lines,".implode(' ',$local)."\n";        }    }    fclose($handle);}function local_word($line, $word){    $local = array();    $local_length = 1;    $word_length = strlen($word);    for($i = 0; ( $char = $line{$i} ) !== ''; $i++ ){        // 单词最后一个字符必定不是符号,且必有一个符号结尾,此计为一个新词        if( !is_symbel( $line{ $i-1 } ) && is_symbel($char) ){            $local_length++;        }             if( $char === $word[0] && // 如果第一个字符相同            is_symbel( $line{ $i-1 } ) && // 且为单词开始            is_symbel( $line{ $i+$word_length }) // 单词结尾应该为符号        ){            // 进入验证单词模式,一个一个字符比对            for($j = 1; ($w_char = $word{$j}) !== ''; $j++ ){                // 遇到单词字符不匹配                if( $w_char != $line{ $i+$j } ){                    $i += $j;                    break;                }                // 如果单词比对完全正确                if( $j == ($word_length-1) ){                    //echo "$line_length, $word_length\n";                    $local[] = $local_length;                }            }        }    }    return $local;}function is_symbel($char){    $asc = ord($char);    return !( (48 <= $asc && $asc <= 57) ||              (65 <= $asc && $asc <= 90) ||              (97 <= $asc && $asc <= 122) );}如果你经常参加面试的话,你就会发现几乎所有的面试开场白都是进行自我介绍,这是因为一方面面试官是刚从HR那里得到你的信息的,面试之前他可能不太了解你的具体信息,所以他希望你通过自我介绍这个环节,了解一下你的过往经历,还有就是他利用这个时间看下你的简历。经过三面、四面后几家公司等到了百度offer,下面我把面试的过程和一些面试题分享给大家,整理的PDF目录如下:说实话我并不是那种别人一看就很喜欢的工程师,因为一直在小公司做个小架构,所以适合我的职位范围相对来说很窄。不过没关系,跳出舒适区看一下其他风景,我感觉对我来说也是一件好事。

返回列表
上一篇:
下一篇: