PHP面试题精选

本文详细介绍了PHP在Web开发中的各种技术,包括字符串和数组操作、文件处理、HTTP请求方法、数据库交互(如MySQL与Redis)、PHP框架(如ThinkPHP)、服务器配置(如Nginx与PHP-FPM)、安全机制(如防止SQL注入和XSS攻击)以及分布式系统中的概念。此外,还涵盖了其他编程语言(如Go)和工具(如Swoole)的对比,以及数据库引擎(如MyISAM与InnoDB)的区别。文章最后讨论了MySQL的优化策略、缓存管理和高可用方案。

双引号和单引号的区别

双引号解释变量,单引号不解释变量和转义
双引号里插入单引号,其中单引号里如果有变量的话,变量解释

获取文件名后缀的方法

$file = 'x.y.z.png';
echo substr(strrchr($file, '.'), 1);	//1

echo substr($file, strrpos($file, '.')+1);	//2

$arr=explode('.', $file);	//3
echo $arr[count($arr)-1];

echo pathinfo($file)['extension'];	//4
echo pathinfo($file, PATHINFO_EXTENSION);

php实现冒泡排序

function bubbleSort($array){
    $count = count($array);
    for ($i=0;$i<$count-1;$i++){
        for ($j=0;$j<$count-$i-1;$j++) {
            if($array[$j] > $array[$j+1]) {
                $t = $array[$j];
                $array[$j] = $array[$j+1];
                $array[$j+1] = $t;
            }
        }
    }
    return $array;
}

php打印乘法表

for($i=1;$i<=9;$i++)  //控制行数
{
    for ($k=1; $k <=$i; $k++) { //控制列数
        echo $k."*".$i."=".$k*$i.'\t';
    }
    echo '\n';
}

打印昨天这个时候的时间

echo date("Y-m-d",strtotime("-1 day"));

字符串相关方法

substr(string,start,length)	//按长度截取字符串,start为stirng数组下标,得到的字符串包含start下标的字符,start为负数时表示从后往前截取
mb_substr(string,start,length,encoding) //与substr相似,分割中文字符时用
    
strrev(string)	//字符串反转
strpos(string,str)	//返回str在string中第一次出现的位置,如果没有则返回false
strrchr(string,str) //返回str在string中最后一次出现的位置,如果没有则返回false
substr_count(string,str)	///返回str在string中出现的次数

数组相关方法

array_unique($arr)	//元素去重,返回过滤后的数组
array_merge($arr1,$arr2)	//合并返回合并的数组
array_push($arr,$value1,$value2...)$array[]=$value	//追加元素返回新数组的元素个数
array_reverse($arr)   //数组反转,返回翻转后的数组
array_shift($arr)    //删除数组中的第一个元素(red),返回被删除元素的值
array_pop($arr)   //删除数组中的最后一个元素返回数组的最后一个值。如果数组是空的,或者非数组,将返回 NULL

常用的超全局变量

$_GET ----->get传送方式 $_POST ----->post传送方式 $_REQUEST ----->可以接收到get和post两种方式的值 $_GLOBALS ----->所有的变量都放在里面 $_FILES ----->上传文件使用 $_SERVER ----->系统环境变量 $_SESSION ----->会话控制的时候会用到 $_COOKIE ----->会话控制的时候会用到

常用的魔术方法

__get:用来获取私有成员属性值
__set:用来设置私有属性, 给一个未定义的属性赋值时,此方法会被触发,传递的参数是被设置的属性名和值
__call:在调用不存在或不可访问的方法时会被调用,其作用为:让程序继续执行下去,避免当调用的方法不存在或不可访问时,产生错误导致程序终止。
__construct:用于对对象的属性进行初始化
__destruct:通常用于释放对象占用的第三方资源(如:数据库)
__invoke:兼容对象的函数调用形式,允许用户像使用函数一样使用对象

HTTP请求中Content-Type的作用

在请求中,Content-Type 是实体头部用于指示资源的类型,服务端根据这个类型来做不同的处理。

在响应中,Content-Type标头告诉客户端实际返回的内容类型,浏览器根据Content-Type来对文件做不同的处理,例如text、json、excell等

HTTP中POST、GET方式的区别

Get是不安全的,因为在传输过程,数据被放在请求的URL中,对用户是可见的;

Get传送的数据量较小,这主要是因为受URL长度限制;

php://input, POST与_POST与POST_GET的区别

  • $_POST以关联数组方式组织提交的数据,并对此进行编码处理,如urldecode,甚至编码转换;而php://input 通过输入流以文件读取方式取得未经处理的POST原始数据;
  • php://input 允许读取 POST 的’原始数据。和 HTTPRAWPOSTDATA比起来,它给内存带来的压力较小,并且不需要任何特殊的php.ini设置。HTTP_RAW_POST_DATA 比起来,它给内存带来的压力较小,并且不需要任何特殊的 php.ini 设置。HTTPRAWPOSTDATAphp.iniHTTP_RAW_POST_DATA 是PHP内置的一个全局变量。它用于PHP在无法识别的Content-Type的情况下,将POST过来的数据原样地填入变量HTTPRAWPOSTDATA。它同样无法读取Content−Type为multipart/form−data的POST数据。需要设置php.ini中的alwayspopulaterawpostdata值为On,PHP才会总把POST数据填入变量HTTP_RAW_POST_DATA 。它同样无法读取Content-Type为multipart/form-data的POST数据。需要设置php.ini中的always_populate_raw_post_data值为On,PHP才会总把POST数据填入变量HTTPRAWPOSTDATAContentTypemultipart/formdataPOSTphp.inialwayspopulaterawpostdataOnPHPPOSThttp_raw_post_data。
  • php://input读取不到$_GET数据。

echo、print_r、print、var_dump之间的区别

echo、print是php语句,var_dump和print_r是函数

echo 输出一个或多个字符串,中间以逗号隔开,没有返回值是语言结构而不是真正的函数,因此不能作为表达式的一部分使用

print有返回值,只能打印出简单类型变量的值;

print_r 可以打印出复杂类型变量的值(如数组、对象)以列表的形式显示,并以array、object开头;

var_dump() 判断一个变量的类型和长度,并输出变量的数值;

mysql中char和varchar区别

char表示定长、长度固定,varchanr表示变长,即长度可变。
对于char类型来说,最多只能存放的字符个数为255,和编码无关。
varchar最多能存放65532个字符。VARCHAR的最大有效长度由最大行大小和使用的字符集来确定。

mysql备份和恢复语句

备份指定数据库:
mysqldump -h hostname -u username -p databasename > db.sql

恢复:
mysql -h hostname -u username -p databasename < backupfile.sql

如何获取客户端的ip

$_SERVER[“REMOTE_ADDR”];或者getenv(‘REMOTE_ADDR’)

include和require、require_once的区别是什么

require是无条件包含,当文件不存在或者无法打开的时候,会提示错误,并且会终止程序执行;

include有返回值,而require没有,如果被包含的文件不存在的化,那么会提示一个错误,但是程序会继续执行下去;

require_once表示了只包含一次,避免了重复包含;

传值与传引用的区别?

变量默认总是传值赋值,当一个变量的赋予另外一个变量时,改变其中一个变量的值,将不会影响到另外一个变量

php-fpm工作原理

首先要了解几个概念

  • cgi:语言解释器与webwerver的通信协议
  • fast-cgi:是cgi的改良版本,webserver每收到一个请求,都会去fork一个cgi进程,请求结束再kill掉这个进程,发现很浪费资源。fast-cgi每次处理完请求后,不会kill掉这个进程,而是保留这个进程,使这个进程可以一次处理多个请求。这样每次就不用重新fork一个进程了,大大提高了效率
  • php-fpm:即php-Fastcgi Process Manage,是 FastCGI 的实现,并提供了进程管理的功能,包含 master 进程和 worker 进程两种进程,master 进程只有一个,负责监听端口,接收来自 Web Server 的请求,而 worker 进程则一般有多个(具体数量根据实际需要配置),每个进程内部都嵌入了一个 PHP 解释器,是 PHP 代码真正执行的地方

nginx与php-fpm的结合,完整的流程:

1)、FastCGI进程管理器php-fpm自身初始化,启动主进程php-fpm和启动start_servers个CGI 子进程。主进程php-fpm主要是管理fastcgi子进程,监听9000端口。fastcgi子进程等待来自Web Server的连接。

2)、当客户端请求到达Web Server Nginx是时,Nginx通过location指令,将所有以php为后缀的文件都交给127.0.0.1:9000来处理,即Nginx通过location指令,将所有以php为后缀的文件都交给127.0.0.1:9000来处理。

3)FastCGI进程管理器PHP-FPM选择并连接到一个子进程CGI解释器。Web server将CGI环境变量和标准输入发送到FastCGI子进程。

4)、FastCGI子进程完成处理后将标准输出和错误信息从同一连接返回Web Server。当FastCGI子进程关闭连接时,请求便告处理完成。

5)、FastCGI子进程接着等待并处理来自FastCGI进程管理器(运行在 WebServer中)的下一个连接。

phpize是什么

phpize是用来添加php扩展模块的,通过phpize可以建立php的外挂模块.
比如你想在原来编译好的php中加入memcached或者ImageMagick等扩展模块,可以使用phpize对php进行添加扩展。并且phpize编译的扩展库可以随时启用或停用,比较灵活

ThinkPHP框架中D函数与M函数的区别是什么?

M方法实例化模型无需用户为每个数据表定义模型类,D方法可以自动检测模型类,如果存在自定义的模型类,则实例化自定义模型类,如果不存在,则会自动调用M方法去实例化Model基类。同时对于已实例化过的模型,不会重复去实例化

ThinkPHP框架中的URL模式

普通模式、PATHINFO、REWRITE和兼容模式

ThinkPHP框架的运作流程

  1. 用户URL请求

  2. 调用应用入口文件(通常是网站的index.php)

  3. 载入框架入口文件(ThinkPHP.php)

  4. 记录初始运行时间和内存开销

  5. 系统常量判断及定义

  6. 载入框架引导类(Think\Think)并执行Think::start方法进行应用初始化

  7. 设置错误处理机制和自动加载机制

  8. 调用Think\Storage类进行存储初始化(由STORAGE_TYPE常量定义存储类型)

    。。。。。

ThinkPHP框架的路由原理

TP的访问规则是:根目录/模块/控制器/方法,那么我们只需要定义一下映射关系“reg”=>“index/user/reg”,此时只需要再浏览器输入“域名/reg”就能访问“index模块/user/控制器/reg方法”这个地址了

JWT是什么

Json Web Token,是基于Json的一个公开规范,这个规范允许我们使用JWT在用户和服务器之间传递安全可靠的信息,他的两大使用场景是:认证和数据交换。它的原理是由服务端根据规范生成一个令牌(token),并且发放给客户端。此时客户端请求服务端的时候就可以携带者令牌,以令牌来证明自己的身份信息。

swoole是什么,有什么使用场景

Swoole是PHP的异步、并行、高性能网络通信引擎,使用纯C语言编写。一般用于即时通讯,分布式服务等

基于swoole的协程框架有哪些?

Hyperf Swoft EasySwoole

swoole与go语言的协程区别

  • Go 语言原生层面就支持协层,不需要声明协程环境,swoole需要php支持扩展
  • Go 协程是基于多线程的,可以利用多核 CPU,同一时间可能会有多个协程在执行,swoole是单线程

swoole和workman的区别

workerman纯php写的,swoole是php的c扩展,性能肯定更高。
功能上swoole提供的高级特性很多,例如SSL/TLS隧道加密、http2.0、异步mysql驱动、异步redis驱动、异步的http/websocket客户端等。
外部依赖上workerman需要依赖很多额外的第三方PHP扩展来实现,局限性比较大,这些扩展并非是PHP官方维护的,维护性方面良莠不齐,有些扩展连PHP7都不支持,数年没人维护。而Swoole基本上无依赖,底层的代码全部可控。
当然workerman的优势是它完全使用PHP代码实现,开发者可以直接看它的源码。有特殊需求也可以直接改源码来实现。

Redis的数据类型及应用?

Redis支持五种常用数据类型:
string(字符串):缓存或计数器,
hash(哈希):它的结构类似于一个对象,用于存储哈希表或数据表,
list(列表):内部是一个双向链表,元素可重复,用做队列和栈,
set(集合):类似数组结构,用作一组数字或字符串的集合,
zset(sorted set:有序集合):带权值排序的集合,用于排行等

解决mysql和Redis数据不一致问题

  • 更新数据库的时候,同步或异步更新redis
  • 设置缓存失效时间,如果有缓存就从缓存中取数据,如果没缓存就从数据库中取数据,并且重新设置缓存
  • 定时任务,按照一定时间间隔更新缓存

MySQL的MyISAM和InnoDB引擎区别

MySQL默认采用的是MyISAMMyISAM不支持事务;

MyISAM不支持事务,而InnoDB支持;

InnoDB支持数据行锁定,MyISAM不支持行锁定,只支持锁定整个表;

InnoDB支持外键,MyISAM不支持;

redis消息队列先进先出需要注意什么

都是先进先出,如果想优先处理某个任务就不太好处理了,这就需要让队列有优先级的概念;实现方式有以下几种方式:

1)单一列表实现:队列正常的操作是 左进右出(lpush,rpop)为了先处理高优先级任务,在遇到高级别任务时,可以直接插队,直接放入队列头部(rpush)

2)使用两个队列,一个普通队列,一个高级队列,针对任务的级别放入不同的队列

redis 和 memache 缓存的区别

1、存储方式:
memecache 把数据全部存在内存之中,断电后会挂掉,数据不能超过内存大小
redis有部份存在硬盘上,这样能保证数据的持久性。
2、数据支持类型:
redis在数据支持上要比memecache多的多。
3、使用底层模型不同:
新版本的redis直接自己构建了VM 机制 ,因为一般的系统调用系统函数的话,会浪费一定的时间去移动和请求。

redis常用命令

添加键值:set key value
获取键值:get key
删除键值:del key
是否存在:exists key
设置过期时间:expire key seconds
获取剩余生存时间:ttl key
添加hash:HMSET key name “redis tutorial” description “redis basic” (name和description 是属性)
获取hash:HGETALL key
添加列表:LPUSH list_name list_item
取出列表:BLPOP list_name
遍历列表:LRANGE KEY_NAME START END
添加集合:SADD set_name set_item
获取集合:SMEMBERS set_name
添加有序集合:ZADD KEY_NAME SCORE1 VALUE1
遍历有序集合:ZRANGE KEY_NAME 0 -1 WITHSCORES

redis分布式锁及防止死锁

在开发中,如果是多个进程相互竞争一个资源,使用Redis的分布式锁可以保证资源只会被一个操作者持有。
redis设置锁: setnx lock_key true
删除锁:del lock_key
假设有两个客户端同时竞争锁,即向Redis写入lock_key,A客户端写入成功则A先获取到锁,客户端B写入失败则B未获取到锁。A客户端在使用完资源后,将redis中lock_key删除,即释放锁。

但这样是存在一些问题的,试想如果A客户端在获取锁后,出现了故障,导致del语句没有调用,这样lock_key就一直得不到释放,即该资源锁一直存在,那么其他服务也就永远得不到该资源了。
解决:在Redis写入数据时,可以设置数据过期时间,这样即便在服务故障,锁也能自动释放,语法(Redis2.8+):set lock_key true ex 5 nx

MySQL的优化?

参考答案:

1.建立索引

2.应尽量避免在 where 子句中对字段进行 null 值判断,否则将引擎放弃使用索引而进行全表扫描

3.应尽量避免在 where 子句中使用!=或<>操作符,否则将引擎放弃使用索引而进行全表扫描

4.应尽量避免在 where 子句中使用 or 来连接条件,否则将导致引擎放弃使用索引而进行全表扫描

5.in 和 not in 也要慎用,否则会导致全表扫描

6.尽可能的使用 varchar 代替 char ,因为首先变长字段存储空间小,可以节省存储空间

7.MySQL集群、负载均衡、读写分离

8.尽量使用整型表示字符串

9.不要写一些没有意义的查询,如需要生成一个空表结构:select col1,col2 into #t from t where 1=0

如何防止SQL注入

查询条件尽量使用数组方式;

使用预处理机制;

数据字段类型验证;

MySQL高可用方案及其原理

主从复制:异步方式,主服务器执行更改数据的事务后,会产生 binlog,之后 binlog 会被发送到从服务器变成 relay log,与此同时,主服务器会对应用提交返回。从服务器接收到 relay log 后,会通过一个 applier 的线程对日志里面的内容进行施放,使产生的数据更改写入从服务器,之后产生自己的 binlog,进行提交。

MySQL主从不同步原因分析及解决方案

原因:

  • 网络延迟
  • 主从两台机器的负载不一致
  • max_allowed_packet设置不一致
  • key自增键开始的键值跟自增步长设置不一致引起的主从不一致
  • 版本不一致

主从数据不同步是不可避免的,只能尽可能减少这种情况

解决方案:

  • 使用高版本,mysql-5.6.3已经支持了多线程的主从复制,同步速度更快
  • 搭建多个从库做负载均衡,减少从库的查询次数,将更多时间和性能用于同步
  • 使用高配置的从库
  • 调整数据库参数,配置sync_binlog=1,innodb_flush_log_at_trx_commit=1等设置。而Slave可以关闭binlog,innodb_flush_log_at_trx_commit也可以设置为0来提高sql的执行效率,默认值1的意思是每一次事务提交或事务外的指令都需要把日志写入(flush)硬盘。

MySQL如何查看慢查询日志

方法一:找到my.ini文件,配置如下,并重启mysql服务

[mysqld]
slow_query_log = on; #打开慢查询
long_query_time = 1 #设置统计时间阈值,sql执行超过这个时间即统计,单位是秒
slow_query_log_file = /tmp/slow.log #日志存放位置

方法二:

mysql命令行执行

SET GLOBAL slow_query_log = on;#打开慢日志统计
SET GLOBAL long_query_time = 2.000000;#设置统计时间阈值,sql执行超过这个时间即统计,单位是秒

分布式事务以及常用解决方案

分布式事务(XA)在多系统协作,比如跨行转账、下单扣库存等特别是微服务架构方面经常用到。分布式事务需要保证的就是一致性问题,例如在大型电商系统中,下单接口通常会扣减库存、减去优惠、生成订单 id, 而订单服务与库存、优惠、订单 id 都是不同的服务,下单接口的成功与否,不仅取决于本地的 db 操作,而且依赖第三方系统的结果,这时候分布式事务就保证这些操作要么全部成功,要么全部失败。

解决方案:

  • 两阶段提交(2PC):顾名思义就是要分两步提交,第一阶段(prepare):事务管理器向所有本地资源管理器发起请求,询问是否是就绪(ready )状态,所有参与者都将本事务能否成功的信息反馈发给协调者;第二阶段 (commit/rollback):事务管理器根据所有本地资源管理器的反馈,通知所有本地资源管理器,步调一致地在所有分支上提交或者回滚。存在问题:同步阻塞,其中一个占用了资源,其他事务参与者就只能阻塞等待资源释放,处于阻塞状态;数据不一致:在阶段二,如果事务管理器只发送了部分 commit 消息,此时网络发生异常,那么只有部分参与者接收到 commit 消息,也就是说只有部分参与者提交了事务,使得系统数据不一致。
  • TCC

linux常用命令

  • CPU使用率:top
  • 内存使用率:free -h
  • 磁盘使用率:df -h
  • 指定程序的内存占用:先用ps -ef | grep 进程名 获取pid,然后用pmap -x pid
  • 添加可执行权限:chmod u+x xxx.sh ;u代表所有者,x代表执行权限, + 表示增加权限
  • 移动/重命名:mv 目录/文件名 目标目录/文件名
  • 删除目录:rm -rf 目录路径
  • 查看文件:(1)tail -f 文件名,查看文件最后几行 ,-n指定显示多少行(2)more 文件名,按空格翻页 (3)less 文件名 (4)cat -n 文件名,从1开始对所有输出的行数(包括空行)进行编号
  • 压缩: tar -czvf xxx.tar.gz source_file
  • 解压:tar -xzvf xxx.tar.gz
  • 查看端口占用:netstat -anp | grep 80

apche 和 nginx 的优缺

nginx轻量级,比apache占用更少的内存及资源,抗并发
nginx处理请求是异步非阻塞的,而apache 则是阻塞型的,在高并发下nginx 能保持低资源低消耗高性能。
apache 相对于nginx 的优点:rewrite比nginx 的rewrite 强大,少bug,稳定。(需要性能用nginx,求稳定就apache)

memcache或redis雪崩如何解决?

1.先启动缓存,再启动数据库。
2.加锁,防止memcache或redis挂掉,所有请求在mysql处理

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

CSRF(Cross-site request forgery):跨站请求伪造,
防范措施:
1.使用验证码
2.给每一个请求添加令牌 token 并验证

XSS(Cross Site Scripting):跨站脚本攻击
防范措施:对用户输入的数据的过滤

大厂面试题

2019年360工程师面试题

https://www.cnblogs.com/993089249a/p/11613099.html

2019年京东工程师面试题

https://www.cnblogs.com/993089249a/p/11613404.html

2019年新浪工程师面试题

https://www.cnblogs.com/993089249a/p/11613195.html

2019年搜狐工程师面试题

https://www.cnblogs.com/993089249a/p/11613149.html

2019年小米工程师面试题

https://www.cnblogs.com/993089249a/p/11613044.html

2019年滴滴工程师面试题

https://www.cnblogs.com/993089249a/p/11612844.html

2019年阿里工程师面试题

https://www.cnblogs.com/993089249a/p/11612726.html

2019年腾讯工程师面试题

https://www.cnblogs.com/993089249a/p/11608039.html

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值