PHP面试大全高级篇.docx
- 文档编号:5493770
- 上传时间:2022-12-17
- 格式:DOCX
- 页数:37
- 大小:228.71KB
PHP面试大全高级篇.docx
《PHP面试大全高级篇.docx》由会员分享,可在线阅读,更多相关《PHP面试大全高级篇.docx(37页珍藏版)》请在冰豆网上搜索。
PHP面试大全高级篇
PHP面试大全ZX1.1版
版本说明:
基于部分网络+个人+部分群网友帮助集合而成。
如果有错误的地方,请联系
QQ群群主:
247823727修改完成版会重新发布
个人博客:
SVN地址:
php高级部分
1.编写SQL查找出以下表中TG的所有员工
--仅提供向下查询
DELIMITER$$
DROPFUNCTIONIFEXISTSserch_user;
CREATEFUNCTIONserch_user(dept_idINT)
RETURNSTEXT
BEGIN
DECLAREchild_idTEXT;
DECLAREtempTEXT;
SETtemp='';
SETchild_id=dept_id;
WHILEchild_idISNOTNULLDO
SETtemp=CONCAT(temp,',',child_id);
SELECTGROUP_CONCAT(id)INTOchild_idFROMdeptsWHEREFIND_IN_SET(parent_id,child_id)>0;
ENDWHILE;
RETURNtemp;
END;$$
DELIMITER;
#查询所有部门ID
SELECTserch_user
(1);
#查询所有的用户
SELECT*FROM`user`WHEREFIND_IN_SET(dept_id,serch_user
(1));
第二种解法,自我链接:
2.迷宫算法实现
有出口点和入口点,中间有一堆障碍物,求出其中一个入口点到到出口点的最优的路径,DEMO用HTML+JS/PHP实现(要求可以任意设置出口和入口点和障碍物的位置,还有可以设置地图大小,需要做UI)。
3.MySQL查询优化,MySQL索引优化
存储引擎的选择
ØMyisam:
数据库并发不大,读多写少,而且都能很好的用到索引,sql语句比较简单的应用,TB数据仓库
ØInnodb:
并发访问大,写操作比较多,有外键、事务等需求的应用,系统内存较大。
1.对查询进行优化,应尽量避免全表扫描,首先应考虑在where及orderby涉及的列上建立索引。
2.应尽量避免在where子句中使用!
=或<>操作符,否则将引擎放弃使用索引而进行全表扫描。
3.应尽量避免在where子句中对字段进行null值判断,否则将导致引擎放弃使用索引而进行全表扫描,如:
selectidfromtwherenumisnull
可以在num上设置默认值0,确保表中num列没有null值,然后这样查询:
selectidfromtwherenum=0
4.应尽量避免在where子句中使用or来连接条件,否则将导致引擎放弃使用索引而进行全表扫描,如:
selectidfromtwherenum=10ornum=20
可以这样查询:
selectidfromtwherenum=10
unionall
selectidfromtwherenum=20
5.下面的查询也将导致全表扫描:
selectidfromtwherenamelike'%abc%'
若要提高效率,可以考虑全文检索。
6.in和notin也要慎用,否则会导致全表扫描,如:
selectidfromtwherenumin(1,2,3)
对于连续的数值,能用between就不要用in了:
selectidfromtwherenumbetween1and3
7.如果在where子句中使用参数,也会导致全表扫描。
因为SQL只有在运行时才会解析局部变量,但优化程序不能将访问计划的选择推迟到运行时;它必须在编译时进行选择。
然而,如果在编译时建立访问计划,变量的值还是未知的,因而无法作为索引选择的输入项。
如下面语句将进行全表扫描:
selectidfromtwherenum=@num
可以改为强制查询使用索引:
selectidfromtwith(index(索引名))wherenum=@num
8.应尽量避免在where子句中对字段进行表达式操作,这将导致引擎放弃使用索引而进行全表扫描。
如:
selectidfromtwherenum/2=100
应改为:
selectidfromtwherenum=100*2
9.应尽量避免在where子句中对字段进行函数操作,这将导致引擎放弃使用索引而进行全表扫描。
如:
selectidfromtwheresubstring(name,1,3)='abc'--name以abc开头的id
selectidfromtwheredatediff(day,createdate,'2005-11-30')=0--'2005-11-30'生成的id
应改为:
selectidfromtwherenamelike'abc%'
selectidfromtwherecreatedate>='2005-11-30'andcreatedate<'2005-12-1'
10.不要在where子句中的“=”左边进行函数、算术运算或其他表达式运算,否则系统将可能无法正确使用索引。
11.在使用索引字段作为条件时,如果该索引是复合索引,那么必须使用到该索引中的第一个字段作为条件时才能保证系统使用该索引,否则该索引将不会被使用,并且应尽可能的让字段顺序与索引顺序相一致。
12.不要写一些没有意义的查询,如需要生成一个空表结构:
selectcol1,col2into#tfromtwhere1=0
这类代码不会返回任何结果集,但是会消耗系统资源的,应改成这样:
createtable#t(...)
13.很多时候用exists代替in是一个好的选择:
selectnumfromawherenumin(selectnumfromb)
用下面的语句替换:
selectnumfromawhereexists(select1frombwherenum=a.num)
14.并不是所有索引对查询都有效,SQL是根据表中数据来进行查询优化的,当索引列有大量数据重复时,SQL查询可能不会去利用索引,如一表中有字段sex,male、female几乎各一半,那么即使在sex上建了索引也对查询效率起不了作用。
15.索引并不是越多越好,索引固然可以提高相应的select的效率,但同时也降低了insert及update的效率,因为insert或update时有可能会重建索引,所以怎样建索引需要慎重考虑,视具体情况而定。
一个表的索引数最好不要超过6个,若太多则应考虑一些不常使用到的列上建的索引是否有必要。
16.应尽可能的避免更新clustered索引数据列,因为clustered索引数据列的顺序就是表记录的物理存储顺序,一旦该列值改变将导致整个表记录的顺序的调整,会耗费相当大的资源。
若应用系统需要频繁更新clustered索引数据列,那么需要考虑是否应将该索引建为clustered索引。
17.尽量使用数字型字段,若只含数值信息的字段尽量不要设计为字符型,这会降低查询和连接的性能,并会增加存储开销。
这是因为引擎在处理查询和连接时会逐个比较字符串中每一个字符,而对于数字型而言只需要比较一次就够了。
18.尽可能的使用varchar/nvarchar代替char/nchar,因为首先变长字段存储空间小,可以节省存储空间,其次对于查询来说,在一个相对较小的字段内搜索效率显然要高些。
19.任何地方都不要使用select*fromt,用具体的字段列表代替“*”,不要返回用不到的任何字段。
20.尽量使用表变量来代替临时表。
如果表变量包含大量数据,请注意索引非常有限(只有主键索引)。
21.避免频繁创建和删除临时表,以减少系统表资源的消耗。
22.临时表并不是不可使用,适当地使用它们可以使某些例程更有效,例如,当需要重复引用大型表或常用表中的某个数据集时。
但是,对于一次性事件,最好使用导出表。
23.在新建临时表时,如果一次性插入数据量很大,那么可以使用selectinto代替createtable,避免造成大量log,以提高速度;如果数据量不大,为了缓和系统表的资源,应先createtable,然后insert。
24.如果使用到了临时表,在存储过程的最后务必将所有的临时表显式删除,先truncatetable,然后droptable,这样可以避免系统表的较长时间锁定。
25.尽量避免使用游标,因为游标的效率较差,如果游标操作的数据超过1万行,那么就应该考虑改写。
26.使用基于游标的方法或临时表方法之前,应先寻找基于集的解决方案来解决问题,基于集的方法通常更有效。
27.与临时表一样,游标并不是不可使用。
对小型数据集使用FAST_FORWARD游标通常要优于其他逐行处理方法,尤其是在必须引用几个表才能获得所需的数据时。
在结果集中包括“合计”的例程通常要比使用游标执行的速度快。
如果开发时间允许,基于游标的方法和基于集的方法都可以尝试一下,看哪一种方法的效果更好。
28.在所有的存储过程和触发器的开始处设置SETNOCOUNTON,在结束时设置SETNOCOUNTOFF。
无需在执行存储过程和触发器的每个语句后向客户端发送DONE_IN_PROC消息。
29.尽量避免向客户端返回大数据量,若数据量过大,应该考虑相应需求是否合理。
30.尽量避免大事务操作,提高系统并发能力。
4.MySQL索引
索引的类型
Ø普通索引:
这是最基本的索引类型,没唯一性之类的限制。
Ø唯一性索引:
和普通索引基本相同,但所有的索引列值保持唯一性。
Ø主键:
主键是一种唯一索引,但必须指定为”PRIMARYKEY”。
Ø全文索引:
MYSQL从3.23.23开始支持全文索引和全文检索。
在MYSQL中,全文索引的索引类型为FULLTEXT。
全文索引可以在VARCHAR或者TEXT类型的列上创建。
大多数MySQL索引(PRIMARYKEY、UNIQUE、INDEX和FULLTEXT)使用B树中存储。
空间列类型的索引使用R-树,MEMORY表支持hash索引。
单列索引和多列索引(复合索引)
索引可以是单列索引,也可以是多列索引。
对相关的列使用索引是提高SELECT操作性能的最佳途径之一。
多列索引:
MySQL可以为多个列创建索引。
一个索引可以包括15个列。
对于某些列类型,可以索引列的左前缀,列的顺序非常重要。
多列索引可以视为包含通过连接索引列的值而创建的值的排序的数组。
一般来说,即使是限制最严格的单列索引,它的限制能力也远远低于多列索引。
最左前缀
多列索引有一个特点,即最左前缀(LeftmostPrefixing)。
假如有一个多列索引为key(firstnamelastnameage),当搜索条件是以下各种列的组合和顺序时,MySQL将使用该多列索引:
firstname,lastname,age
firstname,lastname
firstname
也就是说,相当于还建立了key(firstnamelastname)和key(firstname)。
这里说的主键设计主要是针对INNODB引擎
1.能唯一的表示行。
2.显式的定义一个数值类型自增字段的主键,这个字段可以仅用于做主键,不做其他用途。
3.MySQL主键应该是单列的,以便提高连接和筛选操作的效率。
4.主键字段类型尽可能小,能用SMALLINT就不用INT,能用INT就不用BIGINT。
5.尽量保证不对主键字段进行更新修改,防止主键字段发生变化,引发数据存储碎片,降低IO性能。
6.MySQL主键不应包含动态变化的数据,如时间戳、创建时间列、修改时间列等。
7.MySQL主键应当有计算机自动生成。
8.主键字段放在数据表的第一顺序。
推荐采用数值类型做主键并采用auto_increment属性让其自动增长。
索引的缺点:
极大地加速了查询,减少扫描和锁定的数据行数。
索引的缺点:
占用磁盘空间,减慢了数据更新速度,增加了磁盘IO。
添加索引有如下原则:
1.选择唯一性索引。
2.为经常需要排序、分组和联合操作的字段建立索引。
3.为常作为查询条件的字段建立索引。
4.限制索引的数据,索引不是越多越好。
5.尽量使用数据量少的索引,对于大字段可以考虑前缀索引。
6.删除不再使用或者很少使用的索引。
7.结合核心SQL优先考虑覆盖索引。
8.忌用字符串做主键。
一些细节
1.当结果集只有一行数据时使用LIMIT1
2.避免SELECT*,始终指定你需要的列
从表中读取越多的数据,查询会变得更慢。
他增加了磁盘需要操作的时间,还是在数据库服务器与WEB服务器是独立分开的情况下。
你将会经历非常漫长的网络延迟,仅仅是因为数据不必要的在服务器之间传输。
3.使用连接(JOIN)来代替子查询(Sub-Queries)
连接(JOIN)..之所以更有效率一些,是因为MySQL不需要在内存中创建临时表来完成这个逻辑上的需要两个步骤的查询工作。
4.使用ENUM、CHAR而不是VARCHAR,使用合理的字段属性长度
5.尽可能的使用NOTNULL
6.固定长度的表会更快
7.拆分大的DELETE或INSERT语句
8.查询的列越小越快
索引过度增加也会出现很多情况索引无效的。
5.
6.php面向对象的三大特征
对象的主要三个特性
对象的行为:
可以对对象施加那些操作,开灯,关灯就是行为。
对象的形态:
当施加那些方法是对象如何响应,颜色,尺寸,外型。
对象的表示:
对象的表示就相当于身份证,具体区分在相同的行为与状态下有什么不同。
面向对象模型
面向对象的概念:
oop(面向对象的编程)它能是其代码更加简洁易于维护并且具有更强的可重性
什么是类:
类是具有相同属性和服务的一组对象的集合比如说人,书,轮船,车都属于类,他为属于该类的对象做了一个统一的抽象描述,在编程的语言中类是一个单独的程序,它应该有一个类名包括属性的说明和服务两个部分。
什么是对象:
对象是系统中描述客观事件的一个实体,他是构成系统的一个基本单位。
*数据与代码都被捆绑在一个实体当中*,一个对象由一组属性和对这组属性进行操作的一组行为组成。
从抽象的角度来说,对象是问题域或实现域中某些事物的一个抽象。
他反映该事物在系统中保存的信息和发挥的作用:
它是一组属性和有权对这些属性进行操作的一个封装体。
客观世界是由对象和对象之间的联系组成的。
类和对象的关系:
类与对象的关系就如模具和铸件的关系,类的实力化的结果就是对象,而对对象的抽象就是类,类描述了一组有相同特性(属性)和相同行为的对象。
类与属性和方法
PHP中定义类语法格式:
classclassname[可选属性]{
public$property[=value];…//用public声明一个公共标识然后给予一个变量变量也可以赋值
functionfunctionname(args){//类的方法里的成员函数
代码}…
//类的方法(成员函数)
}
生成对象(类的实例化):
$对象名=newclassname();
使用对象的属性
在一个类中,可以访问一个特殊指针$this当在该类中通过一个操作设置或访问该变量时,使用$this->name来引用.
对象的生成
定义好类后用一个new来声明,由于对象资料的封装特性,对象是无法由主程序区块直接访问的须通过对象来调用类中所定义的属性和行为函数,间接地达成存取控制类中资料的目的。
对象和类的关系
对象和类的关系:
对象是实际存在的,占有动态资源。
类是对象的蓝图,可能占有静态资源。
对象属性占有动态资源
类(静态)属性实际上是有类名字空间上的“全局变量”
性能考虑:
每个对象要单独占用数据空间
增加的调用层次可能消耗执行时间
方法的参数形式和传递方式
方法的参数可以是基本数据类型、数组和类对象。
基本数据类型:
值参传递
数组:
值参传递
类对象:
引用传递
构造函数
构造函数是在类中起到初始化的作用
构造函数的生成方法与其他函数一样只是其名称必须是__construct().
语法格式:
function__construct(参数){
。
。
。
。
。
。
。
。
}
范例:
classPerson{
public$name;
public$sex;
public$age;
function__construct($name,$sex,$age){
echo"我是构造函数
";
$this->name=$name;
$this->sex=$sex;
$this->age=$age;
}
输出结果:
初始化
析构函数
当对象脱离其作用域时(例如对象所在的函数已调用完毕),系统自动执行析构函数。
应在退出前在析构函数中用释放内存。
析构函数__destruct析构函数没有任何参数
范例:
classperson{
function__destruct()
{echo"byebye!
“;}
}
$a=newperson();
访问类型
public公共的(公共修饰符)类内部与类外部都可以访问的
private私有的(私有修饰符)只能在类内部访问
protected受保护的(保护成员修饰符)子类可以访问类外部不可以访问
oop的三个重要特性
封装,继承,多态
封装性:
封装性就是把对象的属性和行为结合成一个独立的单位。
封装一个类需要两步第一步是私有化一个类第二步是用set和get做出读取赋值的操作
他的好处是:
隐藏类的实现细节,可以方便加入逻辑控制性,限制对属性的不合理操作,便于修改增强代码的可维护性。
__get与__set
一般说把类私有话更符合现实的逻辑。
预定义两种函数来进行获取与敷值操作。
__get获取值通常是域的值
__set设置值通常是域的值
__call调用一个对象中不存在的方法时,就会产生错误call()这个方法来处理这种情况。
静态属性和方法
static关键字来声明静态方法
static静态变量在类的内部生成一个静态变量就是能够被所有类的实力化共想也就是说静态成员则放到了“初始化静态段”,在类第一次被加载的时候放入的,可以让堆内存里面的每个对象所共享
使用方法:
self:
:
$静态属性、self:
:
静态方法
staticfunctionp(){
echoself:
:
$country;
echoself:
:
PI;//访问常量
//echo$this->name;在静态方法中只能操作静态属性
//self:
:
p();
}
外部调用:
类:
:
$静态属性、类:
:
静态方法
const关键字:
用来生成常量常量是唯一的不能改变的惯例常量为大写
constCONSTANT='constantvalue';生成一个常量
echoself:
:
CONSTANT;//类内部访问
echoClassName:
:
CONSTANT;//类外部访问
继承性
B类的对象拥有A类的全部属性与行为,称作B对A类的继承。
假如一个类从多个类中继承了属性与服务,这称为多继承,通常我们成为继承类为子类被继承类为父类,在PHP中只有单继承,但一个父类可以被多个类继承,但是一个子类只能有一个父类,但是允许关联继承,通过继承可以减化类的定义。
extende声明继承关系
语法格式:
classBextendsA此范例指明B继承了A
类的外部访问对子类是有效的
子类与父类的属性与方法
子类继承父类的所有内容,但父类中的private部分不能直接访问
子类中新增加的属性和方法是对父类的扩展
子类中定义的与父类同名的属性是对父类属性的覆盖,同名的方法也是对父类方法的覆盖
重写的方法
在子类中,使用parent访问父类中的被覆盖的属性和方法
parent:
:
__construce();
parent:
:
$name;
parent:
:
fun();
覆盖父类原有属性
clone克窿对象语法格式$c=clone$p;$c克窿的对象$p输出echo$c->name;
对象比较
===两个比较运算符。
==是比较两个对象的内容。
===是比较对象的句柄,即引用地址。
instanceof操作符用于检测对象实力是否属于某一个类的类型属于返回true不属于返回false
__clone()如果想在克隆后改变原对象的内容,需要在__clone()中重写原本的属性和方法
function__clone(){
$this->name="我是一个克隆人";
}
final表示一个类是最终版本也就是说它不能在被子类调用
多态性
多态性是指在父类中定义的属性或行为被子类继承之后,可以具有不同的数据类型或表现出不同的行为。
这使得同一个属性或行为在父类及其各个子类中具有不同的语义。
就是说同一种方法在子类与父类中执行的结果不同。
classA{
functioninfo(){
echo“AINFO”;
}
}
classBextendsA{
functioninfo(){
echo“BINFO”;
}
}
classCextendsA{
functioninfo(){
echo“CINFO”;
}
}
functionprintinfo($obj){
functionprintinfo(A$obj){
if($objinstanceofA)
$obj->info();
$obj->info();
}
}
$a=newA();$b=newB();$c=newC();
printinfo($a);//输出AINFO
printinfo($b);//输出BINFO
printinfo($c);//输出CINFO
抽象方法和抽象类
抽象方法是作为子类摸版使用的。
abstractclassPerson{
public$name;
abstractfunctiongetInfo();
}
抽象类不能被实力话,一个抽象类中,必须有一个抽象方法。
但是抽象类中可以定义动态函数。
接口
当一个类继承了一个接口之后,它要覆盖接口的所有方法,接口只能声明常量,接口的方法必须定义为共有否则无法继承,接口可以与多个接口间继承
语法:
interfacePCI{
constTYPE="PCI";
//public$name;error
functionstart();
functionstop();
}
接口中的方法可以声明为static
interfac
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- PHP 面试 大全 高级