分类 PHP 下的文章

PHP自定义session处理方法,保存到MySQL数据库中

我们都知道,session是为了解决因特网的无状态属性而创造出来的。我们可以用session这种会话管理机制来构建购物车、监控站点网络访问,甚至还可以跟踪某一个用户具体是如何使用你的应用的。PHP默认的session处理行为已经能应付大部分的场景,但有时候我们还是希望能够主动一点来控制session的处理方式,比如存储到数据库中而不是文件系统。下面我将以保存session到MySQL数据库给大家讲解如何自定义session处理方法。

解构session存储

在我们开始构建自己的session处理及存储方法之前,理解PHP默认如何存储session数据是很有帮助的。session数据被保存在服务器上一个很小的文件中,并关联了一个唯一的ID,随后被浏览器以cookie的形式保存在客户端。如果cookie没被起用,那么ID就会随着URL被当做参数进行传递。无论是哪种方式,在随后的请求中,PHP都是通过这个唯一的ID对session数据进行读取、更新或者删除等操作。为了便于理解这是怎么一回事,我们可以先从session数据保存的位置开始分析。对于文件形式保存的session数据,可以通过检查php.ini中的session.save_path得知,也可以用session_save_path()函数进行输出,如:

<?php
echo session_save_path();

输出结果就是session数据保存的位置。如果你想更改存储位置,可以修改php.ini配置,或者执行session_save_path()函数,参数就是新的存储路径。

session_save_path("/path/to/session/data");
最佳实践:如果你自定义了session存储路径,那么建议把路径选择在网站根目录之外,这样可以最大限度避免非法获取session数据。当然,你需要保证PHP程序能够正常读写session文件。

现在我们已经知道了session数据存储在哪,那我们就很容易找到对应当前访问的session文件。session文件的命名以“sess_”为前缀,加上唯一的ID。session_id()可以获取唯一ID值(是32位的字符串)。文件内容是以类似serialize()函数编码的方式处理过的数据。

提醒:无论session是保存在默认路径,还是自定义路径或数据库中,内容都是一样的。我们能改变的是存储位置,而不是存储的内容。

session的生命周期

所有的session从session_start()开始,session文件被打开,数据已数组的形势保存在$_SESSION变量中。当脚本执行完成之后,数据又被重新保存到session文件中。所以,当你设置了一个session值的时候,它并不是马上就会进行存储的。但是,你可以通过执行session_write_close()函数强制进行session数据的保存。

session_set_save_handler() 函数提供了自定义session数据存储的机制。它需要个参数,每个参数都是一个可回调的函数,对应了session生命周期的每个阶段:

  1. 打开session文件open
  2. 关闭session文件close
  3. 读取session数据read
  4. 写入session数据write
  5. 销毁session destroy
  6. 垃圾回收 gc

    PHP5.4之后,可以只传递两个参数,第一个参数是实现了SessionHandlerInterface接口的对象,第二个参数控制是否将函数 session_write_close() 注册为 register_shutdown_function() 函数。

- 阅读剩余部分 -

PHP新增、删除xml节点

假设有如下xml文件(/path/to/index.xml):

<?xml version="1.0" encoding="utf-8"?>
<sitemapindex>
    <sitemap>
        <loc>100.xml</loc>
        <lastmod>2020-05-06</lastmod>
    </sitemap>
    <sitemap>
        <loc>101.xml</loc>
        <lastmod>2020-05-06</lastmod>
    </sitemap>
    <sitemap>
        <loc>102.xml</loc>
        <lastmod>2020-05-06</lastmod>
    </sitemap>
</sitemapindex>

新增loc为103.xml的节点

使用SimpleXMLaddChild方法:

$xml = simplexml_load_file("/path/to/index.xml");
$sitemap = $xml->addChild('sitemap');
$sitemap->addChild('loc', '103.xml');
$sitemap->addChild('lastmod', '2020-05-07');
echo $xml->asXML();

- 阅读剩余部分 -

浏览器自动请求favicon导致重新访问一次主程序

语言:PHP
问题描述:自己写了一套程序实现简单的伪静态,就是将所有请求重定向到index.php,然后根据URI分发给不同的脚本处理。但运行起来发现,index.php总是比预想的多执行了一遍。

开始,自己以为是程序哪个地方出了问题,所以从头到尾检查,结果并没发现不合理的地方。最后没办法了,通过浏览器的network查看是不是访问时多发送了一次请求。
这一看就找到原因了:浏览器自动请求favicon.ico文件,但网站根目录不存在此文件,所以会重定向给index.php处理,于是主程序又背地里被执行了一遍。于是,我在伪静态里把类似的静态文件给排除掉了,无论找不找得到,都不会触发程序执行。

- 阅读剩余部分 -

ThinkPHP5.1 如何连接sqlite3数据库

TP5.1可以给模块进行单独配置,包括模板、数据库等。在不影响其他模块的前提下,我尝试给一个新的模块配置sqlite数据库,具体配置如下:

// 由于sqlite数据库是以文件保存的,所以我在网站根目录新建了db目录
return [
    'type' => 'sqlite',
    'dsn'  => 'sqlite:' . Env::get('root_path') . 'db/mynewdb.db',
    // 'charset' => 'utf8',
    'prefix' => 'b2b_'
];

开始时我犯了一个错误,受ezSQL的影响,dsn被我错误的写成:

'dsn'  => 'sqlite3:' . Env::get('root_path') . 'db/mynewdb.db',

结果,程序报错could not find driver

希望TP官方能够提供多几种数据库的连接实例。

PHP 301跳转

为了普通网民浏览网站的习惯,以及便于提升网站权重,有时候需要把不带www的顶级域名跳转到带www的二级域名,下面以csensix.com 为例讲解如何通过PHP实现301跳转。

$request_uri = isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : '';
if($_SERVER['HTTP_HOST'] == 'csensix.com')
{
    header('HTTP/1.1 301 Moved Permanently');
    header('Location: http://www.csensix.com' . $request_uri);
}