我应该如何在 PHP 中实现延迟会话创建?

2024-04-03

默认情况下,PHP 的会话处理机制会设置会话 cookie 标头并存储会话,即使会话中没有数据也是如此。如果会话中没有设置数据,那么我不想要Set-Cookie在响应中发送到客户端的标头,我不希望在服务器上存储空会话记录。如果数据添加到$_SESSION,那么正常行为应该继续。

我的目标是实现 Drupal 7 和压力流 https://launchpad.net/pressflow除非将数据添加到其中,否则不会存储会话(或发送会话 cookie 标头)$_SESSION应用程序执行期间的数组。此行为的目的是允许反向代理,例如Varnish http://varnish-cache.org/缓存和服务匿名流量,同时让经过身份验证的请求传递到 Apache/PHP。 Varnish(或另一个代理服务器)被配置为传递任何没有 cookie 的请求,正确地假设如果 cookie 存在,则该请求是针对特定客户端的。

我已经从 Pressflow 移植了使用的会话处理代码session_set_save_handler()并覆盖执行session_write()检查中的数据$_SESSION保存之前将其保存为数组,并将其写为库,并在此处添加答案(如果这是最佳/唯一的路线)。

我的问题:虽然我可以实现完全自定义session_set_save_handler()系统,是否有一种更简单的方法可以以相对通用的方式获得这种惰性会话创建行为,即透明的对于大多数应用程序?


好吧,一种选择是使用会话类来启动/停止/存储会话中的数据。所以,你可以这样做:

class Session implements ArrayAccess {
    protected $closed = false;
    protected $data = array();
    protected $name = 'mySessionName';
    protected $started = false;

    protected function __construct() {
        if (isset($_COOKIE[$this->name])) $this->start();
        $this->data = $_SESSION;
    }

    public static function initialize() {
        if (is_object($_SESSION)) return $_SESSION;
        $_SESSION = new Session();
        register_shutdown_function(array($_SESSION, 'close'));
        return $_SESSION;
    }

    public function close() {
        if ($this->closed) return false;
        if (!$this->started) {
            $_SESSION = array();
        } else {
            $_SESSION = $this->data;
        }
        session_write_close();
        $this->started = false;
        $this->closed = true;
    }

    public function offsetExists($offset) { 
        return isset($this->data[$offset]); 
    }

    public function offsetGet($offset) {
        if (!isset($this->data[$offset])) {
            throw new OutOfBoundsException('Key does not exist');
        }
        return $this->data[$offset]; 
    }

    public function offsetSet($offset, $value) {
        $this->set($offset, $value);
    }

    public function offsetUnset($offset) {
        if (isset($this->data[$offset])) unset($this->data[$offset]);
    }

    public function set($key, $value) {
        if (!$this->started) $this->start();
        $this->data[$key] = $value;
    }

    public function start() {
        session_name($this->name);
        session_start();
        $this->started = true;
    }
}

在脚本调用开始时使用Session::initialize()。它将用对象替换 $_SESSION ,并设置延迟加载。之后,你可以这样做

$_SESSION['user_id'] = 1;

如果会话未启动,它将启动,并且 user_id 键将设置为 1。如果在任何时候您想关闭(提交)会话,只需调用$_SESSION->close().

您可能想要添加一些更多的会话管理功能(例如 destroy、regenerate_id、更改会话名称的能力等),但这应该实现您想要的基本功能...

它不是一个 save_handler,它只是一个管理会话的类。如果你真的愿意,你可以在类中实现 ArrayAccess,并在构造时用该类替换 $_SESSION (这样做的好处是,遗留代码仍然可以像以前一样使用会话,而无需调用$session->setData())。唯一的缺点是我不确定 PHP 使用的序列化例程是否可以正常工作(您需要在某个时候将数组放回到 $_SESSION 中......可能使用register_shutdown_function()...

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

我应该如何在 PHP 中实现延迟会话创建? 的相关文章

  • 通过身份验证保护 CodeIgniter 2 应用程序的正确方法是什么?

    I have Ion Auth http benedmunds com ion auth 正确安装并在我的服务器上运行 我也有默认的代码点火器2 新闻 教程在同一个 CI 安装中工作 我只是在玩 并对使用身份验证系统 封闭 或保护整个应用程
  • 使用 MYSQL 将 h:mm pm/am 时间格式插入数据库

    我正在尝试将以 h mm am pm 格式写入的时间插入到存储为标准 DATETIME 格式 hh mm ss 的数据库中 但我不知道如何将发布的时间转换为标准格式所以数据库会接受它 这是我到目前为止一直在尝试的 title POST in
  • if/else 简写来定义变量

    我很难理解 if else 的 php 简写是如何描述的here https stackoverflow com questions 20233207 php if shorthand and echo in one line possib
  • 使用 ImageMagick (PHP) 将 2 个图像并排合并为 1 个图像

    我认为这是一件容易的事 我有 2 张图片 JPG 我希望它们合并成一张图片 其中 2 张图片并排 所以我有图片 A 和图片 B 我想要图片 AB 并排 两个图像具有相同的宽度和高度 在本例中 宽度 200px 高度 300px 但是第二个图
  • Readfile 从大文件中读取 0 字节?

    我正在尝试通过以下方式发送一个大文件readfile 但是 没有任何内容发送到浏览器 并且readfile 回报0 not false 我尝试发送的文件大小为 4GiB 并且可由 PHP 读取 我正在设置set time limit 0 以
  • 使用 ImageMagick 和 PHP 将 PNG 转换为 JPG 并将透明背景设置为白色

    将图像从 PNG 转换为 JPEG 时 如何使用 ImageMagick 带有 php 扩展 将透明背景设置为白色 在撰写本文时 您尚未指定正在使用哪个扩展 但如果您使用命令行 则命令将是 convert image png backgro
  • get url 重定向时 File_get_contents() 不起作用

    我正在使用的功能是 function http post url data data url http build query data data len strlen data url date default timezone set
  • 使用 PHP Selenium Webdriver 单击下拉菜单中的选项?

    我正在使用 PHP Selenium Webdriver 包装器Facebook https github com facebook php webdriver 任何人都可以给我一个如何单击或从选择下拉菜单中选择选项的示例吗 我已经尝试过这
  • 从类似 cronjob 的语法创建“下次运行时间”日期

    在我正在创建的应用程序中 用户可以安排重复任务 生成间隔模式的简单值是 Minute 0 59 90 each minute Hour 0 23 90 each hour Day of month 1 31 90 each day of m
  • 获取字符串中的最后一个整数

    我需要隔离包含多个整数的字符串中最新出现的整数 我怎样才能得到23代替1 for lastnum1 text 1 out of 23 lastnum1 this gt getEval eregi replace out of text 你可
  • 通过 URL 指定控制器类与为每个控制器编写一个脚本相比,有何优缺点?

    今年夏天我安装了两个不同的 PHP 系统 每个都使用两种不同的方法 方法 1 每个任务一个 PHP 文件 该方法需要一个PHP为每个主要任务创建文件 例如 我的上传脚本可以通过http www domain com upload php O
  • 如何纠正这个非法字符串偏移?

    我收到此错误 警告 第 32 行 home mysite public html wp content themes evento lib php extra class php 中的非法字符串偏移 type 我意识到文件中的这部分代码是错
  • 对 SimpleXML 数据进行排序和分组

    我正在对 XML 文件中的出版物数据进行排序和分组 我目前使用的方法效果很好大部分情况下 尽管我觉得有一种更有效的方法来完成我想要完成的任务 以下是目标节点的示例
  • 在 WooCommerce 中添加到购物车之前清空购物车

    我正在使用 WP 作业管理器和 Woo Subscriptions Now 最初 我选择了一个套餐 Woo Subscription 然后我添加了所有细节 但没有提交 回到网站 所以要再次购买 我需要选择一个套餐 于是我选择了套餐并填写了详
  • 重写 URL,将 ID 替换为查询字符串中的标题

    我对 mod rewrite 很陌生 但我做了一些搜索 但找不到这个问题的答案 我有一个网站 它只有一个 PHP 页面 根据查询字符串中传递给它的 ID 提供数十页内容 我想重写 URL 以便此 ID消失并替换为从数据库中提取的页面标题 例
  • PHP print_r() 中 _r 的含义是什么?

    我见过这个答案 https stackoverflow com questions 13103410 what does r suffix mean就这样 但我不确定它对于 PHP 是否相同 如果是 可重入的含义是什么 From PHP n
  • 从所有会话中注销

    我有一个注销选项 这是我的代码 session start session destroy setcookie key time 60 60 24 setcookie username time 60 60 24 我想添加另一个选项来注销所
  • 我可以在 PHP 会话变量中安全地存储用户名和密码吗?

    我想在 REST api 之上制作一个轻量级的 web 应用程序 用户只需进行一次身份验证 从那时起 所有针对 web api 的请求都希望通过以某种方式保持用户名和密码有效来完成 我已经做了一个工作原型我在哪里将用户名和密码存储在会话变量
  • 如何从 Laravel 执行存储过程

    我需要在表单提交数据后执行存储过程 我让存储过程按照我想要的方式工作 并且我的表单正常工作 我只是不知道从 laravel 5 执行 sp 的语句 它应该是这样的 执行 my stored procedure 但我似乎在网上找不到类似的东西
  • 使用 PHP 将 latin1_swedish_ci 转换为 utf8

    我有一个数据库 里面充满了类似的值 Dhaka 应该是 Dhaka 因为我在创建数据库时没有指定排序规则 现在我想修复它 我无法从最初获取数据的地方再次获取数据 所以我在想是否可以在 php 脚本中获取数据并将其转换为正确的字符 我已将数据

随机推荐

  • 在 IIS 7.5 上部署 ASP.NET MVC 应用程序时出现“未配置默认文档”错误

    开发 ASp NET MVC 5 应用程序 在开发计算机 Windows 7 x86 上运行没有问题 当我尝试在 IIS 7 5 Win Server 2008 R2 64 位 上部署它时 出现 3 个错误 无法识别的属性 targetFr
  • codeigniter 中的 is_unique 用于编辑功能

    我有要求 我可以在新的添加函数中对唯一值进行验证 例如 this gt form validation gt set rules email Email required valid email is unique users Email
  • Elasticsearch 多词过滤器

    我对 Elasticsearch 还很陌生 所以这是我的问题 我想用 elasticsearch 进行搜索查询并想用多个术语进行过滤 如果我想搜索用户 tom 那么我希望获得用户 isActive 1 isPrivate 0 和 isOwn
  • JavaScript 绘图库? [关闭]

    Closed 此问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 对于 JavaScript 交互式绘图库有什么建议吗 只需要绘制不同颜色的线条 多边形 文字即可 兼容
  • 类实例上元类的方法

    我想知道在元类上声明的方法会发生什么情况 我预计 如果您在元类上声明一个方法 它将最终成为一个类方法 但是 行为是不同的 例子 gt gt gt class A object classmethod def foo cls print fo
  • 目前Mono虚拟机的性能如何?

    网络上充斥着不同语言 编译器 虚拟机的各种性能测试 然而 几乎没有任何一个使用真实场景来测试性能 此外 在 Google 上搜索此类基准通常只会产生几年前的基准 因为这些基准有最多的时间来收集它们的链接 你们中有人真正了解不同虚拟机的当前性
  • 使用 antd 在组件中创建子菜单失败

    我正在使用 antd 3 5 4 我有一个包含用户管理项目的菜单 未登录时 菜单有一个带有登录页面链接的菜单项 登录后 菜单有一个子菜单 其中包含多个链接 包括注销 我只是对连接的用户进行简单的测试以显示链接或子菜单 当所有内容都在同一个文
  • 方案/球拍:画布操作

    1 正如标题所述 当我调整窗口大小时 我绘制的对象消失 但矩形保持原样 2 原点从左上角开始 但我希望它在左下角 3 除了绘图库之外 我找不到任何缩放功能 所以如果我希望实现这样的功能 一个选项是通过绘制更大的对象并刷新画布来 缩放 def
  • 使用 FileUpload 过滤文件扩展名

    我正在编写一个 ASP NET Web 应用程序 其中涉及使用FileUpload控制 此刻 这个特殊的FileUpload控件仅需要 zip 或 gz 文件类型 如果上传的文件类型不正确 则会向用户显示错误消息 该功能已经实现 我想要做的
  • Windows Phone 8.1 中的信标 - 没有可能性吗?

    首先 是的 我已经阅读了所有其他类似的问题 其次 我正在开发应用程序 WP 8 1 WinRT 它必须使用信标 我读了很多相关内容 我知道 如果不先配对 通常无法与 BLE 设备连接 但希望最后会破灭 所以我想问一下我有什么可能性 可以在代
  • 一次上传两个文件

    我正在尝试使用 codeigniters 上传类一次上传两个文件 两个文件字段 尽管提供了字段名称 codeigniter 仍会在第二个字段上产生错误 这是 codeigniter php 或 html 的限制 还是我只是错误地使用了该类
  • $concat mongodb 中的两个字段

    我有这两个集合 employees id NumberInt 0 name Max surname Power and loggableUser id NumberInt 0 employee NumberInt 1 现在我必须在以下查询中
  • 如何以递归方式将 React 组件渲染到自身中

    我有一个组件 即列表组件 列表组件可以渲染项目 通过组件ListItem 通过下面的内容可以轻松实现 import React from react import ListItem from list item list item clas
  • 如何使用 FastAPI 防止表单输入时页面重新加载

    我有一个使用 FastAPI 的简单程序 它将浮点值乘以 2 并将其显示在 HTML 中 该值通过 HTML 表单输入 我想知道如何获得动态显示的值 而无需在按 Enter 或按提交按钮时重新加载页面 以下是脚本 main py 和 dou
  • 在 C# 中用点和小数格式化数字[关闭]

    Closed 这个问题需要细节或清晰度 help closed questions 目前不接受答案 我需要先 点 然后逗号 例如 1234567 这是一个数字或金钱的示例 我想要像 1 234 567 00 谁能给我答案 如果执行代码的计算
  • Gcc 卸载编译选项

    我正在尝试使用 Ubuntu 18 04 上的 gcc 10 CUDA 11 和此 CMakeLists txt 文件 或 OpenMP 版本 构建最简单的具有 GPU 卸载功能的 OpenMP 或 OpenACC C 程序 cmake m
  • 下载的php总是损坏

    我有一个用 PHP 编写的下载脚本 我的视图文件脚本链接到 ids 然后选择与该 ID 匹配的所有数据 然后使用该数据下载照片 我的照片在文件夹中重要吗 它被移动到一个文件夹 然后该目录被上传到MYSQL数据库 目前的代码现在允许一些文件完
  • Python3,与列表重新匹配

    我读到了这个 https stackoverflow com a 17090205 6426449 https stackoverflow com a 17090205 6426449 我制作了一个不能在 django 中的用户名上使用的列
  • 在 WSL (Ubuntu) 中安装适用于 python3 的 venv

    我正在尝试配置venv在带有 Ubuntu 的 Linux 的 Windows 子系统上 我尝试过的 1 安装venv通过pip pip3 准确地说 pip3 install venv 我收到以下错误 ERROR Could not fin
  • 我应该如何在 PHP 中实现延迟会话创建?

    默认情况下 PHP 的会话处理机制会设置会话 cookie 标头并存储会话 即使会话中没有数据也是如此 如果会话中没有设置数据 那么我不想要Set Cookie在响应中发送到客户端的标头 我不希望在服务器上存储空会话记录 如果数据添加到 S