深度实现session【包括session入库、session机制和session和cookie的使用方法,完善会话机制(在分布式机器中也能使用)】、无限分类的实现

1.session的注意点:
@session_start();//这个配置需要注意,session开启中会有影响,所以使用错误抑制符进行限制【并且使用php.ini对session进行自动开启】

session_start()前的输出问题:
【session信息本身会增加到http头信息,也就是http主体不能在头前】
对php.ini中的输出缓存进行配置,out_buffer的配置【注意:开启之后能够保证输出内容在脚本中缓存】

【注意】
(1)脚本中session变量的键只能是字符串类型的【$_SESSION[10]这样是错误的,因为session本身是需要进行序列化】
(2)如果不声明session_start()的话,$_SESSION变量就相当于一个普通数组进行操作【与session文件不进行交互】
(3)不能unset来删除$_SESSION来删除所有session变量,而是通过将session设置为空来实现【unset只是将读取出来的session数据销毁,对session文件的数据无影响】
(4)删除session文件【session_destory()实现对session文件的销毁】【只删除文件,不会对$_SESSION变量进行处理】【一旦执行session_destory操作,不会再执行session写操作,即使有session变量存在】
【注意完全删除一个session:将与当前session相关的数据完全销毁之后,再删除文件以及sessionID(在cookie中)的删除】
【完全删除session需要考虑的就是会话机制本身】

2.session的存储处理
session.save_path进行session文件的路径修改

当请求变多之后,session文件会变多,此时如何管理?
通过session.save_path进行多级子目录进行管理【根据sessionID进行分级管理】

sessionID的形成算法:hash【session.hash_bits_per_character = 5(这里表示第一级子目录总共有2^5=32种分别为0-9,a-v)】

session文件的管理还是有问题:
文件量大,管理不方便
难共享【分布式的服务器的管理问题】

解决方案:将session数据放入数据库服务器中进行保存管理【将session入库的处理】


3.session入库
将session机制中读文件和写文件的机制,通过数据库进行介入管理。
【设置一个公共类进行session入口的所有方法】

session_set_save_handle();//函数的使用,结合session的机制,进行调用指定的方法
这个方法的使用,按照一定的顺序进行规范调用。
//关于session的文件创建(入库不需要文件创建)和需要session读写等操作的机制还是session自身的机制【所以需要使用指定的session函数:session_set_save_handle以及内部的方法要具体实现】
【相当于实现了一个注册函数,结合php内部机制实现session的入库操作(只是入库将session机制本身需要创建的文件,改为对数据库的操作)】
session入库本身就是讲原本要写入文本中的数据,写入数据库中【从而解决了session文本太过多,难以管理】


设计存入数据库表内的数据的格式【数据类型,因为sessionID本身就是唯一或者主键形式的】


【注意】
【对session的入库操作需要单独进行封装,不过也不需要感觉太难,就是不使用session对文件处理的机制,对文件的写文件等机制进行session_set_save_handle重写(保存session基本机制(对session处理的时机不变),只有读写针对的情景不一样),将session对文件的处理移到数据库读写来提升性能】
session_set_save_handle:执行的顺序需要注意
对open和close的方法进行初始化和析构处理

4.session的垃圾回收
session里的gc函数实现session的垃圾回收【因为session的垃圾回收比脚本要特殊,脚本结束,php垃圾回收,但是session需要先写数据,然后再释放】

如果session入库之后,由于session中保存的没有用的sessionID也需要进行回收,这也属于session的垃圾回收
【如何判断是否失效的原则】
cookie中如果sessionID失效,也会导致session内的ID失效(cookie中保存sessionID被刷新,那么服务器上保存的id再也找不到对应的id,此时服务器上的id便后失效)【失效sessionID其实出现的次数非常多】
php处理sessionID是否是垃圾的原则:php认为某条ID多长时间不使用,来判断是否是垃圾【垃圾回收基于时间:默认1440s,通过php配置进行修改】


session.gc相关的配置都是关于session的垃圾处理【每当开启session_start()都会有概率进行垃圾回收】
【session_start()会进行垃圾回收的查找,但是只是有几率进行gc垃圾回收,这也是为了提升性能。因为并不是,每次session_start都会实现一次gc垃圾处理】
【用mysql入库的数据内进行时间来判断垃圾回收的处理机制:这里的处理机制更加容易控制】


【session_set_save_handle:执行的顺序有合理性,删除在读取之后,能够保证即使过期还是可以正常读取(有可能)】

【重点!!!】
【使用入库之后处理session的顺序需要自己对session处理的机制】
(1)session_start()。首先进行open【操作初始化】
(2)执行read,进行读取
(3)有可能执行gc垃圾回收
(4)在脚本执行过程中时,会针对session变量和有可能执行session_destory
(5)脚本执行完成,如果没有执行session_destory,那么就会执行一个write操作
(6)脚本执行完成后,进行close操作

以上就是把session在脚本中执行的顺序


5.session中常见的问题
(1)session和cookie的区别和联系
存储位置,安全级别。二者的联系也是sessionID
(2)session数据的有效期
浏览器关闭。
请求中的cookie保存的sessionID失效【默认中的sessionID的cookie变量是一个临时变量】
【这一点要注意,如果没有将cookie中的sessionID进行持久化,那么重新开启一个浏览器,就相当于重新获得一个sessionID】
(3)由问题2带来一个问题:如何持久化session。【同一个用户的再次开启同一个浏览器的话,能够获得同一个sessionID】
延长cookie变量的有效期【持久化sessionID的cookie变量】
至于session本身的保留跟session的持久化只是一部分
【只有cookie中关于sessionID做到持久化,session中保留的数据才有意义】
【不过服务器端对session保存的时间的长短也要和cookie中设置的sessionID的时间要统一】


session_set_cookie_params();//这个函数的使用
setcookie();//两个函数都正常


(4)cookie禁用,session并不能用【url传递sessionID并不安全】
session.use_only_cookie:进行session使用的配置


以上就是session的所有问题

6.设计列表:分类管理【重点】
无限分类【一级一级的分类下去:用于头部或者对层级深度的不同进行一级级展示】
树状列表【各级节点:节点关系由数据表进行关联】
【n个节点(数据),n-1条边(数据关系:通过一个字段来实现关联)】
实现无限分类

【重点】
如何将关联的数据进行联系【数据库实现上下级的关联创建!!!】
【sql语句的查找是关键:sql将该节点上的值取出来和任何节点中判断父节点的值,将结果进行返回即可实现】

在插入数据时的配置也需要对类id和关联id进行对应添加,这一点也是创建分类时的关键


【重点】
利用递归实现无限分类
【一次性获取所有的数据,将数据进行递归查找】【节省数据库开销】
这一点思路要注意【虽然表示sql语句中进行条件判断的思路比较容易整理,但是通过这样的一次性操作,然后对数组进行分组之后进行无线分类显示能够实现功能】
【只要有这个对数组操作的思路即可实现递归,递归的一级级的判断依据就是父id是否等于子数据中的关联id,来进行递归】
【递归点和递归出口时递归需要注意的重点,而这个无线分类的递归其实更加简单,只要针对条件进行递归即可,不需要有递归出口】
【递归中需要共享所有递归的结果放在一个容器中,所以需要使用静态变量来做数组容器】


例子:
<?php


//一:
mysql_connect('127.0.0.1:3306', 'root', '123456');
$sql = "select * from itcast_shop.it_category where 1 order by sort_order";
$result = mysql_query($sql);
while($row = mysql_fetch_assoc($result)) {
$list[] = $row;
}
echo '<pre>';
//var_dump($list);


//二,递归查找
/**
*
* @param $arr array 当前所有的可能分类,在该数组内查找子分类
* @param $p_id int 当前查找的父ID
*
* @param $deep int 当前递归调用的深度
*
* @return array 排序好的数组列表!
*/
function getTree($arr, $p_id, $deep=0) {
//利用一个静态局部变量将所有依次找到的元素,都保存
static $tree = array();
//遍历所有的可能分类,找到parent_id==$p_id
foreach($arr as $row) {
//判断是否为子分类
if($row['parent_id'] == $p_id) {
//是子分类
//记录当前所找到
$row['deep'] = $deep;
$tree[] = $row;
//利用当前查找的分类,找其子分类
//递归调用
getTree($arr, $row['cat_id'], $deep+1);
}
}

return $tree;
}

$tree = getTree($list, 0);

//var_dump($tree);

foreach($tree as $row) {
echo $row['deep'];
echo str_repeat('&nbsp;&nbsp;', $row['deep']);//将一个字符串重复
echo $row['cat_name'];
echo '<br>';
}

以上实现了递归调用的方法【重点递归的实现和递归的容器需要考虑静态变量来实现】

原文地址:https://www.cnblogs.com/shuoshuren/p/4231857.html