PHP常见题

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

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

2. SESSION 与 COOKIE的区别是什么,请从协议,产生的原因与作用说明?

A、http无状态协议,不能区分用户是否是从同一个网站上来的,同一个用户请求不同的页面不能看做是同一个用户。

B、SESSION存储在服务器端,COOKIE保存在客户端。Session比较安全,cookie用某些手段可以修改,不安全。

Session依赖于cookie进行传递。禁用cookie后,session不能正常使用。

Session的缺点:保存在服务器端,每次读取都从服务器进行读取,对服务器有资源消耗。Session保存在服务器端的文件或数据库中,默认保存在文件中,文件路径由php配置文件的session.save_path指定。Session文件是公有的。

3. HTTP 状态中302、403、 500代码含义?

一二三四五原则:(即一:消息系列;二:成功系列;三:重定向系列;四:请求错误系列;五:服务器端错误系列。)
302:临时转移成功,请求的内容已转移到新位置
403:禁止访问
500:服务器内部错误 401:代表未授权。

4. 请写出数据类型(int char varchar datetime text)的意思;请问 varchar 和 char有什么区别?

Int 整数char 定长字符 Varchar 变长字符 Datetime 日期时间型Text 文本型 Varchar与char的区别 char是固定长度的字符类型,分配多少空间,就占用多长空间。Varchar是可变长度的字符类型,内容有多大就占用多大的空间,能有效节省空间。由于varchar类型是可变的,所以在数据长度改变的时,服务器要进行额外的操作,所以效率比char类型低。

5. MyISAM和 InnoDB 的基本区别?索引结构如何实现?

A、MyISAM类型不支持事务,表锁,易产生碎片,要经常优化,读写速度较快,适合用于频繁查询的应用;
B、InnoDB类型支持事务,行锁,有崩溃恢复能力,读写速度比MyISAM慢,适合于插入和更新操作比较多的应用,空间占用大,不支持全文索引等。创建索引:alert table tablename add index 索引名 (字段名)

6. isset() 和 empty() 区别

isset判断变量是否存在,可以传入多个变量,若其中一个变量不存在则返回假;empty判断变量是否为空为假,只可传一个变量,如果为空为假则返回真。

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

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

8. 在PHP中error_reporting这个函数有什么作用?

设置PHP的报错级别并返回当前级别。

9. 现在编程中经常采取MVC三层结构,请问MVC分别指哪三层,有什么优点?

MVC三层分别指:业务模型、视图、控制器,由控制器层调用模型处理数据,然后将数据映射到视图层进行显示,优点是:①可以实现代码的重用性,避免产生代码冗余;②M和V的实现代码分离,从而使同一个程序可以使用不同的表现形式

10. 在程序的开发中,如何提高程序的运行效率?

A、优化SQL语句,查询语句中尽量不使用select *,用哪个字段查哪个字段;少用子查询可用表连接代替;少用模糊查询;

B、数据表中创建索引;

C、对程序中经常用到的数据生成缓存。

11. 语句include和require的区别是什么?为避免多次包含同一文件,可用什么语句代替它们?

区别:在失败的时候:include产生一个warning,而require产生直接产生错误中断require在运行前载入include在运行时载入代替:require_once,include_once

12. 简述php的垃圾收集机制。

php中的变量存储在变量容器zval中,zval中除了存储变量类型和值外,还有is_ref和refcount字段。refcount表示指向变量的元素个数,is_ref表示变量是否有别名。如果refcount为0时,就回收该变量容器。如果一个zval的refcount减1之后大于0,它就会进入垃圾缓冲区。当缓冲区达到最大值后,回收算法会循环遍历zval,判断其是否为垃圾,并进行释放处理。

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

CSRF,跨站请求伪造,攻击方伪装用户身份发送请求从而窃取信息或者破坏系统。讲述基本原理:用户访问A网站登陆并生成了cookie,再访问B网站,如果A网站存在CSRF漏洞,此时B网站给A网站的请求(此时相当于是用户访问),A网站会认为是用户发的请求,从而B网站就成功伪装了你的身份,因此叫跨站脚本攻击。

CSRF防范:A、合理规范api请求方式,GET,POSTB、对POST请求加token令牌验证,生成一个随机码并存入session,表单中带上这个随机码,提交的时候服务端进行验证随机码是否相同。

XSS,跨站脚本攻击。

防范:不相信任何输入,过滤输入。

14. 堆和栈的区别?

A、堆是程序运行期间动态分配的内存空间,你可以根据程序的运行情况确定要分配的堆内存的大小;

B、栈是编译期间就分配好的内存空间,因此你的代码中必须就栈的大小有明确的定义。

15. __autoload()方法的工作原理是什么?

使用这个魔术函数的基本条件是类文件的文件名要和类的名字保持一致。

当程序执行到实例化某个类的时候,如果在实例化前没有引入这个类文件,那么就自动执行__autoload()函数。

这个函数会根据实例化的类的名称来查找这个类文件的路径,当判断这个类文件路径下确实存在这个类文件后

就执行include或者require来载入该类,然后程序继续执行,如果这个路径下不存在该文件时就提示错误。

使用自动载入的魔术函数可以不必要写很多个include或者require函数。

16. 简述高并发网站解决方案。

A、前端优化(CND加速、建立独立图片服务器)

B、服务端优化(页面静态化、并发处理[异步|多线程]、队列处理)

C、数据库优化(数据库缓存[Memcachaed|Redis]、读写分离、分库分表、分区)

D、Web服务器优化(负载均衡、反向代理)

17. 怎么防止sql注入?

1)过滤掉一些常见的数据库操作关键字:select,insert,update,delete,and,*等,或者通过系统函数:addslashes(需要被过滤的内容)来进行过滤。

2)在PHP配置文件中

Register_globals=off;设置为关闭状态 //作用将注册全局变量关闭。

比如:接收POST表单的值使用$_POST[‘user’],如果将register_globals=on;直接使用$user可以接收表单的值。

3)SQL语句书写的时候尽量不要省略小引号(tab键上面那个)和单引号

4)提高数据库命名技巧,对于一些重要的字段根据程序的特点命名,取不易被猜到的

5)对于常用的方法加以封装,避免直接暴漏SQL语句

6)开启PHP安全模式

Safe_mode=on;

7)打开magic_quotes_gpc来防止SQL注入

Magic_quotes_gpc=off;默认是关闭的,它打开后将自动把用户提交的sql语句的查询进行转换,把’转为',这对防止sql注入有重大作用。

因此开启:magic_quotes_gpc=on;

8)控制错误信息

关闭错误提示信息,将错误信息写到系统日志。

9)使用mysqli或pdo预处理。

18. 对于分布式session如何处理

  1. session复制 session复制是早期的企业级的使用比较多的一种服务器集群session管理机制。应用服务器开启web容器的session复制功能,在集群中的几台服务器之间同步session对象,使得每台服务器上都保存所有的session信息,这样任何一台宕机都不会导致session的数据丢失,服务器使用session时,直接从本地获取。

    这种方式在应用集群达到数千台的时候,就会出现瓶颈,每台都需要备份session,出现内存不够用的情况。

  2. session绑定 利用hash算法,比如nginx的ip_hash,使得同一个Ip的请求分发到同一台服务器上。

    这种方式不符合对系统的高可用要求,因为一旦某台服务器宕机,那么该机器上的session也就不复存在了,用户请求切换到其他机器后么有session,无法完成业务处理。

  3. 利用cookie记录session session记录在客户端,每次请求服务器的时候,将session放在请求中发送给服务器,服务器处理完请求后再将修改后的session响应给客户端。这里的客户端就是cookie。

    利用cookie记录session的也有缺点,比如受cookie大小的限制,能记录的信息有限;每次请求响应都需要传递cookie,影响性能,如果用户关闭cookie,访问就不正常。但是由于cookie的简单易用,可用性高,支持应用服务器的线性伸缩,而大部分要记录的session信息比较小,因此事实上,许多网站或多或少的在使用cookie记录session。

  4. session服务器 session服务器可以解决上面的所有的问题,利用独立部署的session服务器(集群)统一管理session,服务器每次读写session时,都访问session服务器。

    这种解决方案事实上是应用服务器的状态分离,分为无状态的应用服务器和有状态的session服务器,然后针对这两种服务器的不同特性分别设计架构。

    对于有状态的session服务器,一种比较简单的方法是利用分布式缓存(memcached), 数据库等。在这些产品的基础上进行包装,使其符合session的存储和访问要求。

    如果业务场景对session管理有比较高的要求,比如利用session服务基层单点登录(sso),用户服务器等功能,需要开发专门的session服务管理平台。

    分布式 session 在并发的情况下,会出现 session 不同步的问题?

    可以使用 tair 的乐观锁解决这个问题,当用户取得 session 后,并获得一个版本号。当更 新 session 的时候,版本号+1。如果在跟新 session 的时候版本号不一致,则不能更新。保证 session 的一致性

19. PHP-FPM 和 Swoole 有什么区别?

两者最本质的区别在于进程模型PHP生命周期管理

  • PHP-FPM:它是传统 PHP 的进程管理器,属于多进程同步阻塞模型。

    • 每个请求会独占一个工作进程(Worker)。
    • 处理完请求后,进程会销毁所有资源(如数据库连接、变量),然后空闲等待下一个请求。
    • 生命周期:每个请求都需要完整的“启动 PHP → 初始化模块 → 执行脚本 → 销毁资源”过程。
  • Swoole:它是基于事件循环的高性能网络引擎,属于多进程异步非阻塞模型(也支持协程)。

    • 常驻内存:PHP 类、对象、数据库连接等在请求间可以复用,无需重复初始化。
    • 支持协程:用同步代码实现异步非阻塞 IO,极大提高并发能力。
    • 生命周期:全局资源只加载一次,后续请求只执行业务逻辑,没有重复加载的开销。

20. 大量请求同时发生时,PHP-FPM 和 Swoole 各自如何处理?

假设瞬间涌来 10000 个并发请求(例如秒杀开始的一刹那):

PHP-FPM 的处理方式(多进程排队)

  1. 假设你的 PHP-FPM 配置了 200 个 Worker 进程(最大通常也就几百,再大会因上下文切换导致性能陡降)。
  2. 操作系统同时把这 200 个请求分配给空闲 Worker,每个 Worker 同步、阻塞地处理自己的请求。
  3. 剩下 9800 个请求进入 TCP 全连接队列,排队等待。
  4. 当某个 Worker 完成请求并释放后,立即从队列中拉取下一个人处理。
  5. 后果:越后面的请求等待时间越长(平均排队时间 = 队列长度 × 单请求处理时间),很快触发超时,甚至导致 Nginx 或 FPM 的队列溢出,返回 502/503 错误。

本质:并发能力 = Worker 进程数,且每个进程同一时刻只能处理一个请求。

Swoole 的处理方式(协程并发)

  1. 通常配置与 CPU 核心数相当的 Worker 进程(比如 8 个),每个进程内运行成千上万个协程。

  2. 当 10000 个请求同时到达时,8 个 Worker 进程的事件循环瞬间接收全部连接。

  3. 每个 Worker 内为每个请求创建一个协程,这些协程并非同时执行代码,而是:

    • 协程 A 执行到 I/O 操作(如查数据库)时,自动挂起,Worker 立即切换执行协程 B、C、D……
    • 数据库返回数据后,协程 A 被自动唤醒,继续执行后续代码。
  4. 关键:虽然 Worker 进程只有 8 个,但 CPU 几乎没有空闲——因为 I/O 等待期间,其他协程在跑业务逻辑。10000 个请求几乎在同一时间开始处理,同时结束(总时间 ≈ 单个请求最慢的那个 I/O 耗时)。

本质:并发能力 ≈ 内存允许的协程数量(可达数万甚至数十万),且 I/O 不阻塞进程。

21.

待补充