Можно ли динамически перезагружать PHP-код во время работы скрипта?

у меня есть многопользовательский сервер, который использует PHPSockets и, таким образом, полностью написан на PHP.

в настоящее время, когда я делаю какие-либо изменения в PHP server-script, я должен убить скрипт, а затем запустить его снова. Это означает, что любые пользователи онлайн отключены (обычно это не проблема, потому что на данный момент их не так много).

теперь я переписываю сервер-скрипт, чтобы использовать пользовательские классы PHP и сортировать вещи немного (вы не хотите знаешь, как противно это выглядит сегодня). Сегодня я думал: "разве нельзя внести изменения в источник php без перезапуска всего скрипта?".

например, я планирую иметь main.php файл, который включает user.php, который содержит класс MyUser и game.php, который содержит класс MyGame. теперь предположим, что я хотел бы изменить user.php и "перезагрузить" сервер, чтобы изменения в user.php вступает в силу, без отключение каких-либо онлайн-пользователей?

Я попытался найти другие вопросы, которые ответили на это, ближе всего я получил этот вопрос:изменение запущенного скрипта и его перезагрузка без его убийства (php), что, однако, не решает проблему отключения онлайн-пользователей.

обновление

мои собственные решения этого были:

  1. в особых случаях включите файл external.php, к которому можно получить доступ несколько переменных и используйте их, как хотите. При этом я должен был убедиться, что в коде нет ошибок, так как весь сервер рухнет, если я попытаюсь получить доступ к несуществующему методу.
  2. перепишите все это на Java, что дало мне возможность добавить систему плагинов с использованием динамической перезагрузки классов. Работает как заклинание. Прощай РНР.

7 ответов


разве нельзя внести изменения в источник php без перезапуска всего скрипта?

[...]

Я планирую иметь main.php-файл, который включает пользователей.РНР который содержит класс MyUser

в вашем случае, вы не можете. Классы могут быть определены только один раз за выполнение скрипта. Вам нужно будет перезапустить скрипт, чтобы переопределить эти классы.


Я не слишком хорошо знаком с PHP, но я бы предположил, что процесс создан для запуска скрипта, при этом он копирует инструкции, необходимые для запуска программы, и начинает выполнение на CPU, во время этого, если бы вы "обновили" инструкции, вам нужно было бы убить процесс ultimate и перезапустить его. Включает в себя причудливый способ связывания ваших классов и файлов вместе, но в конечном итоге процессор будет иметь эту информацию отдельно от того, где файл из них хранится, и это в конечном счете разные, пока вы не перезапустить процесс.

Я не знаю ни одной системы, в которой вы можете создавать код и активно редактировать его и видеть изменения во время выполнения этого кода. Большинство активных программ требуют перезагрузки для перезагрузки нового исходного кода.


Runkit позволит вам добавлять, удалять и переопределять методы (среди прочего) во время выполнения. Хотя вы не можете изменить определенные свойства класса или существующих экземпляров, это позволит вам изменить поведение этих объектов.

Я не рекомендую это как постоянное решение, но это может быть полезно во время разработки. В конце концов, вы захотите сохранить состояние игры в файлах, базе данных,memcache для, etc.


нельзя include снова файл с тем же class, но вы можете сделать это с помощью array. Вы также можете конвертировать из array to class, Если вам действительно нужно сделать так. Это относится только к данным, но не к поведению (методам).


Как насчет хранения объекта пользователя в APC кэш в то время как ваш основной скрипт загружается из кэша и проверяет каждый так часто для нового кода операции.

чтобы включить функцию в кэш, необходимо включить Класс SuperClosure. Примером может служить:

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);
}

см. здесь учебник по APC.


простое решение используйте $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


Я не знаю много об этих вещах с играми на ПК, но вы можете попробовать, чтобы получить все переменные из базы данных для пользователя, а затем обновлять текстовые поля или кнопки, используя эти переменные

в web используется AJAX (изменение данных без обновления страницы).Не для программирования?