(图文无关)(其实没图)
如果你正在寻找PHP开发的工作,那么提前掌握这些PHP面试题技巧,你就能体会到这是一门多么神奇的语言。这篇文章能使你在求职过程中事倍功半。
我们先从字符串开始:
<?php
error_reporting(E_ALL);
$a = 'abc';
$a[4] = 'e';
var_dump($a);
var_dump(ord($a[3]));
请问这段代码的输出是什么呢?是「abce」、「abc」、「abcx00e」还是报一个E_NOTICE?
答:它的输出是「abc e」,不会报错。少的那个字符被空格(ASCII = 32)补齐了。
那么:
$a[-1] = '0';
var_dump($a);
$a[-100] = 'a';
var_dump($a);
$a[1] = 'abcde';
var_dump($a);
又是什么呢?
字符串过去了,我们再来看看函数调用吧。
我们都知道,PHP的传参有按值传递、通过引用传递两种方式。那么:
<?php
function foo($a)
{
$a=5;
echo func_get_arg(0);
}
foo(2);
echo "n";
是多少呢?
只回答2或者5的都不合格:Online PHP editor | output for Nu8Ns
![bbc354d52eda4b623344060d31fff928.png](https://i-blog.csdnimg.cn/blog_migrate/cc0d70b815683a4b1af4be20e9739b2d.png)
出处:php/php-src
玩玩魔术方法吧:
<?php
class foo {
public $pp = array('t'=>null);
function bar() {
echo $this->t ='faaa';
}
function __get($prop)
{
return $this->pp[$prop];
}
function __set($prop, $val)
{
echo "__set";
$this->pp[$prop] = '';
}
}
$f = new foo;
$f->bar();
请问它的输出是「__set」吗?如果你回答是的话,那你的面试已经不合格了。它的输出是「__setfaaa」。
当然,这个其实很好理解,直接使用=之后的值可以避免多调用一次__get,算是个“性能优化”手段。
代码出处:php/php-src
再看一段代码:
<?php
class A {
function __call($strMethod, $arrArgs) {
echo __CLASS__;
}
}
class B extends A {
function __call($strMethod, $arrArgs) {
echo __CLASS__;
}
function test() {
A::test1(1,'a');
B::test2(1,'a');
self::test3(1,'a');
parent::test4(1,'a');
}
}
$b = new B();
$b->test();
请问它的输出是「ABBA」吗?其实它的答案是「BBBB」。
这不是Bug,而是feature:When __call() is invoked via ::, ensure current scope's __call() is favoured over the specified class's __call().
代码出处:php/php-src ; 测试:Online PHP editor | output for AclDv
再深入一点,我们一起来学习反射吧。
<?php
class A {
protected static $static_var='foo';
public function getStatic(){
$class = new ReflectionClass($this);
return $class->getStaticPropertyValue('static_var');
}
public function getStatic2(){
$class = new ReflectionClass($this);
$staticProps = $class->getStaticProperties();
return $staticProps['static_var'];
}
}
class B extends A {
protected static $static_var='foo2';
}
请问调用getStatic
和getStatic2
分别会输出什么?
答案:
getStatic2 = foo2
getStatic = Fatal error: Uncaught ReflectionException: Class B does not have a property named static_var in /in/ENaZW:7
为什么呢?
getStaticPropertyValue
会调用zend_std_get_static_property
,其会检查当前调用的参数在当前作用域是否可见: https://github.com/php/php-src/blob/ded87a9ea0f12107031e6cac6c0299c1f87ff233/Zend/zend_object_handlers.c#L1466
而getStaticProperties
则可以直接输出所有参数,不管它是否可见。
代码出处:ReflectionClass::getStaticPropertyValue - Manual
今天我们的面试题就到这里,现在,你学会PHP了吗?
最后,如果你想体验一下谭浩强的乐趣,不如我们一起:
<?php
function f() { return 0; }
$a[0][1] = 'good';
$a[1][1] = 'bad';
echo "n" . '$i=f(): ';
echo $a[$i=f()][++$i];
unset($i);
echo "n" . '$$x=f(): ';
$x='i';
echo $a[$$x=f()][++$$x];
unset($i, $x);
echo "n" . '${'i'}=f(): ';
echo $a[${'i'}=f()][++${'i'}];
unset(${'i'});
echo "n" . '$i[0]=f(): ';
echo $a[$i[0]=f()][++$i[0]];
unset($i);
echo "n" . '$i[0][0]=f(): ';
echo $a[$i[0][0]=f()][++$i[0][0]];
unset($i);
echo "n" . '$i->p=f(): ';
$i = new stdClass;
echo $a[$i->p=f()][++$i->p];
unset($i);
echo "n" . '$i->p->q=f(): ';
$i = new stdClass;
$i->p = new stdClass;
echo $a[$i->p->q=f()][++$i->p->q];
unset($i);
echo "n" . '$i->p[0]=f(): ';
$i = new stdClass;
echo $a[$i->p[0]=f()][++$i->p[0]];
unset($i);
echo "n" . '$i->p[0]->p=f(): ';
$i = new stdClass;
$i->p[0] = new stdClass;
echo $a[$i->p[0]->p=f()][++$i->p[0]->p];
unset($i);
Class C {
static $p;
}
echo "n" . 'C::$p=f(): ';
echo $a[C::$p=f()][++C::$p];
echo "n" . 'C::$p[0]=f(): ';
C::$p = array();
echo $a[C::$p[0]=f()][++C::$p[0]];
echo "n" . 'C::$p->q=f(): ';
C::$p = new stdclass;
echo $a[C::$p->q=f()][++C::$p->q];
php/php-src