很荣幸参加了百度PHP岗位面试,百度PHP面试会问什么是大家最关心的,鉴于互联网自由与分享精神,不涉及公司机密的百度PHP面试题公布。望能帮助到将去百度PHP面试同学。
Ps:1、部门省略。2、涉及公司情况的省略。时隔一个月,具体的已经记不大清楚了,仅供参考。

一面:技术面
1、介绍自己
2、介绍项目
3、分布式部署方式
4、项目优化经验
5、XHProf
6、大文件,里面都是数字,一行一个,排序
6、以上5点的扩展

二面:技术面
1、介绍项目
2、XHProf
3、介绍项目优化经验
4、写几个PHP自带的函数
5、一个关联数组(KEY-VALUE键值对,KEY是字符串,VALUE是整数),在不使用PHP自带函数的前提下,对数组排序,然后问时间复杂度。最后问写完后问还能不能优化,怎么优化。
6、不断的边聊边扩展。

三面:技术面
1、画一下项目的流程图
2、介绍一下项目
3、项目优化经验
4、为什么离职
5、你想做什么
6、边聊便扩展

等通知...

邮件告知面试已过...

HR电话谈薪资和offer...

XHProf是Facebook开发的性能调试工具,帮助我们的PHP程序性能调优,更加健壮。XHProf安装和使用方法将在本章讲解。XHProf是PHP的PECL扩展。没有XDeBug那些耗费资源,更加的小巧。
流程:程序开头打点,结尾打点。那么XHProf机会记录在两个点之间的所有代码响应时所耗费的时间、内存、CPU等各项指标,我们也可以知道一次请求调用了多少次MySQL,多少次Memcache,更加直观的指明优化道路。
安装:

------------下载并编译PHP-XHProf源码------------
wget http://pecl.php.net/get/xhprof-0.9.4.tgz
tar -zxvf xhprof-0.9.4.tgz
cd xhprof-0.9.4
cd extension
phpize
./configure --enable-xhprof
make
make test
sudo make install

------------修改php.ini---------------
sudo vim /etc/php.ini
#在php.ini最下方加入以下:
extension=xhprof.so
xhprof.output_dir="/var/www/xhprof"

-----------重启Apache--------------
sudo apache restart

进入刚才解压的安装包文件夹中,将xhprof_lib和xhprof_html复制到项目目录下。
接下来,建立一个头文件head.php,这是要打两个点中的开头的点:

//head.php
<?php
if(extension_loaded('xhprof')){
    //载入下载的XHPROF包中的2个文件夹
    include_once 'xhprof_lib/utils/xhprof_lib.php';
    include_once 'xhprof_lib/utils/xhprof_runs.php';
    xhprof_enable(XHPROF_FLAGS_CPU + XHPROF_FLAGS_MEMORY);
}

再建立一个底部文件foot.php,这是要打两个点中的结尾的点:

//foot.php
<?php
if(extension_loaded('xhprof')){
    $ns = 'myXhprof';
    //关闭profiler
    $xhprofData = xhprof_disable();
    //实例化类
    $xhprofRuns = new XHProfRuns_Default();
    $runId = $xhprofRuns->save_run($xhprofData, $ns);
    //前端展示库的URL
    $url = 'http://localhost/xhprof_html/index.php';
    $url .= '?run=%s&source=%s';
    //变量替换
    $url = sprintf($url, $runId, $ns);
    //输入URL
    echo '<a href="'.$url.'" target="_blank">查看结果</a>';
}

使用的最后一步:打点。现在我们建立一个测试文件index.php。测试我大Hello World。

//index.php
<?php
include_once 'head.php';
echo 'Hello World';
include_once 'foot.php';

可以看到,在http://localhost/index.php中,最下面是我们在foot.php中写的“查看结果”,点击进去,可以看到本次请求所使用到的所有函数的列表,每个函数所耗费的时间、CPU、Memory等信息,点击第一栏可以根据所选排序。点击[View Full Callgraph]可以看到由本列表所生成的流程图,从入口到哪个函数,又到哪个函数,这个函数调用了哪个函数,这个函数调用了多少次Memcache等,一幕了然。减少MC的调用,减少这个,减少那个,请求的响应速度能不快吗?

技巧:
我有1000个文件,现在我需要用XHProf检测一下我整个项目,难道要每个文件头部和尾部都要加上include吗?
在php.ini中添加:

auto_prepend_file = /var/www/head.php
auto_append_file = /var/www/foot.php

或者在.htaccess中添加

php_value auto_prepend_file = /var/www/head.php
php_value auto_append_file = /var/www/foot.php

报错:
1、点击[View Full Callgraph]查看图片的时候报错:failed to execute cmd:" dot -Tpng". stderr:`sh: dot:command not found`。
原因:原因:未安装图形化工具
解决:

//红帽系列
yum install graphviz
//Ununtu
apt-get install graphviz
//OS X
brew install graphviz

PHP命名空间是PHP5.3开始支持。本篇讲解PHP命名空间用法和PHP命名空间详解。它的诞生使的我们在一个文件中可以使用多个同名的类而不冲突。
好处:我们的项目有一个记录日志文件的类,叫做Log。然后我们又必须要引入另一个代码包,这个代码包里也有一个叫做Log的类。那么在一个文件中,我们记录日志的又需要给两个类都写一条日志。可以类同名了,怎么办?这个时候,命名空间应运而生。在Java等语言中命名空间是很早就已经提供了支持,而我大PHP一直到5.3才对命名空间提供了支持。
示例一:
文件index.php

<?php
include 'test.php';

class index{
    public function a(){
        echo basename(__FILE__);
        echo '<br>';
        echo __CLASS__ . ' : ' . __METHOD__;
    }
}
$obj = new index();
$obj->a();
echo '<br>';
$obj1 = new test\index();
$obj1->a();
?>

文件test.php

<?php
namespace test;
class index{
    public function a(){
        echo basename(__FILE__);
        echo '<br>';
        echo __CLASS__ . ' : ' . __METHOD__;
    }
}
?>

我们给index.php不设置命名空间,对test.php设置命名空间,名为test。运行index.php。
结果:

index.php
index : index::a
test.php
test\index : test\index::a

我们看到了,同名的类也可以运行而不冲突了。

示例二:
文件index.php

<?php
namespace index;
include 'test.php';

class index{
    public function a(){
        echo basename(__FILE__);
        echo '<br>';
        echo __CLASS__ . ' : ' . __METHOD__;
    }
}
$obj = new index();
$obj->a();
echo '<br>';
$obj1 = new \test\index();
$obj1->a();
?>

文件test.php

<?php
namespace test;
class index{
    public function a(){
        echo basename(__FILE__);
        echo '<br>';
        echo __CLASS__ . ' : ' . __METHOD__;
    }
}
?>

我们给index.php设置命名空间,名为index,对test.php设置命名空间,名为test。运行index.php。
结果:

index.php
index\index : index\index::a
test.php
test\index : test\index::a

比较示例一和二,不对index.php设置命名空间,即该文件是整个PHP全局命名空间下面的一个文件,那么使用test\index()即可,如果对index.php设置命名空间,即在其他的命名空间中使用命名空间,就要多一个“\”,就要使用\test\index()。

示例三:
文件index.php

<?php
namespace index;

include 'namespace.php';

use \test\test1\test2 as test2;

class index{
    public function a(){
        echo basename(__FILE__);
        echo '<br>';
        echo __CLASS__ . ' : ' . __METHOD__;
    }
}

$obj = new index();
$obj->a();

echo '<br>';

$obj1 = new \test\test1\test2\index();
$obj1->a();

echo '<br>';

$obj1 = new test2\index();
$obj1->a();

文件test.php

<?php
namespace test\test1\test2;
class index{
    public function a(){
        echo basename(__FILE__);
        echo '<br>';
        echo __CLASS__ . ' : ' . __METHOD__;
    }
}

结果:

index.php
index\index : index\index::a
test.php
test\test1\test2\index : test\test1\test2\index::a
test.php
test\test1\test2\index : test\test1\test2\index::a

这说明了什么?别名!用过SQL吧。

select COUNT(*) as `count` from `tebleName`

嗯,一个意思。\test\test1\test2这个名字太长了,就别名为test2就好了。使用了use之后呢,这个命名空间就想到于是在index这个命名空间下面了,而不是全局命名空间的一员了,所以使用test2\index(),而不是\test2\index()。

别名时在PHP代码编译的时候执行的,而变量的解析则要更晚。也就是说不能对变量运用use关键字。示例如下(摘自官方手册示例):

<?php
use My\Full\Classname as Another, My\Full\NSname;

$obj = new Another; // 实例化一个 My\Full\Classname 对象
$a = 'Another';
$obj = new $a;      // 实际化一个 Another 对象

PHP redis的使用方法详解。php上使用redis主要有两种方式,一种是Predis,一种是phpredis。phpredis是php的一个扩展,以C语言编写的高性能链表。本文讲解Predis的使用。Predis是PHP语言编写。

PHP redis的使用方法详解。php上使用redis主要有两种方式,一种是Predis,一种是phpredis。phpredis是php的一个扩展,以C语言编写的高性能链表。本文讲解Predis的使用。
Predis是Redis官方推出的由PHP原生语言编写的客户端。由于Predis采用了命名空间的方式,所以Predis要求PHP版本最低为5.3。
Predis开源且托管在GitHub上https://github.com/nrk/predis/。下载整个文件夹复制到项目目录即可。

//引入autoload.php文件
require './predis/autoload.php';

//实例化
$redis = New Predis\Client();
/*这个是简化版,等同于$redis = New Predis\Client(array(
 * 'scheme' => 'tcp',
 * 'host' => '127.0.0.1'
 * 'port' => 6379
 *));
 */

//GET
$redis->get('key');

//LPUSH
$redis->lpush('key', '1', '2', '3');

//MSET 相当于$redis->MSET('article:1:title', 'biaoti', 'article:1:content', 'neirong', 'ctime', 'shijian');
$article = array('article:1:title'=>'biaoti', 'article:1:content'=>'neirong', 'article:1:ctime'=>'shijian');
$redis->MSET('key', $article);

//MGET
$articleKeys = array_keys($article);
$redis->MGET($articleKeys);

//SORT
//SORT articleList BY article:*->time LIMIT 0 10 GET article:*->title GET # DESC ALPHA STORE storeKey
$sort = array(
    'by' => 'article:*->time',
    'limit' => array(0, 10),
    'get' => array('article:*->title', '#'),
    'sort' => 'desc',
    'alpha' => true,
    'store' => 'storeKey'
);

Predis的封装之后,用起来非常方便,关联数组的引入是开发效率非常高的。更多的内容可以参考Predis文档:https://github.com/nrk/predis/blob/v0.8/FAQ.md

Redis管道是大幅提升传输速度和用户体验的一个功能。Redis是使用TCP协议进行传输,当客户端发送一条命令之后,到服务器端接收到这个命令,这个过程是需要发送时间的。当服务器处理完命令返回结果给客户端的时候,这个是需要返回时间的。统称为往返时延。如果多条命令一次性发送过去,Redis服务器端全部处理好后一次性发送回客户端,那么就只需要花费一份的往返时延。这就是Redis的管道命令。Redis底层通信协议对管道命令提供了支持。如:

$ (echo -en "PING\r\nPING\r\nPING\r\n"; sleep 1) | nc localhost 6379
+PONG
+PONG
+PONG

关于管道的具体使用,后期在详细说明。这里只需要知道有这个概念即可。