设为首页 收藏本站
查看: 1205|回复: 0

[经验分享] PHP常见面试题目深入解答分析(一)

[复制链接]

尚未签到

发表于 2017-4-7 09:54:25 | 显示全部楼层 |阅读模式
高手请无视本文,骨灰们请直接绕行... :-)
  本文旨在对网上流传很广的部份初/中级PHP开发工程师面试题目做出一些解答.并对这些面试题对面试者的测试意义,以及题目本身做一些较为深入的分析.
也许大量的初/中级PHPer们在面试的时候已经发现,许多公司的面试题目其实基本类似.:-),或许出题者本身并不清楚这些题目究竟要考验应聘者哪方面的知识.(反正天下面试题一大抄).也有PHPer们认为这些面试题千篇一律,而且很没有意思,并不能看出应试者真实水平,时常抱怨:"单引号和双引号有什么区别,这种题目有什么意思吗?我只需要把东西做出来就OK了.",那么这些题目的背后究竟隐藏着什么样的细节呢?在这篇文章里,将做一些分析.
   题目一: 双引号和单引号的区别在哪里?
按照官方手册的说法,"单引号字符串中出现的变量和转义序列不会被变量的值替代".按这样的描述.单引号和双引号的区别无非就在于 变量 和 转义序列两方面.
  从 变量 方面来讲. 当用双引号或者定界符指定字符串时,其中的变量会被解析。比如以下例子
  <?php
  $v_char='test';
  echo "$v_char";
  ?>
  结果会输出 test
  而如果是 echo '$v_char'; 时 ,会原样输出 $v_char
  而转义符方面,如果是 echo "test\nnextline"; 则显示结果为
  test
  nextline
  如果是单引号,则会原样显示 test\nnextline ,其中的\n并不会做为换行转义.
  由此可以推导出的答案就是,一般来讲,单引号界定字符,要比双引号略微快.
  如果更进一步研究到编译层面,在scanning阶段针对双引号的词法规则处理的确比单引号要多近一倍,
  而在opcodes层面,我们来看一段代码:
  <?php
$show_value = 123;
echo 'sing_quote'.$show_value;
echo "double_quote{$show_value}";
  ?>
  将这段代码转换为opcodes后.结果如下:
  1: <?php
2: $show_value = 123;
0 ASSIGN !0, 123
3: echo 'sing_quote'.$show_value;
1 CONCAT 'sing_quote', !0 =>RES[~1]
2 ECHO ~1
4: echo "double_quote{$show_value}";
3 ADD_STRING 'double_quote' =>RES[~2]
4 ADD_VAR ~2, !0 =>RES[~2]
5 ECHO ~2
6 RETURN 1
  由此可以看出,双引号中直接显示变量也确实比单引号用(.)符号连接变量要略微复杂些.
  所以总的来说,如果不需要使用转义字符,则使用单引号确实比双引号要来得划算.
   题目二:传值与传引用有什么不同?(值传递与引用传递的区别)
  官方手册中,对于引用部份有着如下描述:引用是符号表别名 PHP 的引用允许用两个变量来指向同一个内容
  并且更进一步的指出:在 PHP 中,变量名和变量内容是不一样的,因此同样的内容可以有不同的名字。最接近的比喻是 Unix 的文件名和文件本身――变量名是目录条目,而变量内容则是文件本身。引用可以被看作是 Unix 文件系统中的 hardlink。
   既然引用都指向着同样的内容,那么只要对其中任意一个变量名施以任何改变内容值的语句,那么访问其它指向这块内容的变量名时,将得到更新后的内容.比如如下代码:
   $arr = array(1,2,3,4,5);
   foreach($arr as &$v)
   {
   $v++;
   }
   print_r($arr);
   将看到遍历数组后,数组中每一元素的值都被修改.
   在函数(或方法)传参中,将一变量作为参数时,是以引用的方式传处,还是值的方式传入,主要表现形式是在sample_call_function($varname) 还是 sample_call_function(&$varname) 上.
   从概念上分析,值传递是对内容进行"拷贝",引用传递是用内容进行"建立快捷方式",所以很多答题答案都讲值传递要复制一次内存数据,引用传递则省去了这个消耗,所以更划算.
   但从PHP底层处理方式来看,这种结论回答略显草率了.PHP底层对于变量内存管理是基于常见的copy on write(写时复制) 和change on write(改变时复制).所以对于
   $val = 'test';
   debug_zval_dump($val);
   在函数debug_zval_dump中使用到的$val,并不会多开辟一块内存空间来存放'test'的内容.
  但对于
   $val = 'test';
   $a = &$val;
   debug_zval_dump($val);
则又有不同,这时传参的$val则会新开辟一块内存空间来存放'test'. 这在PHP源码包,zend_execute.c中有完整的处理流程.

   题目三:include和require的区别是什么?  
  官方手册中对此的描述是:这两种结构除了在如何处理失败之外完全一样。include() 产生一个警告而 require() 则导致一个致命错误。
  这个解释其实已经相当详细了.当引用一个外部文件时,如果这个文件打开出错,require将直接中止程序,并抛出一个Fatal Error,而include只会抛出一个warning,并继续执行include下面的语句.
   另外.我在一些网站上看到过对include和require区别做出的如下解释:
   require ()函数工作方式与XSSI相类似;不管在程序的哪个部分使用了这个函数,只有程序一开始运行,头文件的内容就被作为程序本身的一部分来处理。因此,如果 您在一个条件判定语句中使用了require()函数,那么即使这个条件即使不为真,头文件也会被包含进来。
   而include()函数只是在执行到这一条语句时才会把头文件内容包含进来。如果程序没运行到这里,那PHP是不会管它的。这就意味着,您在条件判定部分使用include时,它会完全按照您希望的那样工作。

  那么这条解释的正确性究竟如何,我们可以做2个小实验:
   文件名: 1.php
   <?php
   if(0) include('2.php');
   if(0) require('2.php');
  ?>
  假设我们只有1.php,没有2.php 按照上述说法,当条件不为真时,文件也被包含进来,那么因为2.php根本不存在,所以必然程序会报错.但是上述程序的执行结果显然否定了按上述说法进行的推理.
  第二个实验,使用工具,查看上述代码最终生成的opcode:
  1: <?php
2: if(0) include('2.php');
0 JMPZ 0, ->3
1 INCLUDE_OR_EVAL '2.php', INCLUDE
2 JMP ->3
3: if(0) require('2.php');
3 JMPZ 0, ->6
4 INCLUDE_OR_EVAL '2.php', REQUIRE
5 JMP ->6
6 RETURN 1
  由opcode中,我们也很明显的看到了,include和require都是转换成 INCLUDE_OR_EVAL的OPCODE在执行,除了参数不同外,确实没有其它流程上的差别.
   题目四:SESSION与COOKIE的相同点和不同点是什么?
  SESSION和COOKIE均是用于将特定的数据保留下来,以便用于之后请求的方法.即:相同点是它们都基于为每个客户端在一个规定的访问时限里,保存下数据以供这个客户端之后请求使用.
  其不同的地方在于访问方式和处理的机制不同:
  COOKIE是基于特定的HTTP响应头,客户端收到相应指令后,将数据保存于客户端.之后每一次HTTP请求中,COOKIE数据都将被客户端送往服务器.服务器端脚本可通过 预定义变量数组 $_COOKIE来获取相关的值.
SESSION则是将数据保存于服务器端,但是和每一个客户端之间建立一个唯一的身份ID,即SESSION_ID,客户端向服务器发送这个SESSION_ID,服务器再根据SESSION_ID取出相应的数据.这个SESSION_ID的传递方式有两种,一是存放在客户端的cookie中,经由HTTP头隐式传递,要么经由URL显示传递.使用时可通过预定义变量数组 $_SESSION来获取相关的值.
  将这两者比较而言,COOKIE数据由于存放在客户端,减轻了服务器端存储方面的压力.但数据的安全性相对来说就要差一些.所以如果依靠COOKIE存放用户登录信息等敏感数据时,一定要对其做加密处理.而SESSION数据存放在服务器端,客户端本身访问不到直接数据,安全性相对COOKIE来说稍稍好一些.但对服务器的IO操作及存储方面会带来一些压力.尤其是PHP默认的SESSION处理机制,实际上就是将SESSION数据串行化,然后存放到一个以SESSION_ID为名字的文本文件中,用户量多的情况下带来的开销不容忽视.好在PHP的SESSION机制是非常灵活的,提供了相应方法改变SESSION处理机制.比如放到memcached里或其它地方 :-) 这得另开文章单独讲了.

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-361358-1-1.html 上篇帖子: [转载]让PHP支持大型项目-构建JSP、PHP与JAVA融为一体的开发环境 下篇帖子: PHP中$_SERVER的详细参数与说明
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表