脚本运行时是否可以动态重新加载PHP代码?

时间:2012-06-05 20:47:02

标签: php reload multiplayer

我正在使用一台使用PHPSockets的多人游戏服务器,因此完全用PHP编写。

目前,每当我对PHP服务器脚本进行任何更改时,我都必须终止该脚本,然后重新启动它。这意味着任何在线用户都会断开连接(通常不是问题,因为目前没有这么多)。

现在我正在重写服务器脚本以使用自定义PHP类并对其进行一些排序(你不想知道它今天看起来多么讨厌)。今天我在想:“如果不重新启动整个脚本,是不是可以对php源进行更改?”。

例如,我计划有一个包含main.php的{​​{1}}文件,其中包含类user.phpMyUser,其中包含类game.php }。 现在让我们说我想更改MyGame并“重新加载”服务器,以便user.php的更改生效,而不会断开任何在线用户的连接?

我试图找到解决这个问题的其他问题,我得到的最接近的问题是Modifying a running script and having it reload without killing it (php),但这似乎并不能解决在线用户的断线问题。

更新

我自己的解决方案是:

  1. 在特殊情况下,请包含文件external.php,该文件可以访问一些变量并使用它们。执行此操作时,我必须确保代码中没有错误,因为如果我尝试访问不存在的方法,整个服务器都会崩溃。
  2. 将整个事情重写为Java ,这使我有可能使用动态类重新加载添加插件系统。奇迹般有效。再见PHP。

7 个答案:

答案 0 :(得分:8)

  

如果不重新启动整个脚本,是否应该可以更改php源?

     

[...]

     

我打算使用一个包含user.php的main.php文件   其中包含MyUser类

在你的情况下,你不能。类只能在正在运行的脚本中定义一次。您需要重新启动脚本才能重新定义这些类。

答案 1 :(得分:2)

我对PHP不太熟悉,但我会假设创建了一个运行脚本的进程,这样做会复制运行程序所需的指令并开始在CPU上执行,在此期间,如果你是“更新”指令,你需要杀死进程终极并重新启动它。包含是一种将类和文件链接在一起的奇特方式,但最终处理器将这些信息与存储文件的位置分开,并且在重新启动过程之前最终会有所不同。

我不知道您可以在哪个系统中创建代码并主动编辑它,并在运行该代码时查看更改。大多数活动程序需要重新启动才能重新加载新的源代码。

答案 2 :(得分:2)

Runkit将允许您在运行时添加,删除和重新定义方法(以及其他内容)。虽然您无法更改类或其现有实例的已定义属性,但它允许您更改这些对象的行为。

我不建议将其作为永久性解决方案,但在开发过程中可能会有用。最终,您需要将游戏状态存储到文件,数据库Memcache

答案 3 :(得分:0)

您不能include再次使用相同class的文件,但可以使用array执行此操作。如果您确实需要,也可以从array转换为class。这仅适用于数据,而不适用于行为(方法)。

答案 4 :(得分:0)

当主脚本从缓存加载时,如何将用户对象存储到APC缓存中,并经常检查新的操作码。

要在缓存中包含某个功能,您必须包含SuperClosure Class。一个例子是:

if (!apc_exists('area')) {
  // simple closure
  // calculates area given length and width
  $area = new SuperClosure(
    function($length, $width) {
      return $length * $width;
    }
  );
  apc_store('area', $area);
  echo 'Added closure to cache.';
} else {
  $func = apc_fetch('area');
  echo 'Retrieved closure from cache. ';
  echo 'The area of a 6x5 polygon is: ' . $func(6,5);
}

See here for a tutorial on APC

答案 5 :(得分:0)

简单的解决方案使用$ MyUser而不是MyUser

require MyUserV1.php;
$MyUser = 'MyUserV1';
$oldUser = new $MyUser('your name');
//Some time after
require MyUserV2.php;
$MyUser = 'MyUserV2';
$newUser = new $MyUser('your name');

每个声明的类都保留在内存中,但在最后一次MyUserV1注销时变为未使用 你可以让它们从一个抽象类MyUser继承来使用is_a

答案 6 :(得分:-1)

我对PC上的游戏了解不多,但您可以尝试从用户的数据库中获取所有变量,然后使用这些变量更新文本字段或按钮

在网络中使用AJAX(在不刷新页面的情况下更改数据)。不是编程的吗?