首页  >  文章  >  后端开发  >  PHP面试踩过的坑

PHP面试踩过的坑

步履不停
步履不停原创
2019-07-03 17:55:2914019浏览

PHP面试踩过的坑

相关推荐:《2019年PHP面试题大汇总(收藏)

因为最近需要面试,所以特意整理了一下面试所经历的一些面试题。分享一下,希望对自己有用,也对其他人有用。尚未有答案的,后面会陆续更新,如果有补充答案的,也十分感激。

1.get,post的区别

**显示有区别 **
get方法是将字符串拼接在地址栏后面可以看见 
而post方法看不见

**传递的大小有区别 **
具体大小和浏览器有关系,ie浏览器是2k其他浏览器的最大值可能不同,但是也比较小。 
而post方法传递参数的大小是可以设定的,原来是认为无限大。在Php当中在php.ini文件是可以设置参数的大小的。

**安全性 **
get方法安全性比较低因为暴露在外面而post方法安全性比较高

**提交的原理 **
get方法提交的数据都是独立的。 
而Post方法将所有的提交的数据变成一个整体(将提交的数据变成xml格式)

**灵活性**
get方法很灵活, 
post方法不灵活,必须要有表单的参与才能用post提交很不方便

2.require,include区别

 require是无条件包含也就是如果一个流程里加入require,无论条件成立与否都会先执行require
 include有返回值,而require没有(可能因为如此require的速度比include快)
 包含文件不存在或者语法错误的时候require是致命的错误终止执行,include不是

3.获取URL后缀名

pathinfo()解析文件路径,返回其组成部分;
返回关联数组
dirname    文件路径
basename   文件名+扩展名
extension   最后一个扩展名
filename   文件名
eg: print_r( pathinfo('/ab/cd/e.php') );
Array(
  [dirname] => /ab/cd
  [basename] => e.php
  [extension] => php
  [filename] => e
)
扩展:
打印解析路径    var_dump( pathinfo($path) );
打印路径的父级路径    var_dump( pathinfo($path, PATHINFO_DIRNAME) );
打印路径的尾名    var_dump( pathinfo($path, PATHINFO_BASENAME) );
打印路径的最后的扩展名   var_dump( pathinfo($path, PATHINFO_EXTENSION) );
打印路径的文件的名字   var_dump( pathinfo($path, PATHINFO_FILENAME) );

4.tcp,udp,http区别

参考链接:https://blog.csdn.net/qq_31332467/article/details/79217262

5.获取上级目录的方法

echo __FILE__ ; // 获取当前所在文件的绝对路径及地址,结果:D:\aaa\my.php 
echo dirname(__FILE__); // 取得当前文件所在的绝对目录,结果:D:\aaa\ 
echo dirname(dirname(__FILE__)); //取得当前文件的上一层目录名,结果:D:\

6.数据库主从复制,读写分离

* 什么是主从复制
主从复制,是用来建立一个和主数据库完全一样的数据库环境,称为从数据库;

* 主从复制的原理:
1.数据库有个bin-log二进制文件,记录了所有的sql语句。
2.只需要把主数据库的bin-log文件中的sql语句复制。
3.让其从数据的relay-log重做日志文件中在执行一次这些sql语句即可。

* 主从复制的作用
1.做数据的热备份,作为后备数据库,主数据库服务器故障后,可切换到从数据库继续工作,避免数据丢失。
2.架构的扩展。业务量越来越大,I/O访问频率过高,单机无法满足,此时做多库的存储,降低磁盘I/O访问频率,提高单机的I/O性能
3.主从复制是读写分离的基础,使数据库能制成更大 的并发。例如子报表中,由于部署报表的sql语句十分慢,导致锁表,影响前台的服务。如果前台服务使用master,报表使用slave,那么报表sql将不会造成前台所,保证了前台的访问速度。

* 主从复制的几种方式:
1.同步复制:所谓的同步复制,意思是master的变化,必须等待slave-1,slave-2,...,slave-n完成后才能返回。
2.异步复制:如同AJAX请求一样。master只需要完成自己的数据库操作即可。至于slaves是否收到二进制日志,是否完成操作,不用关心。MYSQL的默认设置。
3.半同步复制:master只保证slaves中的一个操作成功,就返回,其他slave不管。
这个功能,是由google为MYSQL引入的。

* 关于读写分离
在完成主从复制时,由于slave是需要同步master的。所以对于insert/delete/update这些更新数据库的操作,应该在master中完成。而select的查询操作,则落下到slave中。

7.数据库索引

**什么是索引**
索引是对数据库表中一列或多列的值进行排序的一种结构,使用索引可快速访问数据库表中的特定信息。(摘自百度百科)

**索引类型**
1.FULLTEXT 全文索引
    全文索引,仅MyISAM引擎支持。其可以在CREATE TABLE ,ALTER TABLE ,CREATE INDEX 使用,不过目前只有 CHAR、VARCHAR ,TEXT 列上可以创建全文索引。
2.HASH 哈希索引
    HASH索引的唯一性及类似键值对的形式十分适合作为索引,HASH索引可以一次定位,不需要像树形索引那样逐层参照,因此具有极高的效率。但是这种高效是有条件的。即只在“=”和“in”条件下高效,对于范围查询,排序及组合索引仍然效率不高。
3.BTREE 树形索引
    BTREE所以是一种将索引按一定算法,存入一个树形的数据结构中(二叉树),每次查询都是从树的入口root开始,一次遍历node,获取leaf。这是MySQL中默认也是最常用的索引类型。
4.RTREE
    RTREE在MySQL中很少使用,仅支持geometry数据类型,支持该存储引擎只有MyISAM、BDb、InnoDb、NDb、Archive几种。相对于BTREE,RTREE的优势在于范围查找。

**索引种类**
普通索引:仅加速查询
唯一索引:加速查询+列值唯一(可以有null)
主键索引:加速查询+列值唯一(不可以有null)+表中只有一个
组合索引:多列值组成一个索引,专门用于组合搜索,其效率大于索引合并
全文索引:对文本内容进行分词,进行搜索
外键索引:与主键索引形成联系,保证数据的完整性。

**索引使用的注意事项**
1.符合索引遵循前缀原则
2.like查询%不能再前,否则索引失效。如有需要,使用全文索引
3.column is null可以使用索引
4.如果MySQL估计使用索引比全表扫描慢,则放弃使用索引
5.如果or前的条件中列有索引,后面的没有,索引不会生效。
6.列类型是字符串,查询时,一定要给值加引号,否则索引失效。
7.确定order by 和 group by 中只有一个表的列,这样才能使用索引

8.高并发的解决方案

web服务器优化 :负载均衡 
流量优化:防盗链处理 将恶意请求屏蔽,
前端优化:减少http请求、添加异步请求、启用浏览器缓存和文件压缩、cdn加速、建立独立的图片服务器、
服务端优化:  页面静态化、并发处理、队列处理、
数据库优化: 数据库缓存、分库分表、分区操作 、读写分离、负载均衡

9.MVC的理解

1、Model(业务模型):应用程序中用于处理应用程序数据逻辑的部分,通常模型对象负责在数据库中存取数据。          
2、view(视图):应用程序中处理数据显示的部分。通常视图是依据模型数据创建的。
3、controller(控制器):应用程序中处理用户交互的部分。通常控制器负责从视图读取数据,控制用户输入,并向模型发送数据。

10.常用的文件操作函数

**1. 获得文件名:**
basename — 返回路径中的文件名部分

$path = "/home/cate/index/index2.php";\
$file = basename($path);\
echo $file; //结果index2.php

**2. 获得目录名**
dirname — 返回路径中的目录部分

$path = "/home/cate/index/index2.php";\
$file = dirname($path);\
echo $file;//结果/home/cate/index

**3.得到路径关联数组**
pathinfo() 函数以数组的形式返回关于文件路径的信息。
返回的数组元素如下:
-   [dirname]: 目录路径
-   [basename]: 文件名
-   [extension]: 文件后缀名
-   [filename]: 不包含后缀的文件名
pathinfo(path,options)
| path | 必需。规定要检查的路径。 |
| options | 可选。规定要返回的数组元素。默认是 all。

可能的值:

-   PATHINFO_DIRNAME - 只返回 dirname
-   PATHINFO_BASENAME - 只返回 basename
-   PATHINFO_EXTENSION - 只返回 extension
-   PATHINFO_FILENAME - 只返回 filename

 |
 **4.filesize取得文件大小**
filesize ( string $filename )
返回文件大小的字节数,如果出错返回  **FALSE** 并生成一条  **E_WARNING** 级的错误。

 **判断目录是否存在**
 $lujing = "./nihao/wohao";
 if(!is_dir($liujing)){ 
     mkdir(iconv("UTF-8", "GBK", $lujing),0777,true);
 }

 **判断文件是否存在**
 file_exists(path);

11.常见的排序算法

1. 冒泡排序
思路分析:在要排序的一组数中,对当前还未排好的序列,从前往后对相邻的两个数依次进行比较和调整,让较大的数往下沉,较小的往上冒。即,每当两相邻的数比较后发现它们的排序与排序要求相反时,就将它们互换。

代码实现:
$arr=array(1,43,54,62,21,66,32,78,36,76,39);  
function bubbleSort($arr)
{  
  $len=count($arr);
  //该层循环控制 需要冒泡的轮数
  for($i=1;$i<$len;$i++)
  { //该层循环用来控制每轮 冒出一个数 需要比较的次数
    for($k=0;$k<$len-$i;$k++)
    {
       if($arr[$k]>$arr[$k+1])
        {
            $tmp=$arr[$k+1];
            $arr[$k+1]=$arr[$k];
            $arr[$k]=$tmp;
        }
    }
  }
  return $arr;
}

2. 选择排序 
思路分析:在要排序的一组数中,选出最小的一个数与第一个位置的数交换。然后在剩下的数当中再找最小的与第二个位置的数交换,如此循环到倒数第二个数和最后一个数比较为止。

代码实现:
function selectSort($arr) {
//双重循环完成,外层控制轮数,内层控制比较次数
 $len=count($arr);
    for($i=0; $i<$len-1; $i++) {
        //先假设最小的值的位置
        $p = $i;

        for($j=$i+1; $j<$len; $j++) {
            //$arr[$p] 是当前已知的最小值
            if($arr[$p] > $arr[$j]) {
            //比较,发现更小的,记录下最小值的位置;并且在下次比较时采用已知的最小值进行比较。
                $p = $j;
            }
        }
        //已经确定了当前的最小值的位置,保存到$p中。如果发现最小值的位置与当前假设的位置$i不同,则位置互换即可。
        if($p != $i) {
            $tmp = $arr[$p];
            $arr[$p] = $arr[$i];
            $arr[$i] = $tmp;
        }
    }
    //返回最终结果
    return $arr;
}

3.插入排序
思路分析:在要排序的一组数中,假设前面的数已经是排好顺序的,现在要把第n个数插到前面的有序数中,使得这n个数也是排好顺序的。如此反复循环,直到全部排好顺序。

代码实现:
function insertSort($arr) {
    $len=count($arr); 
    for($i=1, $i<$len; $i++) {
        $tmp = $arr[$i];
        //内层循环控制,比较并插入
        for($j=$i-1;$j>=0;$j--) {
            if($tmp < $arr[$j]) {
                //发现插入的元素要小,交换位置,将后边的元素与前面的元素互换
                $arr[$j+1] = $arr[$j];
                $arr[$j] = $tmp;
            } else {
                //如果碰到不需要移动的元素,由于是已经排序好是数组,则前面的就不需要再次比较了。
                break;
            }
        }
    }
    return $arr;
}

4.快速排序  
思路分析:选择一个基准元素,通常选择第一个元素或者最后一个元素。通过一趟扫描,将待排序列分成两部分,一部分比基准元素小,一部分大于等于基准元素。此时基准元素在其排好序后的正确位置,然后再用同样的方法递归地排序划分的两部分。

代码实现:
function quickSort($arr) {
    //先判断是否需要继续进行
    $length = count($arr);
    if($length <= 1) {
        return $arr;
    }
    //选择第一个元素作为基准
    $base_num = $arr[0];
    //遍历除了标尺外的所有元素,按照大小关系放入两个数组内
    //初始化两个数组
    $left_array = array();  //小于基准的
    $right_array = array();  //大于基准的
    for($i=1; $i<$length; $i++) {
        if($base_num > $arr[$i]) {
            //放入左边数组
            $left_array[] = $arr[$i];
        } else {
            //放入右边
            $right_array[] = $arr[$i];
        }
    }
    //再分别对左边和右边的数组进行相同的排序处理方式递归调用这个函数
    $left_array = quick_sort($left_array);
    $right_array = quick_sort($right_array);
    //合并
    return array_merge($left_array, array($base_num), $right_array);
}

12.接口与抽象类的区别

1. 接口
(1)对接口的使用是通过关键字implements
(2)接口不能定义成员变量(包括类静态变量),能定义常量
(3)子类必须实现接口定义的所有方法
(4)接口只能定义不能实现该方法
(5)接口没有构造函数
(6)接口中的方法和实现它的类默认都是public类型的
2. 抽象类
(1)对抽象类的使用是通过关键字extends
(2)不能被实例化,可以定义子类必须实现的方法
(3)子类必须定义父类中的所有抽象方法,这些方法的访问控制必须和父类中一样(或者更为宽松)
(4)如一个类中有一个抽象方法,则该类必须定义为抽象类
(5)抽象类可以有构造函数
(6)抽象类中的方法可以使用private,protected,public来修饰。
(7)一个类可以同时实现多个接口,但一个类只能继承于一个抽象类。
3. Final类/方法
(1)final类不能被继承
(2)final方法不能被重写
4. Static类/方法
(1)可以不实例化类而直接访问
(2)静态属性不可以由对象通过->操作符来访问,用::方式调用

13.innoDB,MyISAM的区别

MyISAM:
不支持事务;
数据存储在磁盘,可被压缩,存储空间较小;
只支持表级锁;
支持(FULLTEXT类型的)全文索引。
保存有表的总行数,如果select count(*) from table,会直接取出该值;
如果执行大量的SELECT,MyISAM是更好的选择;
不支持外键;

InnoDB:
支持事务;
存储在共享空间,需要更多的内存和存储;
具有事务、回滚和崩溃修复能力;
只支持行级锁;
不支持(FULLTEXT类型的)全文索引,但是innodb可以使用sphinx插件支持全文索引,并且效果更好;
支持外键;
如果你的数据执行大量的INSERT或UPDATE,出于性能方面的考虑,应该使用InnoDB表。

**MyISAM和InnoDB两者的应用场景:**\
1) MyISAM管理非事务表。它提供高速存储和检索,以及全文搜索能力。如果应用中需要执行大量的SELECT查询,那么MyISAM是更好的选择。\
2) InnoDB用于事务处理应用程序,具有众多特性,包括ACID事务支持。如果应用中需要执行大量的INSERT或UPDATE操作,则应该使用InnoDB,这样可以提高多用户并发操作的性能。

14.常见的设计模式

#策略模式
策略模式是对象的行为模式,用意是对一组算法的封装。动态的选择需要的算法并使用。
策略模式指的是程序中涉及决策控制的一种模式。策略模式功能非常强大,因为这个设计模式本身的核心思想就是面向对象编程的多形性思想。
策略模式的三个角色:
1.抽象策略角色
2.具体策略角色
3.环境角色(对抽象策略角色的引用)
实现步骤:
1.定义抽象角色类(定义好各个实现的共同抽象方法)
2.定义具体策略类(具体实现父类的共同方法)
3.定义环境角色类(私有化申明抽象角色变量,重载构造方法,执行抽象方法)
就在编程领域之外,有许多例子是关于策略模式的。例如:
如果我需要在早晨从家里出发去上班,我可以有几个策略考虑:我可以乘坐地铁,乘坐公交车,走路或其它的途径。每个策略可以得到相同的结果,但是使用了不同的资源。

# 工厂模式
工厂模式是我们最常用的实例化对象模式,是用工厂方法代替new操作的一种模式。
使用工厂模式的好处是,如果你想要更改所实例化的类名等,则只需更改该工厂方法内容即可,不需逐一寻找代码中具体实例化的地方(new处)修改了。为系统结构提供灵活的动态扩展机制,减少了耦合。

# 单例模式
单例模式确保某个类只有一个实例,而且自行实例化并向整个系统提供这个实例。
单例模式是一种常见的设计模式,在计算机系统中,线程池、缓存、日志对象、对话框、打印机、数据库操作、显卡的驱动程序常被设计成单例。
单例模式分3种:懒汉式单例、饿汉式单例、登记式单例。
单例模式有以下3个特点:
1.只能有一个实例。
2.必须自行创建这个实例。
3.必须给其他对象提供这一实例。
那么为什么要使用PHP单例模式?
PHP一个主要应用场合就是应用程序与数据库打交道的场景,在一个应用中会存在大量的数据库操作,针对数据库句柄连接数据库的行为,使用单例模式可以避免大量的new操作。因为每一次new操作都会消耗系统和内存的资源。

# 注册模式
注册模式,解决全局共享和交换对象。已经创建好的对象,挂在到某个全局可以使用的数组上,在需要使用的时候,直接从该数组上获取即可。将对象注册到全局的树上。任何地方直接去访问。

# 适配器模式
将各种截然不同的函数接口封装成统一的API。 \
PHP中的数据库操作有MySQL,MySQLi,PDO三种,可以用适配器模式统一成一致,使不同的数据库操作,统一成一样的API。类似的场景还有cache适配器,可以将memcache,redis,file,apc等不同的缓存函数,统一成一致。 \
首先定义一个接口(有几个方法,以及相应的参数)。然后,有几种不同的情况,就写几个类实现该接口。将完成相似功能的函数,统一成一致的方法。

15.写出乘法表的算法

1.九九乘法表 for 实现:
for($i=1;$i<10;$i++){    
    for($j=1;$j<=$i;$j++){        
    echo $i.&#39;*&#39;.$j.&#39;=&#39;.$i*$j.&#39;   &#39;;   
    }    
    echo &#39;<br />';
}
2.九九乘法表 while 实现:
$m = 1;
while($m<10){    
    $n = 1;   
    while($n<=$m){       
    echo $m.&#39;*&#39;.$n.&#39;=&#39;.$m*$n.&#39;   &#39;;        
    $n++;       
}       
echo &#39;<br>';        
$m++;}

16.echo,print_r ,print,var_dump区别

 echo是PHP语句, print和print_r是函数,语句没有返回值,函数可以有返回值(即便没有用)
 print() 只能打印出简单类型变量的值(如int,string)
 print_r() 可以打印出复杂类型变量的值(如数组,对象)
 echo 输出一个或者多个字符串
 echo:语句结构;
 print:是函数,有返回值
 print_r:能打印数组,对象
 var_dump:能打印对象数组,并且带数据类型

17.session和cookie的区别

 session:储存用户访问的全局唯一变量,存储在服务器上的php指定的目录中的(session_dir)的位置进行的存放
 cookie:用来存储连续訪問一个頁面时所使用,是存储在客户端,对于Cookie来说是存储在用户WIN的Temp目录中的。
两者都可通过时间来设置时间长短

18.用PHP写出显示客户端IP与服务器IP的代码

客户端:$_SERVER["REMOTE_ADDR"]
服务器:$_SERVER["SERVER_ADDR"]

19.sql语句应该考虑哪些安全性

(1)防止sql注入,对特殊字符进行转义,过滤或者使用预编译sql语句绑定
(2)使用最小权限原则,特别是不要使用root账户,为不同的动作或者操作建立不同的账户
(3)当sql出错时,不要把数据库出错的信息暴露到客户端

20.优化mysqi数据库的方法

(1)选取适当的字段,打字段设置为NOT NULL,在查询的时候数据库不用比较NULL;
(2)使用链接(join)代替子查询;
(3)使用联合(UNION)查询代替手动创建临时表;
(4)尽量减少使用(LIKE)关键字和通配符
(5)使用事务和外健

21.对于大流量的网站,你会采用什么方法来解决访问量?

(1)首先确认服务器硬件是否满足支持当前的流量;
(2)优化数据库的访问;
(3)禁止外部盗链;
(4)控制大文件下载;
(5)使用不同的主机分流;
(6)使用流量分析统计;

22.isset(),empty()的区别

isset():
若变量不存在则返回 FALSE 
若变量存在且其值为NULL,也返回 FALSE 
若变量存在且值不为NULL,则返回 TURE 
同时检查多个变量时,每个单项都符合上一条要求时才返回 TRUE,否则结果为 FALSE 

empty():
若变量不存在则返回 TRUE
若变量存在且其值为""、0、"0"、NULL、、FALSE、array()、var $var; 以及没有任何属性的对象,则返回 TURE\
若变量存在且值不为""、0、"0"、NULL、、FALSE、array()、var $var; 以及没有任何属性的对象,则返回 FALSE

23.六大设计原则(接14点设计模式)

1.单一职责原则:一个类只负责一个职责。
2.开闭原则:一个软件实体比如类-模块-函数,应该对扩展开放,对修改关闭。
3.里氏替换原则:所有引用基类的地方必须透明地使用其子类的对象,子类必须完全实现父类的方法,可以拓展自己的方法和属性,即子类可以扩展父类的功能,但是不能改变父类的原有功能。
4.迪米特法则:一个对象应该对其他对象保持最少的了解。
5.接口隔离原则:类间的依赖应该建立在最小的接口上。
6.依赖倒置原则:高层模块不应该依赖底层模块,二者应该依赖其抽象;抽象不应该依赖细节;细节应该依赖抽象;

24.group by 与distinct的区别

25.开发中应该注意哪些安全机制

1.PHP配置
2.Sql注入,
3.Xss攻击(cross site script 跨站脚本),
4.盗链,
5.CSRF(跨站请求伪造cross site request forgery),
6.CC(是利用不断对网站发送连接请求致使形成拒绝服务的目的)

26.memcache和Redis的区别

数据结构:memcache仅支持简单的key-value形式,Redis支持的数据更多(string字符串,set集合,list列表,hash散列,zset有序集合);
多线程:memcache支持多线程,Redis支持单线程
持久化:Redis支持持久化,memcache不支持持久化
分布式:Redis做主从结构,memcache服务器需要通过hash一致化来支撑主从结构

1.  Redis中,并不是所有的数据都一直存储在内存中的,这是和Memcache相比一个最大的区别。
2.  Redis在很多方面具备数据库的特征,或者说就是一个数据库系统,而Memcache只是简单的K/V缓存。
3.  他们的扩展都需要做集群;实现方式:master-slave、Hash。
4.  在100k以上的数据中,Memcache性能要高于Redis。
5.  如果要说内存使用效率,使用简单的key-value存储的话,Memcached的内存利用率更高,而如果Redis采用hash结构来做key-value存储,由于其组合式的压缩,其内存利用率会高于Memcache。当然,这和你的应用场景和数据特性有关。
6.  如果你对数据持久化和数据同步有所要求,那么推荐你选择Redis,因为这两个特性Memcache都不具备。即使你只是希望在升级或者重启系统后缓存数据不会丢失,选择Redis也是明智的。
7.  Redis和Memcache在写入性能上面差别不大,读取性能上面尤其是批量读取性能上面Memcache更强

27.常用的数组函数

数组的键名和值:
array_values($arr);  获得数组的值
array_keys($arr);  获得数组的键名
array_flip($arr);  数组中的值与键名互换(如果有重复前面的会被后面的覆盖)
in_array("apple",$arr);  在数组中检索apple
array_search("apple",$arr);  在数组中检索apple ,如果存在返回键名
array_key_exists("apple",$arr);  检索给定的键名是否存在数组中
isset($arr[apple]):   检索给定的键名是否存在数组中

数组的内部指针:
current($arr);  返回数组中的当前单元\
pos($arr);  返回数组中的当前单元\
key($arr);  返回数组中当前单元的键名\
prev($arr);  将数组中的内部指针倒回一位\
next($arr);  将数组中的内部指针向前移动一位\
end($arr);  将数组中的内部指针指向最后一个单元\
reset($arr;  将数组中的内部指针指向第一个单元\
each($arr);  将返回数组当前元素的一个键名/值的构造数组,并使数组指针向前移动一位\
list($key,$value)=each($arr);  获得数组当前元素的键名和值

数组的排序:
1.通过元素值对数组排序:
sort($arr);  由小到大的顺序排序(第二个参数为按什么方式排序)忽略键名的数组排序\
rsort($arr);  由大到小的顺序排序(第二个参数为按什么方式排序)忽略键名的数组排序\
usort($arr,"function");  使用用户自定义的比较函数对数组中的值进行排序(function中有两个参数,0表示相等,正数表示第一个大于第二个,负数表示第一个小于第二个)忽略键名的数组排序\
asort($arr);  由小到大的顺序排序(第二个参数为按什么方式排序)保留键名的数组排序\
arsort($arr);  由大到小的顺序排序(第二个参数为按什么方式排序)保留键名的数组排序\
uasort($arr,"function");  使用用户自定义的比较函数对数组中的值进行排序(function中有两个参数,0表示相等,正数表示第一个大于第二个,负数表示第一个小于第二个)保留键名的数组排序

2.通过键名对数组排序
ksort($arr);  按照键名正序排序\
krsort($arr);  按照键名逆序排序\
uksort($arr,"function");  使用用户自定义的比较函数对数组中的键名进行排序(function中有两个参数,0表示相等,正数表示第一个大于第二个,负数表示第一个小于第二个)

数组的合并:
array_merge($arr1,$arr2);  合并两个或多个数组(相同的字符串键名,后面的覆盖前面的,相同的数字键名,后面的不会做覆盖操作,而是附加到后面)
array_merge_recursive($arr1,$arr2);   递归合并操作,如果数组中有相同的字符串键名,这些值将被合并到一个数组中去。如果一个值本身是一个数组,将按照相应的键名把它合并为另一个数组。当数组 具有相同的数组键名时,后一个值将不会覆盖原来的值,而是附加到后面

数组的差集
array_diff($arr1,$arr2);  返回差集结果数组\
array_diff_assoc($arr1,$arr2,$arr3);  返回差集结果数组,键名也做比较

数组的交集
array_intersect($arr1,$arr2);  返回交集结果数组\
array_intersect_assoc($arr1,$arr2);  返回交集结果数组,键名也做比较

其他:
extract($arr);用于把数组中的元素转换成变量导入到当前文件中,键名当作变量名,值作为变量值
compact(var1,var2,var3);compact() 函数创建包含变量名和它们的值的数组。
array_slice($arr,0,3);  可以将数组中的一段取出,此函数忽略键名
array_push($arr,"apple","pear");  将一个或多个元素压入数组栈的末尾(入栈),返回入栈元素的个数\
array_pop($arr);  将数组栈的最后一个元素弹出(出栈)

28.浏览器通过URL访问的原理

1.键盘或触屏输入URL并回车确认
2.URL解析/DNS解析查找域名IP地址
3.网络连接发起HTTP请求
4.HTTP报文传输过程
5.服务器接收数据
6.服务器响应请求/MVC
7.服务器返回数据
8.客户端接收数据
9.浏览器加载/渲染页面
10.打印绘制输出

29.常见的负载均衡方案

1.基于DNS的负载均衡
2.基于四层交换技术的负载均衡
3.基于七层交换技术的负载均衡
4.四层+七层负载结合方案

30.mysql_fetch_row()和mysql_fetch_array()的区别

mysql_fetch_row() 从和结果标识 data 关联的结果集中取得一行数据并作为数组返回。每个结果的列储存在一个数组的单元中,偏移量从 0 开始。依次调用 mysql_fetch_row() 将返回结果集中的下一行,如果没有更多行则返回 FALSE。                                                     

mysql_fetch_array() 函数从结果集中取得一行作为关联数组,或数字数组,或二者兼有。

解释:
(1)如果你的表里面有字段a,b,c那么你用mysql_fetch_row()  就返回array(1=>a的值,2=>b的值,3=>c的值)这个时候你读数组的话,只能这样写$array[1],$array[2]才能得到a的值;

(2)要是用mysql_fetch_array()  就返回array(a=>a的值,b=>b的值,c=>c的值)和 array(1=>a的值,2=>b的值,3=>c的值)这个时候你读数组的话$array[1]和$array[a]都能得到a的值

31.如何保障代码在多个PHP版本中可以正常运行

通过修改nginx配置文件的fastCGI,监听不同端口,从而选择不一样的版本。

32.分析MySQL查询慢的原因

1.查看慢查询日志
2.通过pt-query-digest工具分析
3.设置set profiling = 1;开启服务,执行show profile。查看所有语句会监测消耗时间存到临时表
4.找到消耗时间大的ID,执行show profile for query 临时表ID
5.使用show status,show processlist 等命令查看
6.使用explain分析单条SQL语句

33.如何不借助第三变量交换两个变量的值

字符串交换:
1.substr,strlen两个方法实现:
$a="abc";
$b="bcd";
echo '交换前 $a:'.$a.',$b:'.$b.'<br />';

$a.=$b;//将字符串合并为一条

//利用切割字符串的方法交换
$b=substr($a,0,(strlen($a)-strlen($b)));
$a=substr($a, strlen($b));
echo '交换后$a:'.$a.',$b:'.$b.'<br />';

2.使用str_replace方法实现:
$a="abc";\
$b="bcd";\
echo '交换前 $a:'.$a.',$b:'.$b.'<br />';\
$a.=$b;\
$b=str_replace($b, "", $a);\
$a=str_replace($b, "", $a);\
echo '交换后$a:'.$a.',$b:'.$b.'<br />';\

3.结合使用list方法和array实现:
$a="abc";\
$b="bcd";\
echo '交换前 $a:'.$a.',$b:'.$b.'<br />';\
list($b,$a)=array($a,$b);\
echo '交换后$a:'.$a.',$b:'.$b.'<br />';
PS:list()用法:把数组中的值赋给list中的变量中:
    $my_array = array("Dog","Cat","Horse");
    list($a, $b, $c) = $my_array;
    则 $a = "Dog",$b = "Cat" ,  $c = "Horse";

字符串和数字都适用 使用异或运算:
$a="abc";\
$b="bcd";\
echo '交换前 $a:'.$a.',$b:'.$b.'<br />';\
$a=$a^$b;\
$b=$b^$a;\
$a=$a^$b;\
echo '交换后$a:'.$a.',$b:'.$b.'<br />';    

原理:https://blog.csdn.net/github_37767025/article/details/68943789

只适用于数字:
$a=3;\
$b=5;\
echo '交换前 $a:'.$a.',$b:'.$b.'<br />';\
$a=$a+$b;\
$b=$a-$b;\
$a=$a-$b;\
echo '交换后$a:'.$a.',$b:'.$b.'<br />';

34.char和varchar的区别

1.varchar用于存储可变长度,char用于存储定长
2.对于经常变更的数据char比varchar更好,不容易产生碎片
3.对于非常短的列,char比varcahr在存储空间上更有效率
4.char对于未达到长度的数据会自动补空格

35.MySQL事务的四大特性

一般来说,事务是必须满足4个条件(ACID)::原子性(Atomicity,或称不可分割性)、一致性(Consistency)、隔离性(Isolation,又称独立性)、持久性(Durability)。

    原子性:一个事务(transaction)中的所有操作,要么全部完成,要么全部不完成,不会结束在中间某个环节。事务在执行过程中发生错误,会被回滚(Rollback)到事务开始前的状态,就像这个事务从来没有执行过一样。

    一致性:在事务开始之前和事务结束以后,数据库的完整性没有被破坏。这表示写入的资料必须完全符合所有的预设规则,这包含资料的精确度、串联性以及后续数据库可以自发性地完成预定的工作。

    隔离性:数据库允许多个并发事务同时对其数据进行读写和修改的能力,隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致。事务隔离分为不同级别,包括读未提交(Read uncommitted)、读提交(read committed)、可重复读(repeatable read)和串行化(Serializable)。

    持久性:事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。

36.线程和进程

进程:是并发执行的程序在执行过程中分配和管理资源的基本单位,是一个动态概念,竞争计算机系统资源的基本单位。

线程:是进程的一个执行单元,是进程内科调度实体。比进程更小的独立运行的基本单位。线程也被称为轻量级进程。一个程序至少一个进程,一个进程至少一个线程。

**进程线程的区别:**

-   地址空间:同一进程的线程共享本进程的地址空间,而进程之间则是独立的地址空间。
-   资源拥有:同一进程内的线程共享本进程的资源如内存、I/O、cpu等,但是进程之间的资源是独立的。

     一个进程崩溃后,在保护模式下不会对其他进程产生影响,但是一个线程崩溃整个进程都死掉。所以多进程要比多线程健壮。

     进程切换时,消耗的资源大,效率高。所以涉及到频繁的切换时,使用线程要好于进程。同样如果要求同时进行并且又要共享某些变量的并发操作,只能用线程不能用进程

-   执行过程:每个独立的进程程有一个程序运行的入口、顺序执行序列和程序入口。但是线程不能独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。
-   线程是处理器调度的基本单位,但是进程不是。
-   两者均可并发执行。

**优缺点:**

  线程执行开销小,但是不利于资源的管理和保护。线程适合在SMP机器(双CPU系统)上运行。

  进程执行开销大,但是能够很好的进行资源管理和保护。进程可以跨机器前移。

  **何时使用多进程,何时使用多线程?**

对资源的管理和保护要求高,不限制开销和效率时,使用多进程。

要求效率高,频繁切换时,资源的保护管理要求不是很高时,使用多线程。

38.HTTP状态码

1**
信息,服务器收到请求,需要请求者继续执行操作
2**
成功,操作被成功接收并处理
3**
重定向,需要进一步的操作以完成请求
4**
客户端错误,请求包含语法错误或无法完成请求
5**
服务器错误,服务器在处理请求的过程中发生了错误

39.Linux服务器CPU负载过高的排查方法

参考链接:https://blog.csdn.net/u014692324/article/details/80816521

40.常见的查找算法

参考链接:https://segmentfault.com/a/1190000016582674

41.PHP中布尔值为false的情况

JS:
1、undefined(未定义,找不到值时出现)
2、null(代表空值)
3、false(布尔值的false,字符串"false"布尔值为true)
4、0(数字0,字符串"0"布尔值为true)
5、NaN(无法计算结果时出现,表示"非数值";但是tapeof NaN==="number")
6、""(双引号)或''(单引号) (空字符串,中间有空格时也是true)

PHP:
1、undefined(未定义,找不到值时出现)
2、null(代表空值)
3、false(布尔值的false,字符串"false"布尔值为true)
4、0(数字0,字符串"0"布尔值都为false)
5、""(双引号)或''(单引号) (空字符串,中间有空格时也是true)

推荐教程:phpStudy极速入门视频教程

以上是PHP面试踩过的坑的详细内容。更多信息请关注PHP中文网其他相关文章!

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn