前两天出去面试了,结果让我有点意外,我居然跪在了很简单的几道基础题上,使用框架开发项目时间久了,果然就如当时在学校老师说的那样,基础全忘光了,写项目的业务模块倒是熟练了很多,反而把最基本的东西忘的一干二净,刚好最近找工作也要复习,不如就把面试中遇到的面试题自己做一个详解,同时根据问到的知识点进行一个相关知识点的补充。
飞飞当时给我说过一句话挺有趣的,“面试一万个人然后招一个人,你最后没有面试上,就是自己太菜,不用管自己在那9999个人里面排多少位,这不重要,重要的是,你不是第一。”虽然这句话看起来说的有一些绝对,但还是有一些道理的,菜就是菜,慢慢补呗。
写出Session与Cookie区别
考点:PHP会话控制技术
为什么需要会话控制技术?
HTTP是无状态协议,没有一个内建机制维护两个事物之间的状态。同一个用户请求两次HTTP请求时,HTTP协议不会认为这两次请求都来自同一个用户,会当成两个独立的请求来处理。也就没有办法保持用户的登陆状态,所以会话控制技术的核心思想是 允许客户端跟踪服务端做出的连续请求 ,从而完成登陆状态的保持。
Cookie: 服务器发送给客户端的片段信息, 存储在客户端浏览器的内存或硬盘中的一种技术。
-
写Cookie:setcookie(name,value,expire,path,domain,secure) -
name:Cookie名称,可以使用 ‘a[b]’ -
value:Cookie值 -
expire:Unix时间戳,以秒为单位,如果不设置,则在浏览器关闭时过期 -
path:有效服务器路径,设置为 ‘/’ 时,对整个域名domain有效,如果设置为 ‘/foo/’ ,则仅对domain中/foo/目录及其子目录有效(例如:/foo/ban/) -
domain:Cookie的有效域名/子域名,设置成子域名(例如:’www.example.com’ ),会使Cookie对这子域名和他的三级域名有效(例如:w2.www.example.com)。要让Cookie对整个域名有效,设置顶级域名就行了(例如:example.com) -
读取Cookie:$_COOKIE -
删除Cookie:setcookie(name,”,time()-1) ,把Cookie设为过期即可
Cookie优缺点:
优点: 存储在客户端不会浪费服务器资源
缺点: 由于数据存储在客户端,不建议将一些敏感重要的数据使用Cookie存储。客户端有权限禁用掉Cookie的使用。
Session: 将用户的数据 存储在服务器 当中,用户无法禁止掉Session使用,但 Session不是完全脱离Cookie的 。Session是通过服务器客户端Cookie带过来的SESSIONID来确定用户数据的,如果Cookie被禁用,需要通过URL传递SESSIONID的形式保存SESSION的状态。
Session的使用
-
开启Session: session_start()
-
使用Session: $_SESSION
直接操作SESSION数组就可以 -
清空Session: $_SESSION=[]
或$_SESSION = null
-
删除Session(包括文件和Cookie): session_destroy()
Session的配置 php.ini
文件
-
session.auto_start
是否自动开启Session -
session.cookie_domain
设置Session的有效域名 -
session.cookie_lifetime
设置的cookie有效时间,是从创建了这个cookie时开始计算,不会因为操作而刷新 -
session.cookit_path
设置session有效服务器路径 -
session.name
存储在客户端的Cookit的名称, -
session.save_path
设置session在服务器存储路径 -
session.use_cookies
是否使用Cookie传递session -
session.use_trans_sid
是否允许SESSIONID通过URL明文传输 -
session.gc_probability
清理多少次垃圾 -
session.gc_divisor
每访问多少次 -
session.gc_maxlifetime
设置的session的最大生命周期 -
session.save_handler
设置存储方式,可以存储到Redis中或MySQL中,默认是’files’类型,即文件存储
Session垃圾回收机制
Session是存储在服务器上的,如果用户没有走退出程序而是直接关闭掉了浏览器,则Session文件会永久的保存在服务器上,时间长了会撑满内存,这个适合就需要使用Session的垃圾回收机制,大概流程是这样的:
-
当用户长时间没有再次访问Session,比如刷新、修改、添加等操作(时间根据: session.gc_maxlifetime
设置的秒数,默认1440,PHP5默认1500),超过这个时间 则Session将会被设为过期的“垃圾文件” -
当Session被设置为垃圾文件时,PHP每被请求设定次数 (次数根据: session.gc_divisor
设置的次数,默认1000),清除设定个数文件(session.gc_probability
默认是1次,也就是说每访问1000次清空一个过期文件),不建议把清除次数设置的特别小,会消耗服务器资源
优点: 数据存储在服务器,相比Cookie比较更安全。
缺点: 占用服务器资源,如果垃圾回收机制设置不合理,会撑满服务器硬盘。
Cookie被禁用时如何传递SESSIONID
<!-- 使用session_name()和session_id()传递 -->
<a href="<?php%20echo%20session_name().'='.session_id()?>">下一个页面</a>
<!-- 使用SID常量传递,SID比较智能,比较推荐使用这个-->
<!-- 在Cookie开启的时候,值为空,Cookie禁用的时候才会输出 -->
<a href="<?php%20echo%20SID?>">下一个页面</a>
Session存储共享(Redis/MySQL/Memcache)
如果需要使用多台服务器的话,直接将Session存储到其中一台服务器的时候,可能下次访问的时候就是另一台服务器了,这种情况下Session因为不能共享的原因会导致用户的Session信息无法共享在其他的服务器上。这时需要使用 session_set_save_handler
设置用户自定义会话存储函数。
写出下列代码输出结果
<?php
var_dump(empty($a));
var_dump(isset($a));
var_dump(is_null($a));
empty($a)
输出 bool(true)
, 判断一个变量是否为空,当变量不存在时,或它的值等同于false时,那么它就会被认为不存在, empty() 并不会产生警告 , empty() 本质上与 !isset(var == false 等价
isset($a)
输出 bool(fasle)
,判断变量是否设置且非NULL,使用 unset() 释放变量后,使用 isset() 结果为false。isset() 可以传递多个变量,只有当所有变量都被设置时才会返回TRUE,计算过程从左往右,中途遇到没有设置的变量则不会继续往后计算。is_null($a)
输出 bool(true)
,检测变量是否为NULL,以下三种情况变量被认为是NULL:
-
赋值为NULL -
尚未被复制 (只是被声明了) -
被 unset() 掉的变量
使用正则验证邮箱的正确性
我写的面试答案:[0-9a-zA-Z]+@[0-9a-zA-Z]{2,}.[0-9a-zA-Z]{2,4}
太久不用正则的原因导致我写的这个正则,用到是能用,但是写的过于繁琐,还有就是小部分情况下无法验证。错误: 使用.
的时候需要转义,否则匹配不到 “.” 会出现错误
改良后的写法:^w+@w{2,}.w{2,4}$
正则表达式的所用:分割
查找
匹配
替换
关于正则的用法补充:
-
分隔符 -
/
正斜线 -
#
hash符号 -
~
取反符号 -
通用原子 -
d
十进制的0-9 -
D
除了十进制的0-9,可以理解为d
取反 -
w
数字字母下划线 -
W
除了数字字母下划线,可理解为w
取反 -
s
空白字符(空格) -
S
除了空白字符,可理解为s
取反 -
元字符 -
.
除了换行符以外的任意字符 -
*
匹配前面的内容,零次、一次、多次 -
?
匹配前面的内容,零次、一次 -
^
必须以此开头 -
$
必须以此结尾 -
+
出现一次或多次 -
{n}
只能出现N次 -
{n,}
至少出现N次 -
{n,m}
至少出现N次,最多出现M次 -
[]
或,比如[123]
表示 1或2或3 -
()
表示一个整体 -
[^123]
表示 除了1 除了2 除了3 -
|
表示或的意思 -
[-]
范围值,例如[0-9]
-
模式修正符 -
i
不区分大小写 -
m
每一行分别匹配 -
s
修正换行符,如果有换行符就需要使用这个修正,否则匹配不上 -
U
取消贪婪模式 -
x
忽略模式中的空白字符 -
A
必须以这个模式开头 -
D
修正对n
的忽略 -
u
utf-8编码,中文匹配时有用
补充一些常用正则规则:
-
验证手机号: ^1[3456789]d{9}$
-
验证身份证号: ^d{17}[dxX]$
设计一个无限级分类表,并写出查询代码
什么是无限级分类?
无限分类就是在一个分类下面可以创建多个子类,而其子类下面同样可以创建不同子类,如此往复,没有终点。
使用无限分类一个可以做分类的下拉列表,也可以做分类的面包屑导航。
以父ID实现的无限分类
使用递归算法。表中一个字段id,一个字段pid(父ID),这样可以根据WHERE id = pid 来查出上一层内容,运用递归至顶层。
表名:cate
字段名 | 类型 |
---|---|
id | int(11) 主键索引 无符号 |
pid | int(11) 无符号 父级id,根据这个判断父级是谁 |
title | var_char() 分类名称 |
代码实现:
<?php
$dsn="mysql:host=127.0.0.1;port=3306;dbname=test;charset=utf8mb4;";
$pdo=new PDO($dsn,'root','root');
$sql='SELECT * FROM `cate` Order BY pid';
$result=$pdo->query($sql,PDO::FETCH_OBJ);
$categories =[];
// 循环结果集 按照层级拼
foreach($result as $value){
$categories[$value->pid][]=$value;
}
$tree=[];
// 拼接树形结构
function catetree($categories,$n){
global $tree;
// 如果由子类再循环
if(isset($categories[$n])){
foreach($categories[$n] as $category){
// 几层就输出几个
$tree[] = '├'.str_repeat('-',$n).$category->title;
catetree($categories,$category->id);
}
}
}
// 调用函数
catetree($categories,0);
// 输出结果
var_dump($tree);
/**
array (size=10)
0 => string '├新闻' (length=9)
1 => string '├-国内新闻' (length=16)
2 => string '├---北京新闻' (length=18)
3 => string '├-国际新闻' (length=16)
4 => string '├----美国新闻' (length=19)
5 => string '├图片' (length=9)
6 => string '├--风景图片' (length=17)
7 => string '├--美女图片' (length=17)
8 => string '├-------日韩明星' (length=22)
9 => string '├---------日本电影' (length=24)
**/
?>
MySQL的InnoDB和MyISAM引擎区别,分别适合那些场景?
-
InooDB引擎 -
支持事务,性能优秀 -
数据存储在共享表空间,可通过配置分开 -
对于主键查询性能高于其他引擎 -
读取数据时自动在内存构建Hash索引,插入数据时自动构建插入缓冲区 -
通过一些机制和工具支持真正的热备份 -
支持崩溃后的安全恢复 -
支持行级锁,但没有命中索引的情况下依然会使用表锁 -
支持外键 -
MyISAM引擎 -
5.1版本之前MyISAM引擎是默认的存储引擎 -
拥有全文索引、空间函数和压缩 -
不支持事务和行级锁,不支持崩溃后的安全恢复 -
表存储的两个文件MYD和MTI -
设计简单,在某些场景下性能会很好
InnoDB 适用场景: 需要事务的操作;更新数据需要使用行级锁;大数据量读写。
MyISAM适用场景: 不需要事务的操作;批量插入快;更新少;统计和读取频繁。
Redis常用类型,分别适合那些场景
String(字符串)
特点:字符串的一个常见用途就是用来缓存用户信息,我们将用户信息结构体使用JSON序列化成字符串,然后将序列化后的字符串塞进Redis来缓存,取用户信息的时候再经过一次反序列化过程。
Hash(哈希)
特点:Hash是一个键值对(K/V)合集,特别适合用于存储对象。
相比字符串序列化的存储信息更加直观。更新和获取数据时不需要像字符串那样全部取出来,只需要取出或者写入需要的部分即可。但是哈希结构的存储消耗高于单个字符串。
list(列表)
特点:简单的字符串列表,按照插入的顺序进行排序
列表结构将常被用来做异步队列使用,将需要延后处理的任务结构体序列化成字符串,塞进Redis的列表,另一个线程通过轮询对列表中的数据进行处理。
set(集合)
特点:set是String的无序合集,和列表不同的是合集中不允许有重复的元素
集合适合用来存储某些活动的用户ID,因为有去重功能,可以保证同一个用户不会中奖两次。
黑名单/白名单功能,sismember
命令可以方便的判断这个条件是否存在于黑名单/白名单之中
zset(有序集合)
特点:保留了set中不允许有重复元素的特点,但不同的是Zset是可以排序的,与列表的索引下标作为排序依据不同,Zset可以给每个元素设置一个数字,作为排序依据。
适合用来做排行榜这类的功能,比如:
-
粉丝列表,根据粉丝关注时间来排序 -
热搜榜单:根据热搜点击次数来排序 -
成绩榜单:根据学生的成绩分数排序
写出冒泡排序
冒泡排序很简单,就直接上代码吧
<?php
function Bubble(Array $arr){
$length=count($arr) - 1;
for ($i=0; $i < $length; $i++) {
for ($j=0; $j < $length; $j++) {
if($arr[$j] > $arr[$j+1]){
$temp=$arr[$j];
$arr[$j]=$arr[$j+1];
$arr[$j+1]=$temp;
}
}
}
return $arr;
}
// 设置一个数组
$arr=[5,3,6,8,1,2,4,9,7];
var_dump(Bubble($arr));
原文始发于微信公众号(两双筷子):一个菜鸡的PHP面试题解
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/78516.html