PHP爱考的那些笔试题
来自《PHP程序员面试笔试宝典》,涵盖了近三年了各大型企业常考的PHP面试题,针对面试题提取出来各种面试知识也涵盖在了本书。
一、单例模式是在应用程序中最多只能拥有一个该类的实例存在,一旦创建就会一直在内存中。
由于单例模式的设定,所以常应用于数据库类设计,它可以保证只连接一次数据库。
单例类的特点如下:
1)单例类不能直接实例化创建,只能由类本身实例化。因此,构造函数必须标记为private,从而防止类被实例化。
2)需要保证一个能访问到的实例公开的静态方法和一个私有静态成员变量来保存类实例。
3)类中通常需要有一个空的私有__clone()方法防止别人对单例类进行实例克隆。
示例代码如下:
<?php
class Database
{
private static $instance;
private function __construct()
{
// to do
}
private function __clone()
{
// to do
}
public static function getInstance()
{
if (!(self::$instance instanceof self)) {
self::$instance = new self();
}
return self::$instance;
}
}
$a =Database::getInstance();
$b =Database::getInstance();
print_r($a === $b);
?>
二、【真题180】 写一个函数,尽可能高效地从一个标准 url 里取出文件的扩展名。例如,http://www.sina.com.cn/abc/de/fg.php?id=1 需要取出 php 或 .php。
参考答案:方法一:
function getExt($url){
$arr = parse_url($url);
$file = basename($arr['path']);
$ext = explode(".",$file);
return $ext[1];
}
方法二:
function getExt($url) {
$url = basename($url);
$pos1 = strpos($url,".");
$pos2 = strpos($url,"?");
if(strstr($url,"?")){
return substr($url,$pos1 + 1,$pos2 - $pos1 - 1);
}else{
return substr($url,$pos1);
}
}
三、1.PHP相关的日期函数
1)checkdate($month,$date,$year)函数的功能是在日期用于计算或被保存在数据库中之前,判断日期是否是一个合法的日期。如下例所示:
<?php
echo checkdate(2,30,2005) ? "valid" : "invalid"; //输出invalid
echo checkdate(4,6,2010) ? "valid" : "invalid"; //输出valid
?>
如果日期有效,则输出valid,如果日期无效,则输出invalid。
2)mktime($hour, $minute, $second, $month, $day, $year)函数的功能是获得即时时间的UNIX时间戳。示例代码如下:
<?php
// returns timestamp for 2017-11-25 13:15:23
echo mktime(13,15,23,11,25,2017); //输出1511586923
?>
mktime可以根据实际返回unix时间戳。
3)date($format, $ts)函数的功能是显示格式化时间或日期。示例代码如下:
<?php
echo date("d-M-Y h:i A", mktime()); //输出13-Sep-2005 01:16 PM
?>
4)strtotime($str)函数的功能是将非标准化的日期/时间字符串转换成标准、兼容的UNIX时间戳。示例代码如下:
<?php
echo date("d-M-y", strtotime("today")); //输出25-Nov-17
echo date("d-M-y", strtotime("tomorrow")); //输出26-Nov-17
echo date("d-M-y", strtotime("today +3 days")); //输出28-Nov-17
?>
strtotime("today")获取的是今天的时间戳,strtotime("tomorrow")获取的是明天时间的时间戳,strtotime("today +3 days")获取到的是三天后的时间戳。
四、【真题173】 在如下代码中,date()将会输出( )。
<?php
$date="2009-5-19";
$time="14:31:38";
$datetime=$date.$time;
echo date("Y-m-d:H:i:s",strtotime($datetime));
?>
A.2009-05-19:14:31:38 B.19-5-2009:2:31:38
C.2009-5-19:2:31:38 D.19/5/2009:14:31:38
参考答案:A。
分析:日期中输出的H:i:s中的H表示24小时制的小时,i表示分,s表示秒。所以根据拼接的时间通过strtotime()函数转换成时间戳后再转成日期就可以得到2009-05-19:14:31:38。所以,选项A正确。
五、++与—的含义是什么?
递增与递减有两种使用方法。
1)++$a或--$a:表示先将变量增加或减少1,后做赋值操作,称为前置递增或递减运算符。
2)$a++或$a--:表示先做赋值操作,后将变量增加或减少1,称为后置递增或递减运算符。
【真题74】 若$y、$ x为int型变量,则执行以下语句后,$y的值为( )。
$x=1;
++$x;
$y = $x++;
A.1 B.2 C.3 D.0
参考答案:B。
分析:前置运算++$x,首先对$x 执行加一运算,然后返回$x,对于后置运算$x++,首先返回$x,然后对$x执行加一运算。
六、PHP中遍历数组有三种常用的方法:
(1)使用for语句循环遍历数组
使用for语句循环遍历数组要求遍历的数组必须是索引数组。PHP中不仅有联合数组而且还有索引数组,所以PHP中很少用for语句循环遍历数组。
for语句遍历数组的方式如下:
<?php
$arr = array(1,2,3);
for($i=0; $i<count($arr); $i++){
echo $arr[$i]." ";
}
?>
程序的运行结果为
1 2 3
(2)使用foreach语句遍历数组
foreach 仅能用于数组,当试图将其用于其他数据类型或者一个未初始化的变量时会产生错误。foreach的使用格式如下:
1)foreach (array_expression as $value){}。
2)foreach (array_expression as $key => $value){}。
需要注意的是,第1种方法遍历给定的 array_expression 数组。每次循环中,当前单元的值被赋给 $value并且数组内部的指针向前移一步(因此下一次循环中将会得到下一个单元)。第2种格式做同样的事,此外,当前单元的键名也会在每次循环中被赋给变量 $key。
示例代码如下:
<?php
$speed = array(50,120,180,240,380);
foreach($speed as $keys=>$values){
echo $keys."=>".$values." ";
}
?>
程序的运行结果为
0=>50
1=>120
2=>180
3=>240
4=>380
(3)联合使用list()、each()和while循环遍历数组
list()、each()、while循环遍历方法:
<?php
$arr = array(
array("aa0","bb0","cc0"),
array("aa1","bb1","cc1"),
array("aa2","bb2","cc2"),
array("aa3","bb3","cc3")
);
while (list($key,$value) = each($arr)){
list($param1,$param2,$param3) = $value;
echo "$param1 $param2 $param3"." ";
}
?>
程序的运行结果为
aa0 bb0 cc0
aa1 bb1 cc1
aa2 bb2 cc2
aa3 bb3 cc3
需要注意的是,list()函数不是一个真正的函数,它是PHP的一个语言结构,仅能用于数字索引的数组,且数字索引从0开始。
Mysql部分
一、如何进行数据库优化?
数据库优化的过程可以使用以下的方法进行:
1)选取最适用的字段属性,尽可能减少定义字段长度,尽量把字段设置NOT NULL,例如'省份、性别',最好设置为ENUM。
2)使用连接(JOIN)来代替子查询。
① 删除没有任何订单客户:DELETE FROM customerinfo WHERE customerid NOT in(SELECT customerid FROM orderinfo)。
② 提取所有没有订单客户:SELECT FROM customerinfo WHERE customerid NOT in(SELECT customerid FROM orderinfo)。
③ 提高b的速度优化:SELECT FROM customerinfo LEFT JOIN orderid customerinfo. customerid=orderinfo.customerid WHERE orderinfo.customerid IS NULL。
3)使用联合(UNION)来代替手动创建的临时表。创建临时表:SELECT name FROM 'nametest' UNION SELECT username FROM 'nametest2'。
4)事务处理。保证数据完整性,例如添加和修改。同时,如果两者成立,则都执行,一者失败都失败:
mysql_query("BEGIN");
mysql_query("INSERT INTO customerinfo (name) VALUES ('$name1')";
mysql_query("SELECT * FROM 'orderinfo' where customerid=".$id");
mysql_query("COMMIT");
5)锁定表,优化事务处理。用一个SELECT语句取出初始数据,通过一些计算,用UPDATE语句将新值更新到表中。包含有WRITE关键字的LOCK TABLE语句可以保证在UNLOCK TABLES命令被执行之前,不会有其他的访问来对customerinfo表进行插入、更新或者删除的操作。
mysql_query("LOCK TABLE customerinfo READ, orderinfo WRITE");
mysql_query("SELECT customerid FROM 'customerinfo' where id=".$id);
mysql_query("UPDATE 'orderinfo' SET ordertitle='$title' where customerid=".$id);
mysql_query("UNLOCK TABLES");
6)使用外键,优化锁定表。把customerinfo里的customerid映射到orderinfo里的customerid,任何一条没有合法的customerid的记录不会写到orderinfo里。
CREATE TABLE customerinfo
(
customerid INT NOT NULL,
PRIMARY KEY(customerid)
)TYPE = INNODB;
CREATE TABLE orderinfo
(
orderid INT NOT NULL,
customerid INT NOT NULL,
PRIMARY KEY(customerid,orderid),
FOREIGN KEY (customerid) REFERENCES customerinfo
(customerid) ON DELETE CASCADE
)TYPE = INNODB;
注意:'ON DELETE CASCADE',该参数保证当customerinfo表中的一条记录删除的话同时也会删除order。
表中的该用户的所有记录,注意使用外键时要定义数据库引擎为INNODB。
二、选择正确的存储引擎?
在MySQL中有两个存储引擎:MyISAM和InnoDB,每个引擎都有利有弊。
MyISAM适合于一些需要大量查询的应用,但其对于有大量写操作的支持并不是很好。甚至只是需要update一个字段,整个表都会被锁起来,而其他进程,就算是读进程都无法操作直到读操作完成。另外,MyISAM 对于 SELECT COUNT(*) 这类的计算是超快无比的。
InnoDB 的趋势会是一个非常复杂的存储引擎,对于一些小的应用,它会比 MyISAM 还慢。但是它支持“行锁”,于是在写操作比较多的时候,会更优秀。并且,它还支持更多的高级应用,例如事务。
三、【真题231】 用什么方法检查PHP脚本的执行效率(通常是脚本执行时间)和数据库SQL的效率(通常是数据库query时间),并定位和分析脚本执行和数据库查询的瓶颈所在?
参考答案:检查PHP脚本的执行效率的方法如下:可以在检查的代码开头记录一个时间,然后在代码的结尾也记录一个时间,结尾时间减去开头时间取这个时间的差值,从而检查PHP的脚本执行效率,记录时间可以使用microtime()函数。
检查数据库SQL的效率的方法如下:可以通过explain显示MySQL如何使用索引来处理select语句及连接表,帮助选择更好的索引和写出更优化的查询语句。然后启用slow query log记录慢查询,通过查看SQL的执行时间和效率来定位分析脚本执行的问题和瓶颈所在。
四、 以下代码的运行结果为( )。
<?php
mysql_connect('localhost','root',"");
$result = mysql_query("SELECT id,name FROM tb1");
while($row = mysql_fetch_array($result,MySQL_ASSOC)){
echo' ID:' .$row[0].' Name:' .$row[];
}
?>
A.报错 B.循环换行打印全部记录
C.无任何结果 D.只打印第一条记录
参考答案:A。
分析:因为代码中没有指明要操作的数据库名,所以会报错。
所以,本题的答案为A。
问题:设教务管理系统中有三个基本表:
学生信息表S(SNO, SNAME, AGE, SEX),其属性分别表示学号、学生姓名、年龄和性别。
选课信息表SC(SNO, CNO, SCGRADE),其属性分别表示学号、课程号和成绩。
课程信息表C(CNO, CNAME, CTEACHER),其属性分别表示课程号、课程名称和任课老师姓名。
1)把SC表中每门课程的平均成绩插入另外一个已经存在的表SC_C(CNO, CNAME, AVG_GRADE)中,其中AVG_GRADE表示的是每门课程的平均成绩。
INSERT INTO SC_C(CNO, CNAME, AVG_GRADE)
SELECT SC.CNO, C.CNAME, AVG(SCGRADE) FROM SC, C WHERE SC.CNO = C.CNO GROUP BY SC.CNO
2)规定女同学选修何昊老师的课程成绩都应该在80分以上(包含80分)。
ALERT TABLE SC, S, C
ADD CONSTRAINT GRADE CHECK(SCGRADE>=80)
WHERE SC.CNO=C.CNO AND SC.SNO=S.SNO AND C.CTEACHER='何昊' AND S.SEX=
"女"
3)从SC表中把何昊老师的女学生选课记录删除。
DELETE FROM SC WHERE CNO=(SELECT CNO FROM C WHERE C.CTEACHER ='何昊') AND SNO IN (SELECT SNO FROM S WHERE SEX='女')
4)找出没有选修过“何昊”老师讲授课程的所有学生姓名。
SELECT SNAME FROM S
WHERE NOT EXISTS(
SELECT * FROM SC,C WHERE SC.CNO=C.CNO AND CNAME='何昊' AND SC.SNO=S.SNO)
5)列出有两门以上(含两门)不及格课程(成绩小于60)的学生姓名及其平均成绩。
SELECT S.SNO,S.SNAME,AVG_SCGRADE=AVG(SC.SCGRADE)
FROM S,SC,(
SELECT SNO FROM SC WHERE SCGRADE<60 GROUP BY SNO
HAVING COUNT(DISTINCT CNO)>=2)A WHERE S.SNO=A.SNO AND SC.SNO = A.SNO
GROUP BY S.SNO,S.SNAME
6)列出既学过“1”号课程,又学过“2”号课程的所有学生姓名。
SELECT S.SNO,S.SNAME
FROM S,(SELECT SC.SNO FROM SC,C
WHERE SC.CNO=C.CNO AND C.CNAME IN('1','2')
GROUP BY SNO
HAVING COUNT(DISTINCT CNO)=2
)SC WHERE S.SNO=SC.SNO
7)列出“1”号课成绩比“2”号同学该门课成绩高的所有学生的学号。
SELECT S.SNO,S.SNAME
FROM S,(
SELECT SC1.SNO
FROM SC SC1,C C1,SC SC2,C C2
WHERE SC1.CNO=C1.CNO AND C1.NAME='1'
AND SC2.CNO=C2.CNO AND C2.NAME='2'
AND SC1.SCGRADE>SC2.SCGRADE
)SC WHERE S.SNO=SC.SNO
8)列出“1”号课成绩比“2”号课成绩高的所有学生的学号及其“1”号课和“2”号课的成绩。
SELECT S.SNO,S.SNAME,SC.[1号课成绩],SC.[2号课成绩]
FROM S,(
SELECT SC1.SNO,[1号课成绩]=SC1.SCGRADE,[2号课成绩]=SC2.SCGRADE
FROM SC SC1,C C1,SC SC2,C C2
WHERE SC1.CNO=C1.CNO AND C1.NAME='1'
AND SC2.CNO=C2.CNO AND C2.NAME='2'
AND SC1.SCGRADE>SC2.SCGRADE
)SC WHERE S.SNO=SC.SNO
购买链接:京东购买
题目来自《PHP程序员面试笔试宝典》,里面涵盖了近三年了各大型企业常考的PHP面试题,针对面试题提取出来各种面试知识也涵盖在了本书。
更多PHP面试笔试真题可以浏览:www.shuaiqi100.com
更多有趣有料的PHP面试笔试资料可以关注:“琉忆编程库”
或者浏览:www.shuaiqi100.com 获取。
PHP程序员面试笔试宝典下载:https://pan.baidu.com/s/1-ES2ZI3z5Lhv-zTKFmJDSQ