PHP面试题库


答案均为不全面的简答,详细解答请自行网络上搜索获取


mvc是什么?

mvc是一种开发模式,主要分为三部分:m(model),也就是模型,负责数据的操作;v(view),也就是视图,负责前后台的显示;c(controller),也就是控制器,负责业务逻辑


oop是什么?

oop是面向对象编程,面向对象编程是一种计算机编程架构,OOP 的一条基本原则是计算机程序是由单个能够起到子程序作用的单元或对象组合而成。
OOP具有三大特征:封装、继承、多态
同时 易维护、质量高、效率高、易扩展


什么事面向对象?主要特征是什么?

面向对象是程序的一种设计方式,它利于提高程序的重用性,使程序结构更加清晰。主要特征:封装、继承、多态。


什么是单点登录?

单点登录SSO(Single Sign On)说得简单点就是在一个多系统共存的环境下,用户在一处登录后,就不用在其他系统中登录,也就是用户的一次登录能得到其他所有系统的信任。


session与cookie的区别?

1、cookie数据存放在第三方应用的浏览器上,session数据放在服务器上。
2、cookie不是很安全,别人可以分析存放在本地的COOKIE,进行COOKIE欺骗,考虑到安全应当使用session。
3、session会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能,考虑到减轻服务器性能方面,应当使用COOKIE。
4、单个cookie保存的数据不能超过4K,很多浏览器都限制一个站点最多保存20个cookie。
5、所以个人建议:
    将登陆信息等重要信息存放为SESSION
    其他信息如果需要保留,可以放在COOKIE


说一下单引号双引号?

单引号内部的变量不会执行, 双引号会执行
单引号解析速度比双引号快。
单引号只能解析部分特殊字符,双引号可以解析所有特殊字符。


接口和抽象类的区别是什么?

抽象类是一种不能被实例化的类,只能作为其他类的父类来使用。抽象类是通过关键字abstract来声明的。
抽象类与普通类相似,都包含成员变量和成员方法,两者的区别在于,抽象类中至少要包含一个抽象方法,抽象方法没有方法体,该方法天生就是要被子类重写的。
抽象方法的格式为:abstract function abstractMethod();
接口是通过 interface 关键字来声明的,接口中的成员常量和方法都是 public 的,方法可以不写关键字public,接口中的方法也是没有方法体。接口中的方法也天生就是要被子类实现的。
抽象类和接口实现的功能十分相似,最大的不同是接口能实现多继承。在应用中选择抽象类还是接口要看具体实现。
子类继承抽象类使用 extends,子类实现接口使用implements。


MyISAM 和 InnoDB 的基本区别?

MyISAM类型不支持事务,表锁,易产生碎片,要经常优化,读写速度较快,而InnoDB类型支持事务,行锁,有崩溃恢复能力。读写速度比MyISAM慢。


如何在页面之间传递变量(至少两种方式) ?

 GET,POST,COOKIE,SESSION,隐藏表单


请说明 PHP 中传值与传引用的区别。什么时候传值什么时候传引用?

按值传递:函数范围内对值的任何改变在函数外部都会被忽略
按引用传递:函数范围内对值的任何改变在函数外部也能反映出这些修改
优缺点:按值传递时,php必须复制值。特别是对于大型的字符串和对象来说,这将会是一个代价很大的操作。按引用传递则不需要复制值,对于性能提高很有好处。


使用PHP描述快速排序算法

原理:快速排序使用分治策略来把待排序数据序列分为两个子序列,具体步骤为:
(1)从数列中挑出一个元素,称该元素为“基准”。
(2)扫描一遍数列,将所有比“基准”小的元素排在基准前面,所有比“基准”大的元素排在基准后面。
(3)通过递归,将各子序列划分为更小的序列,直到把小于基准值元素的子数列和大于基准值元素的子数列排序。


什么是 CSRF 攻击?XSS 攻击?如何防范?

CSRF:跨站请求伪造,可以通过通过判断来源和加 Token 的方式来防范。
XSS:跨站脚本攻击,可以通过对内容转义和过滤来防范,还有 CSP


什么是进程、线程、协程

一、什么是进程

进程是程序执行是的一个实例,进程能够分配给cpu和内存等资源。进程一般包括指令集和系统资源,其中指令集就是你的代码,系统资源就是指cpu、内存以及I/O等。

进程是一个程序在一个数据集中的一次动态执行过程,可以简单理解为“正在执行的程序”,它是CPU资源分配和调度的独立单位。
进程一般由程序、数据集、进程控制块三部分组成。我们编写的程序用来描述进程要完成哪些功能以及如何完成;数据集则是程序在执行过程中所需要使用的资源;进程控制块用来记录进程的外部特征,描述进程的执行变化过程,系统可以利用它来控制和管理进程,它是系统感知进程存在的唯一标志。
进程的局限是创建、撤销和切换的开销比较大。

二、什么是线程
线程是进程的一个执行流,线程不能分配系统资源,它是进程的一部分,比进程更小的独立运行的单位。
解释一下:进程有两个特性:一是资源的所有权,一个是调度执行(指令集),线程是调度执行中的一部分,是指进程执行过程的路径,也叫程序执行流。线程有时候也叫轻量级进程。

线程是在进程之后发展出来的概念。 线程也叫轻量级进程,它是一个基本的CPU执行单元,也是程序执行过程中的最小单元,由线程ID、程序计数器、寄存器集合和堆栈共同组成。一个进程可以包含多个线程。
线程的优点是减小了程序并发执行时的开销,提高了操作系统的并发性能,缺点是线程没有自己的系统资源,只拥有在运行时必不可少的资源,但同一进程的各线程可以共享进程所拥有的系统资源,如果把进程比作一个车间,那么线程就好比是车间里面的工人。不过对于某些独占性资源存在锁机制,处理不当可能会产生“死锁”。

三、什么是协程
协程是一种用户态的轻量级线程,又称微线程,英文名Coroutine,协程的调度完全由用户控制。人们通常将协程和子程序(函数)比较着理解。
子程序调用总是一个入口,一次返回,一旦退出即完成了子程序的执行。
协程的起始处是第一个入口点,在协程里,返回点之后是接下来的入口点。在python中,协程可以通过yield来调用其它协程。通过yield方式转移执行权的协程之间不是调用者与被调用者的关系,而是彼此对称、平等的,通过相互协作共同完成任务。其运行的大致流程如下:
第一步,协程A开始执行。
第二步,协程A执行到一半,进入暂停,通过yield命令将执行权转移到协程B。
第三步,(一段时间后)协程B交还执行权。
第四步,协程A恢复执行。

协程的特点在于是一个线程执行,与多线程相比,其优势体现在:
* 协程的执行效率非常高。因为子程序切换不是线程切换,而是由程序自身控制,因此,没有线程切换的开销,和多线程比,线程数量越多,协程的性能优势就越明显。
* 协程不需要多线程的锁机制。在协程中控制共享资源不加锁,只需要判断状态就好了。
Tips:利用多核CPU最简单的方法是多进程+协程,既充分利用多核,又充分发挥协程的高效率,可获得极高的性能。

四、进程和线程的关系
进程就像地主,有土地(系统资源),线程就像佃户(线程,执行种地流程)。每个地主(进程)只要有一个干活的佃户(线程)。
进程-资源分配的最小单位,相对健壮,崩溃一般不影响其他进程,但是切换进程时耗费资源,效率差些。
线程-程序执行的最小单位,没有独立的地址空间,一个线程死掉可能整个进程就死掉,但是节省资源,切换效率高。

五、php编程常见的进程和线程
1、在web应用中,我们每次访问php,就建立一个PHP进程,当然也会建立至少一个PHP线程。
2、PHP使用pcntl来进行多进程编程
3、PHP中使用pthreads来进行多线程编程
4、nginx的每个进程只有一个线程,每个线程可以处理多个客户端的访问
5、php-fpm使用多进程模型,每个进程只有一个线程,每个线程只能处理一个客户端访问。
6、apache可能使用多进程模型,也可能使用多线程模型,取决于使用哪种SAPI.
7、进程是cpu资源分配的最小单位,线程是cpu调度的最小单位


MYSQL 中主键与唯一索引的区别

主键:绝对不能有空值。唯一索引:可以有空值


http 状态码及其含意

200 请求已成功,请求所希望的响应头或数据体将随此响应返回。
301 被请求的资源已永久移动到新位置。
302 请求的资源现在临时从不同的 URI 响应请求。
400 1、语义有误,当前请求无法被服务器理解。2、请求参数有误。
401 当前请求需要用户验证。
403 服务器已经理解请求,但是拒绝执行它。
404 请求失败,请求所希望得到的资源未被在服务器上发现。
500 服务器遇到了一个未曾预料的状况,无法完成对请求的处理,会在程序码出错时出现。
501 服务器不支持当前请求所需要的某个功能。无法识别请求的方法。
502 作为网关或者代理工作的服务器尝试执行请求时,从上游服务器接收到无效的响应。
503 由于临时的服务器维护或者过载,服务器当前无法处理请求。


linux 中怎么查看系统资源占用情况

top、htop、free、uptime


SQL 注入的原理是什么?如何防止 SQL 注入

原理:第一 SQL 本身有问题(这个不是主要问题)。第二你写的 SQL 很有问题(这是最主要的)
防范:第一,绝对不要相信用户输入的任何东西。第二,预编译。现在的框架一般都会有 SQL 过滤的。


数据库中的事务是什么?

事务(transaction)是作为一个单元的一组有序的数据库操作。如果组中的所有操作都成功,则认为事务成功,即使只有一个操作失败,事务也不成功。如果所有操作完成,
事务则提交,其修改将作用于所有其他数据库进程。如果一个操作失败,则事务将回滚,该事务所有操作的影响都将取消


遍历一个多维数组

递归。array_map 传入一个回调函数


对称加密和非对称加密的方式

对称加密:我们俩共用一个秘钥,你加密,我解密。
非对称加密:我给你一个公钥,你加密完了,我还能有我的私钥把密文解开。但是你没有我的私钥。


怎么解决跨域

JSONP
添加响应头,允许跨域
代理的方式


json 和 xml 区别,各有什么优缺点

(1)可读性方面:基本相同,XML 的可读性比较好;
(2)可扩展性方面:都具有良好的扩展性;
(3)编码难度方面:相对而言,JSON 的编码比较容易;
(4)解码难度:JSON 的解码难度基本为零,XML 需要考虑子节点和父节点;
(5)数据体积方面:JSON 相对于 XML 来讲,数据体积小,传递的速度比较快;
(6)数据交互方面:JSON 与 javascript 的交互更加方便,更容易解析处理,更好的数据交互;
(7)数据描述方面:XML 对数据描述性比较好;
(8)传输速度方面:JSON 的速度远远快于 XML。


进程间通信方式有哪些

1) 管道
管道分为有名管道和无名管道
无名管道是一种半双工的通信方式,数据只能单向流动,而且只能在具有亲缘关系的进程间使用。进程的亲缘关系一般指的是父子关系。无名管道一般用于两个不同进程之间的通信。当一个进程创建了一个管道,并调用 fork 创建自己的一个子进程后,父进程关闭读管道端,子进程关闭写管道端,这样提供了两个进程之间数据流动的一种方式。
有名管道也是一种半双工的通信方式,但是它允许无亲缘关系进程间的通信。
2) 信号量
信号量是一个计数器,可以用来控制多个线程对共享资源的访问., 它不是用于交换大批数据,而用于多线程之间的同步。它常作为一种锁机制,防止某进程在访问资源时其它进程也访问该资源。因此,主要作为进程间以及同一个进程内不同线程之间的同步手段.
3) 信号
信号是一种比较复杂的通信方式,用于通知接收进程某个事件已经发生.
4) 消息队列
消息队列是消息的链表,存放在内核中并由消息队列标识符标识。消息队列克服了信号传递信息少,管道只能承载无格式字节流以及缓冲区大小受限等特点。消息队列是 UNIX 下不同进程之间可实现共享资源的一种机制,UNIX 允许不同进程将格式化的数据流以消息队列形式发送给任意进程。对消息队列具有操作权限的进程都可以使用 msget 完成对消息队列的操作控制。通过使用消息类型,进程可以按任何顺序读信息,或为消息安排优先级顺序.
5) 共享内存
共享内存就是映射一段能被其他进程所访问的内存,这段共享内存由一个进程创建,但多个进程都可以访问。共享内存是最快的 IPC (进程间通信) 方式,它是针对其它进程间通信方式运行效率低而专门设计的。它往往与其他通信机制,如信号量,配合使用,来实现进程间的同步与通信.
6) 套接字:可用于不同及其间的进程通信


事务有几种隔离级别?

读未提交(read-uncommitted)
不可重复读(read-committed)
可重复读(repeatable-read)
串行化(serializable)


self 和 static 的区别

static:如果在子类中重写了父类中的 static 方法、属性,父类就会去访问了子类的 static 方法
self: 是类内指针,不管子类有没有重写过父类中的方法、属性都指向本类的静态方法、属性


语句include和require的区别是什么?

在失败的时候:
include 产生一个 warning ,而 require 直接产生错误中断;
require 在运行前载入;
include 在运行时载入;
require_once 和 include_once 可以避免重复包含同一文件。


了解XSS攻击吗?如何防止?

XSS是跨站脚本攻击,首先是利用跨站脚本漏洞以一个特权模式去执行攻击者构造的脚本,然后利用不安全的Activex控件执行恶意的行为。
使用htmlspecialchars()函数对提交的内容进行过滤,使字符串里面的特殊符号实体化。


什么情况下不宜建立索引?

对于查询中很少涉及的列或者重复值比较多的列,不宜建立索引。
对于一些特殊的数据类型,不宜建立索引,比如文本字段(text)等。


redis的好处

(1) 速度快,因为数据存在内存中,类似于HashMap,HashMap的优势就是查找和操作的时间复杂度都是O(1)
(2) 支持丰富数据类型,支持string,list,set,sorted set,hash
(3) 支持事务,操作都是原子性,所谓的原子性就是对数据的更改要么全部执行,要么全部不执行
(4) 丰富的特性:可用于缓存,消息,按key设置过期时间,过期后将会自动删除


redis 最适合的场景

(1)、会话缓存(Session Cache)
(2)、全页缓存(FPC)
(3)、队列
(4),排行榜/计数器
(5)、发布/订阅


字符串的常用函数?

trim()  -- 去除字符串首尾处的空白字符(或者其他字符)
strlen()  -- 字符串长度
substr()  -- 截取字符串
str_replace()  -- 替换字符串函数
substr_replace()  -- 对指定字符串中的部分字符串进行替换
strstr()  -- 检索字符串函数
explode()  -- 分割字符串函数


php的静态类为什么可以不通过实例化

静态的变量或者是函数是保存的静态内存中的,只有到程序结束时才会被释放
静态类是在编译的时候赋值的,动态类实在程序运行时动态分配的
如果程序只调用一次,静态类在编译的时候要做很多工作,动态类在执行的时候要做很多工作,php是动态语言,每一次这两步都不能省略
所以对于只运行一次的类无所谓谁快谁慢,但是如果一个类在程序中多次调用旧不一样了,多次调用静态类比动态类快凸显


简述laravel一次请求的生命周期

1、首先通过composer自动加载类
2、实例化app容器对象,在构造方法里,注册绑定基础服务,比如事件,日志,异常等
3、注册绑定http的接口和核心实现类到app容器
4、捕获请求request,将请求丢入kernel核心类的handle方法执行
5、在handle中首先把request注册到容器并清除之前request缓存
6、在handle中然后执行服务启动引导,引导http kernel类的参数bootstraper,env文件,config配置,facede别名,服务提供者注册,服务提供者引导启动
7、在handle中接着请求通过管道对象,管道任务有多个中间件,过滤
8、通过中间件后,根据路由分发到不同的控制器或者闭包执行,返回响应
9、发送响应,停止框架容器

//创建app容器实例
$app = require_once __DIR__.'/../bootstrap/app.php';
//解析kernel http 核心类
$kernel = $app->make(Illuminate\Contracts\Http\Kernel::class);
//请求丢进kernel的handle解析,并返回结果
$response = $kernel->handle(
    $request = Illuminate\Http\Request::capture()
);
//发送响应
$response->send();
//调用中间件的terminate,容器的terminate,停止
$kernel->terminate($request, $response);