10个值得深思的 PHP 面试问题

文章所罗列的问题虽然看似简单,但是每个背后都涵盖了一个或几个大家容易忽视的基础知识点,希望能够帮助到你的面试和平时工作。

算术运算符
  运算符      名称    结果            
  $a + $b      加法    $a 和 $b 的和
  $a – $b      减法    $a 和 $b 的差
  $a * $b      乘法    $a 和 $b 的积
  $a / $b      除法    $a 除以 $b 的商
  $a % $b      取模    $a 除以 $b 的余数
递增/递减运算符
  运算符    名称       结果
  ++$a   前加    $a 的值加一,然后进行操作
    $a++     后加    $a 的值先进行操作,后加一
    –$a   前减    $a 的值减一,然后进行操作
    $a–   后减    $a 的值先进行操作,后减一
实例:
<?php
  echo  $a=5+”5th”;    //输出:10
  echo  10%3;          //输出:1
  echo  10+ $a++;      //输出:20
  echo   5- –$a;        //输出:-5
?>
比较运算符
  运算符          名称         结果
  $a == $b      等于       TRUE,如果$a等于$b
  $a === $b      全等        TRUE,如果$a等于$b,并且它们的类型也相同
  $a != $b         不等       TRUE,如果$a不等于$b
  $a <> $b      不等          TRUE,如果$a不等于$b
  $a !== $b       非全等    TRUE,如果$a不等于$b,或者它们的类型不同
  $a < $b         小于        TRUE,如果$a严格小于$b
  $a > $b         大于        TRUE,如果$a严格$b
  $a <= $b      小于等于  TRUE,如果 $a 小于或等于$b
  $a >= $b      大于等于  TRUE,如果 $a 大于或等于$b
  另外一个条件运算符是“  ?   :  ”(或三元)运算符。

php常用的数据类型有:布尔类型,整型,浮点型,字符串,数组,对象,NULL

图片 1

实例:
<?php
     var_dump(0==”a”);  //输出:bool(true)      
    var_dump(0==”00″);      //输出:bool(true)
    var_dump(0===”00″);    //输出:bool(false)
    var_dump(0<>”abc”);   //输出:bool(false)
    var_dump(0!==”01″);  //输出:bool(true) 
    $a=10;
    $b=20;
    $str=$a>$b? “true”:”false”; 
    echo $str;    //输出:false 
?>
逻辑运算符
  运算符      名称      结果
  $a and $b    逻辑与    TRUE,如果 $a 与 $b 都为 TRUE。
  $a or $b    逻辑或    TRUE,如果 $a 或 $b 任一为TRUE。
  $a xor $b    异或        TRUE,如果 $a 和 $b 不同时
  ! $a              逻辑非  TRUE,如果 $a 不为 TRUE。
  $a && $b      逻辑与  TRUE,如果 $a 与 $b 都为TRUE。
  $a || $b        逻辑或  TRUE,如果 $a 或 $b 任一为TRUE。


Q1

第一个问题关于弱类型

$str1 = 'yabadabadoo';
$str2 = 'yaba';
if (strpos($str1,$str2)) {  
    echo "/"" . $str1 . "/" contains /"" . $str2 . "/"";
} else {
    echo "/"" . $str1 . "/" does not contain /"" . $str2 . "/"";
}

正确运行的输出结果:

"yabadabadoo" does not contain "yaba"

strpos是返回字符串str2在str1的位置,没有找到则返回false然而实际上这次返回了0而在if语句中0也被当作false,所以我们需要对false做类型判断,正确的代码如下:

$str1 = 'yabadabadoo';
$str2 = 'yaba';
if (strpos($str1,$str2) !== false) {  
    echo "/"" . $str1 . "/" contains /"" . $str2 . "/"";
} else {
    echo "/"" . $str1 . "/" does not contain /"" . $str2 . "/"";
}

需要注意的是我们使用了!==,在php 和 JS中= !相对==
更为严格需要要求数据类型一致。

  其中and与&& 、or与||是同一逻辑运算符的两种写法。 
  逻辑与和逻辑或 都是短路运算符。在遇到下列逻辑表达式时,PHP解释程序将不会计算右边的表达式:
  <?php
      $a=10;
      if(false && (++$a));
      echo $a;      //输出:10
      $b=10;
      if(true or (++$b));
      echo $b;      //输出:10
  ?>
位运算符
  位运算符允许对整型数中指定的位进行置位。如果左右参数都是字符串,则位运算符将操作字符的 ASCII 值。
  表达式     名称      结果
  $a & $b   按位与     将把 $a 和 $b 中都为 1 的位设为 1。
  $a | $b     按位或    将把 $a 或者 $b 中为 1 的位设为 1。
  $a ^ $b   按位异或  将把 $a 和 $b 中不同的位设为 1。
  ~ $a       按位非    将 $a 中为 0 的位设为 1,反之亦然。
  $a << $b   左移      将 $a 中的位向左移动 $b 次(每一次                           移动都表示“乘以 2”)。
  $a >> $b   右移      将 $a 中的位向右移动 $b 次(每一次                           移动都表示“除以 2”)。
    其他运算符
字符串运算符
有两个字符串运算符。第一个是连接运算符(“.”),它返回其左右参数连接后的字符串。第二个是连接赋值运算符(“.=”),它将右边参数附加到左边的参数后。
错误抑制操作符
在最常见的数据库连接与文件创建操作或出现除0等异常时,可以用@符号来抑制函数错误信息输出到浏览器端 $a=@(5/0)
  外部命令执行
       使用“来运行外部系统命令,注意不是单引号,是ESC下面那个按键
        <?php
          $out=`dir c:`;
              print_r($out);
        ?>//不建议使用
实例:
<?php
  $a=”hello”;
  $a.=” world! “;  //等同于:$a=$a.” world!”;
  echo $a;  //输出:hello world!  
  $m = 3;
  $m += 5;  //等同于:$m=$m+5;
  echo $m;   //输出:8

一.type: bool boolean布尔类型

Q2

下面的输出结果会是怎样?

$x = 5;
echo $x;  
echo "<br />";  
echo $x+++$x++;  
echo "<br />";  
echo $x;  
echo "<br />";  
echo $x---$x--;  
echo "<br />";  
echo $x;

实际运行结果是

5  
11  
7  
1  
5

关于 $x++ 和 $x–这个问题其实非常容易遇见,我们只需记住$x++使用最近的值,然后才自增。

运算符的优先级,++ 是明显高于 +,因此先执行++ 再执行 +
。关于运算符的优先级,有的时候我们真的可以通过括号来让我们的程序更让人直观的了解,毕竟代码不光是用于执行的,有的时候或许团队的可读性也是提高效率的一种。

  $c = ($b = 4) + 5; 
  echo $c;  //输出:9  
?>
    运算符优先级 
下表从低到高列出了运算符的优先级。 
  结合方向    运算符
  左      ,
  左      or
  左      xor
  左      and
  右      print
  右      = += -= *= /= .= %= &= |= ^=                      ~=   <<=  >>= 
  左      ? :
  左      ||
  左      &&
结合方向        运算符
  左      |
  左      ^
  左      &
  无      == != === !==
  无      <  <= > >= 
  左      <<  >>
  左      +  –  .
  左      *  /   %
  右      ! ~ ++ — (int) (float) (string) (array) (object) @
  右      [
  无      new

当转换为 boolean 时,以下值被认为是 FALSE:

Q3

关于变量的引用;

$a = '1';
$b = &$a;
$b = "2$b";

请问 $a 和 $b的值各位多少

部分第一时间会想到 $a=’1′
$b=’21′,仔细一看 $b=&$a,这里$b是变量$a的引用而不是直接 赋值。

1.布尔值 FALSE 本身;

Q4

下面是true还是false

var_dump(0123 == 123);  
var_dump('0123' == 123);  
var_dump('0123' === 123);

var_dump(0123 == 123);//
false,PHP会默认把0123当作8进制来处理,实际转化为10进制就是83,显然这不是相等的。

var_dump(’0123′ == 123);//
true这里php会非常有趣的将’0123′转换成一个数字而且默认去掉了前面的0也就是123==123

var_dump(’0123′ === 123);//
false很显然上面的问题已经说过了数字和字符串类型不一致。

2.整型值 0(零);

Q5

下面的代码有什么问题吗?输出会是什么,怎样修复它

$referenceTable = array();
$referenceTable['val1'] = array(1, 2);
$referenceTable['val2'] = 3;
$referenceTable['val3'] = array(4, 5);

$testArray = array();

$testArray = array_merge($testArray, $referenceTable['val1']);
var_dump($testArray);  
$testArray = array_merge($testArray, $referenceTable['val2']);
var_dump($testArray);  
$testArray = array_merge($testArray, $referenceTable['val3']);
var_dump($testArray);

实际输出如下:

array(2) { [0]=> int(1) [1]=> int(2) }  
NULL  
NULL

运行的时候你或许还能看到下面的警告

Warning: array_merge(): Argument #2 is not an array  
Warning: array_merge(): Argument #1 is not an array

array_merge需要传入的参数都是数组,如果不是,则会返回null。
你可以这样修改

$testArray = array_merge($testArray, (array)$referenceTable['val1']);
var_dump($testArray);  
$testArray = array_merge($testArray, (array)$referenceTable['val2']);
var_dump($testArray);  
$testArray = array_merge($testArray, (array)$referenceTable['val3']);
var_dump($testArray);

3.浮点型值 0.0(零);

Q6

$x应该是输出什么?

$x = true and false;
var_dump($x);

部分同学或许会第一时间想到false,实际上这里依旧是强调运算符的优先级,=
会比 and级别高点,因此等同下面的代码

$x = true;
true and false

答案显而易见。

4.空字符串,以及字符串 “0”;

Q7

经过下面的运算 $x的值应该是多少?

$x = 3 + "15%" + "$25"

答案是18,PHP是会根据上下文实现类型的自动转换

上面的代码我们可以这样理解,如果我们在与字符串进行数学运算,实际php会尽可能将字符串中的数组进行转换,如果是数字开头的话则转换成改数字比如”15%”会变成15,如果不是数字开头则会变成0;
上面的运算类似下面 :

$x = 3 + 15 + 0

5.不包括任何元素的数组;

Q8

运行下面的代码,$text 的值是多少?strlen($text)又会返回什么结果?

$text = 'John ';
$text[10] = 'Doe';

上面代码执行完毕后 $text = “John
D”(John后面会有连续的5个空格) strlen($text)会返回11

$text[10] =
“Doe”给某个字符串具体的某个位置具体字符时候,实际只会把D赋给$text.
虽然$text才开始只有5个自负长度,但是php会默认填充空格。这和别的语言有些差别。

6.不包括任何成员变量的对象(仅 PHP 4.0 适用);

Q9

下面的输出结果会是什么

$v = 1;
$m = 2;
$l = 3;

if( $l > $m > $v){  
    echo "yes";
}else{
    echo "no";
}

实际的输出是”no”,只要仔细分析就不难得出

$l>$m 会转换成1 ,则这个时候再和$m比较。

7.特殊类型 NULL(包括尚未赋值的变量);

Q10

执行下面代码$x会变成什么值呢?

$x = NULL;

if ('0xFF' == 255) {  
    $x = (int)'0xFF';
}

实际的运行结果是$x=0而不是255.

首先’oxFF’ ==
255我们好判断,会进行转换将16进制数字转换成10进制数字,0xff -> 255.

PHP使用is_numeric_string 判断字符串是否包含十六进制数字然后进行转换。

但是$x =
(int)’0xFF’;是否也会变成255呢?显然不是,将一个字符串进行强制类型转换实际上用的是convert_to_long,它实际上是将字符串从左向右进行转换,遇到非数字字符则停止。因此0xFF到x就停止了。所以$x=0

8.从空标记生成的 SimpleXML 对象。

注意事项:

1.var_dump((bool) “0”) ;                
//之前以为是true,字符串0返回false

   var_dump((bool) “0.0”) ;              //返回true

2.var_dump(0 == “sdade”);

   var_dump(“sdade” == 0);          
 //两个都是true,非数字字符串转化为整型为0

   var_dump(“sdade” == (string)0);//返回false

3.var_dump(“897” == 0);              
 //返回false,数字字符串转化为整型为本身数字

4.var_dump(!!”testing”);                  //直接返回bool类型

5.echo false                                      //输出空白

   echo true                                       //输出1


二.type:integer整型

整型值可以使用十进制,十六进制,八进制和二进制表示,前面可以使用符号(+或者-)

decimal:[+-]?[1-9][0-9]*                  //十进制表示方法

hexadecimal:[+-]?0[xX][1-9a-fA-F] //十六进制表示方法

octal:[+-]?0[1-7]+                             //八进制表示方法

binary:[+-]?0[b][01]+                        //二进制表示方法

注意事项:

1.如果进制数传递一个非法的数字,后面的其余数将会被忽略,如$a=01386将会赋值11

2.整数的范围可以用常量PHP_INT_MAX来表示如果整数溢出会将int转化为float类,如
                                     
 var_dump(5000000000*5000000000000);     //输出float 2.5E+22

3.当两个整数不能整除时,会将结果转化为float类型

    var_dump(17/2);                                                
 //输出float 8.5

4.将float强制转化为int类型是会向下取整

   var_dump((int)12.9);                                          
 //输出12

   var_dump((int)-12.9);                                        
 //输出-12

5.$a = TRUE;

   echo ($a++).$a;                                                  //
因为bool类型不能自加,输出11

6.可以将ip地址在数据库中存储为int类型,这样会读写更快

   var_dump($_SERVER[‘REMOTE_ADDR’]);         //输出192.168.10.1

   $ipArr = explode(‘.’, $_SERVER[‘REMOTE_ADDR’]);

   $ip = $ipArr[0] * 0x1000000

   + $ipArr[1] * 0x10000

   + $ipArr[2] * 0x100

   + $ipArr[3];

   $ipArr    = explode(‘.’,$_SERVER[‘REMOTE_ADDR’]);

   $ip      = $ipArr[0]<<24

   + $ipArr[1]<<16

   + $ipArr[2] <<8

   + $ipArr[3];

   var_dump($ip);                                     //输出3232238081

   var_dump(decbin($ip));                      
//输出11000000101010000000101000000001

   将$ip进行数据库读写操作

 
 从数据库取出得到ip时可以利用右移操作进行,分别保留高位右移24,16,8位得到各位。

 
 但是php操作的整数类型,右移会发生超出长度被截断可以将高位除法得到//对这块也不太明白。

   $ipArr[0]=(floor)($ip/0x1000000);

   $ip=$ip-$ipArr[0]*0x1000000;

   $ipArr[1] = ($ip & 0xFF0000)  >> 16;

   $ipArr[2] = ($ip & 0xFF00)  >> 8;

   $ipArr[3] = ($ip & 0xFF);

   $ipDotted=implode(‘.’,$ipArr);


三.type:float浮点型

注意事项:

1.浮点型字长和平台的精度有关:echo (int)((0.1 + 0.7) *
10);//输出7,因为浮点型0.1和0.7在存    
 储过程中以二进制存储无限循环,不能被精确表示:0.1+0.7内部表示成7.9999999999999991118…。

因此不要比较两个浮点数是否相等,但可以在相同精度下比较

   $x = 8 – 6.4;

   $y = 1.6;

   var_dump($x == $y);                                 // boolean false

   var_dump(round($x,3) == round($y,3)); //boolean true

2.var_dump(1.8e308);                                   //float INF
数据过大时会输出无穷大


四.type:string字符串

一个字符串可以用四种方式来表达

单引号;

双引号;

heredoc 语法结构;

nowdoc 语法结构。

注意事项:

1.单引号:

会原样输出单引号里面的内容,只转义反斜线()和单引号自身(‘)不会转义其他序列(例如n,r),也不会转义变量($a)。

echo ‘I ‘m coming in’;                                //I ‘m coming in

echo ‘C:\movie’;                                         //C:movie

echo ‘This will not expand: n a newline’; //This will not expand: n
a newline

echo ‘Variables do not $expand $either’;//Variables do not $expand
$either

2.双引号:

会输出双引号里面的内容,转义符号()和变量

n 换行

r 回车

t 水平制表符

v 垂直制表符

e Escape

f 换页

\ 反斜线

$ 美元标记

3.HereDoc结构:

Heredoc结构就象是没有使用双引号的双引号字符串。

<<<,在该运算符之后要提供一个标识符(可以用双引号括起来),然后换行,接下来是字符串本身,里面的字符将会被转义,最后要用前面定义的标识符作为结束标志,在结束标志符后面只能加一个分号,然后换行。

class foo

{

var $foo;

var $bar;

function foo()

{

$this->foo = ‘Foo’;

$this->bar = array(‘Bar1’, ‘Bar2’, ‘Bar3’);

}

}

$foo = new foo();

$name = ‘MyName’;

echo <<

My name is “$name”. I am printing some $foo->foo.

Now, I am printing some {$foo->bar[1]}.

This should print a capital ‘A’: x41

EOT;

会输出:

My name is “MyName”. I am printing some Foo.

Now, I am printing some Bar2.

This should print a capital ‘A’: A

4.NowDoc结构:

NowDoc结构类似于单引号字符串,用来将大段的字符串原样输出

<<<,后面的标识符要用单引号括起来,如<<<‘EOT’

5.字符串拼接:字符串拼接使用’,’,注意’+’没有这个功能

6.变量解析:当字符串内含有复杂语法时,需要使用花括号进行解析。

class beers {

const softdrink = ‘rootbeer’;

public static $ale = ‘ipa’;

}

$rootbeer = ‘A & W’;

$ipa = ‘Alexander Keith’s’;

echo “I’d like an {${beers::softdrink}}n”;//输出: I’d like an A & W

echo “I’d like an {${beers::$ale}}n”;       //输出: I’d like an
Alexander Keith’s

7.字符串转换为数值:

PHP是一个弱类型语言,当一个字符串被用来当做一个数值来取值时:

如果字符串里面以合法的数值开始,则取该数值,否则其值为0

$foo = “0123” + 0;                     // 123,这里是十进制,而不是八进制

$foo = 1 + “bob3”;                    // 1

$foo = 1 + “10 Small Pigs”;      //11


五.type:array数组

定义方法:

array(key=>value,……),[key=>value]key可以是整型或者字符串,value可以是任何类型.

注意事项:

1.key会有如下的强制转换:

(1)包含有合法的整型值的字符串会被转换为整型。例如键名”8″,实际会被存储为8,但是”08″则不会强制转换,因为其不是一个合法的十进制数

var_dump(array(‘4’=>4));  //4 => int 4

var_dump(array(’04’=>4));//’04’ => int 4

var_dump(array(‘4.3’=>4));//’4.3’ => int 4

(2)浮点数也会被转化为整型,意味着小数部分会被舍去,如键名8.7实际会存储为8

var_dump(array(8.7 => 4));//  8 => int 4

(3)布尔值也会被转换为整型。即键名true实际存储为1,而键名false实际存储为0

var_dump(array(true => 1, false => 0));//array (size=2)1 =>
int 1  0 => int 0

(4)Null会被转换为空字符串,即键名null

var_dump([null=>’asd’]);//” => string ‘asd’

2.key是可选项,如果未指定,PHP将自动使用之前用过的最大整型键名加上1作为新的键名

array(“foo”, “bar”, 11 => “hello”, “world”);//0 =>’foo’ 1
=>’bar’ 11 => ‘hello’  12 => ‘world’

3..unset用来删除一个数组中的某个键,但是不会重建索引。如果需要删除后重建索引,需要array_values()函数

unset($a[12]);

print_r($a);//Array ( [0] => foo [1] => bar [11] =>
hello )

$a[] = ‘new’;

print_r($a);//Array ( [0] => foo [1] => bar [11] =>
hello [13] => new )

$b=array_values($a);

print_r($b);//Array ( [0] => foo [1] => bar [2] => hello
[3] => new )


六.type:object对象

对象初始化:要创建一个新的对象object,使用new实例化一个类

class foo

{

function do_foo()

{

echo “Doing foo.”;

}

}

$bar = new foo;

$bar->do_foo();//Doing foo.

注意事项:

将一个对象转换成对象,将不会发生变化,如果其他任何类型的值转换为对象,将会创建一个内置stdClass的类,

如果该值为null,新的实例为空。

数组转换,将使键名转换为属性名并具有相应的值。

对于任何其他的值,名为scalar的成员变量将包含该变量。

var_dump((object)null);//object(stdClass)[2]

var_dump((object)array(‘first’=>2, ‘second’=>4, ‘last’ =>
3));//object(stdClass)[2]

public ‘first’ => int 2

public ‘second’ => int 4

public ‘last’ => int 3

可用来对对象的属性进行赋值

$obj = (object)array(2, 4, ‘new’ => 3);

var_dump($obj->0);//会报错

var_dump((object)’srtToObj’);//object(stdClass)[2]

public ‘scalar’ => string ‘srtToObj’ (length=8)


七.type:null

特殊的NULL值表示一个变量没有值,NULL唯一的可能值就是null,下列情况下变量被认为是null:

被赋值为null;

尚未被赋值;

被unset();

注意事项:

空数组和null在==运算符时返回true,在===运算符和is_null()下返回false

$a=array();

var_dump($a==null);//true

var_dump($a===null);//false

var_dump(is_null($a));//false

发表评论

电子邮件地址不会被公开。 必填项已用*标注