【问题标题】:Is there a way in PHP to use persistent data as in Java EE? (sharing objects between PHP threads) without session nor cache/DBPHP 中有没有办法像在 Java EE 中一样使用持久数据? (在 PHP 线程之间共享对象)没有会话也没有缓存/DB
【发布时间】:2013-02-11 17:46:28
【问题描述】:

在 PHP 中有没有办法使用“会话外”变量,这些变量不会像在 Java 服务器中那样在每次连接时都被加载/卸载?

请原谅我不够准确,我不知道如何正确地写它。

主要的想法是有这样的东西:

<?php
    ...
    // $variablesAlreadyLoaded is kind of "static" and shared between all PHP threads
    // No need to initialize/load/instantiate it.
    $myVar = $variablesAlreadyLoaded['aConstantValueForEveryone'];
    ...
?>

我已经使用shmop 和其他奇怪的东西做了这样的事情,但是如果在“纯 PHP”中有一种“干净”的方法可以在不使用缓存系统的情况下做到这一点(我认为 APC、Redis ......) ,也不是数据库。

编辑 1:

由于人们(感谢他们为我花时间)以同样的方式回答我的会话,我添加了一个我错过写的约束:请不要会话。

编辑 2:

似乎只有共享内存 (shmop) 和命名管道才能做到这一点。我会使用托管方式来访问共享对象,而不考虑内存管理(共享内存块大小)或系统问题(管道)。

然后,我在网上浏览了一个 PHP 模块/库,它提供了执行此操作的函数/方法:我什么也没找到。

编辑 3:

在对@KFO 指出的方式进行了一些研究之后,似乎putenv / setenv 不是用来处理对象的(我会避免序列化)。因此,它解决了诸如字符串或数字之类的短“事物”的问题,但不适用于更大/更复杂的对象。

使用“env 方式”和另一种方法来处理更大的对象会不连贯,并增加代码的复杂性和可维护性。

编辑 4:

发现这个:DBus (GREE Lab DBus),但我没有工具可以在工作中对其进行测试。有人测试过吗?

我愿意接受每一个建议。

谢谢

编辑 5(“答案”):

由于 DBus 并不是我想要的(需要安装第三方模块,没有“严重”的应用程序证据),我现在使用的 Memcache 已经证明了它的可靠性(在 @PeterM 评论之后,见下文)。

【问题讨论】:

  • 老实说,我以 memcache 结束了一些类似的问题
  • @PeterM :好的,写在屏幕上的便利贴上,但它不符合初始要求。
  • @ArjanTijms :感谢您修复了标题中的错误 :)
  • @Benj,你可以。 APCShmop stackoverflow.com/a/5605710/632951
  • @Pacerier,使用 Memcache 找到了解决方案

标签: php persistence share shared-memory inter-process-communicat


【解决方案1】:
// First page
session_id('same_session_id_for_all');
session_start();
$_SESSION['aConstantValueForEveryone'] = 'My Content';

// Second page
session_id('same_session_id_for_all');
session_start();
echo $_SESSION['aConstantValueForEveryone'];

这在 PHP 中是开箱即用的。使用相同的会话 id(而不是随机的用户唯一字符串)为所有访问者初始化会话会导致所有用户的会话都相同。


真的有必要使用会话来实现目标还是使用constants更好?

没有纯粹的 PHP 方式可以跨不同的共享信息 PHP中的线程!除了“外部” 文件/数据库/服务器变量/sessionfile 解决方案。


由于一些评论员指出,Session 数据的序列化/反序列化功能可能会破坏传输中的数据,因此有一个解决方案:在 PHP 中,可以根据需要配置序列化和反序列化功能serialize_handler。见https://www.php.net/manual/session.configuration.php#ini.session.serialize-handler 看看魔术类方法__sleep()__wakeup() 可能也很有趣,它们定义了对象在序列化或反序列化请求上的行为方式。 https://www.php.net/manual/language.oop5.magic.php#object.sleep ... 从 PHP 5.1 开始,还有一个预定义的 Serializable 接口可用:https://www.php.net/manual/class.serializable.php

【讨论】:

  • 同样的评论:我希望它能够以类似 Servlet 的方式独立于会话,用于每个 PHP 线程。此外,使用会话不是我想要的,因为它每次都序列化/反序列化数据。 // 见@PeterM 评论。
  • 我知道强制会话 ID,但这不是我想要的(写了“无需初始化/加载/实例化它”)。
  • 我更新了问题,感谢你,我看到了我想写的东西。
  • 好的,我明白了。没有纯粹的 PHP 方式可以在 PHP 中的不同线程之间共享信息!除了“外部”文件/数据库/服务器变量/会话文件解决方案。
  • 常量不是我想要的,对象必须是可变的(我知道同步问题)。
【解决方案2】:

另一种解决方案是将变量包装在“持久数据”类中,该类将在每次运行 php 脚本时自动恢复其数据内容。 您的班级需要满足以下条件:

  • 将变量的内容存储到__destructor的文件中
  • __constructor的文件中加载变量的内容

我更喜欢以 JSON 格式存储文件,以便可以轻松检查内容以进行调试,但这是可选的。

请注意,某些网络服务器会更改析构函数中的当前工作目录,因此您需要使用绝对路径。

【讨论】:

    【解决方案3】:

    您可以在 .htaccess 中声明一个变量。例如SetEnv APPLICATION_ENVIRONMENT production 并在您的应用程序中使用函数getenv('APPLICATION_ENVIRONMENT') 访问它

    【讨论】:

    • 似乎是一种有趣的方式。有性能问题吗?一些关于基准或什么的文档?
    • 如果您只使用 setenv 设置一个变量,则不会出现性能问题。但是如果你想配置你的完整应用程序,你最好创建一个配置文件(或类)并在每个请求上加载这个文件。
    • 这里是一些使用 env 选择配置的 zend 框架的用例:stackoverflow.com/questions/2510556/…
    • @KFO :“并在每个请求上加载此文件”不不不,男孩,我写了“不是在每个连接上都加载/卸载”。这非常重要;) setenv/getenv 的 +1
    • 你能解释一下,你的具体问题是什么?我不明白,为什么你只是创建一个新文件,写下你的所有设置并将这个文件包含到你的项目中。
    【解决方案4】:

    我认为您可以使用$_SESSION['aConstantValueForEveryone'],您可以在同一域的每个页面上阅读它。

    考虑引用它的manual

    【讨论】:

    • 我希望它能够以类似于 Servlet 的方式用于每个 PHP 线程,独立于会话。此外,使用会话不是我想要的,因为它每次都会序列化/反序列化数据。
    • @Benj 要求为 everyone 而非当前用户提供变量
    猜你喜欢
    • 1970-01-01
    • 2017-05-06
    • 2011-06-10
    • 1970-01-01
    • 2010-12-14
    • 1970-01-01
    • 2013-11-11
    • 2012-03-29
    • 2019-11-25
    相关资源
    最近更新 更多