Is it possible to dynamically reload PHP code while script is running?
Asked Answered
B

7

8

I'm having a multiplayer server that's using PHPSockets, and thus is written entirely in PHP.

Currently, whenever I'm making any changes to the PHP server-script I have to kill the script and then start it over again. This means that any users online is disconnected (normally not a problem because there aren't so many at the moment).

Now I am rewriting the server-script to use custom PHP classes and sorten things up a little bit (you don't want to know how nasty it looks today). Today I was thinking: "Shouldn't it be possible to make changes to the php source without having to restart the whole script?".

For example, I'm planning on having a main.php file that is including user.php which contains the class MyUser and game.php which contains the class MyGame. Now let's say that I would like to make a change to user.php and "reload" the server so that the changes to user.php goes into effect, without disconnecting any online users?

I tried to find other questions that answered this, the closest I got is this question: Modifying a running script and having it reload without killing it (php) , which however doesn't seem to solve the disconnection of online users.

UPDATE

My own solutions to this were:

  1. At special occations, include the file external.php, which can access a few variables and use them however it'd like. When doing this, I had to make sure that there were no errors in the code as the whole server would crash if I tried accessing a method that did not exist.
  2. Rewrite the whole thing to Java, which gave me the possibility of adding a plugin system using dynamic class reloading. Works like a charm. Bye bye PHP.
Burnout answered 5/6, 2012 at 20:47 Comment(10)
I would generally store modifiable "config" information in a language agnostic format like an XML file and modify that. Then it should be a simple method call to reload the config file and an asset written in Java or Python (for example) can easily manipulate the server from the outside as well. As for dynamically changing the source code of a program? That seems like a bad idea in the first place ...Wilmer
I think what you should really be lookin' at is whether you really need one socket per player or if you can make the game more statefull instead. Thus instead of having an open connection from the client to the server, the client can send normal web requests. But I understand that would probably mean a total rewrite and is not an option at this point? Also, php does not support "undefining" classes, so if you have already defined class "Test", you cannot re-include a file to define class "Test" yet again.Siegbahn
I think for all online games I know, when the administrator wants to apply an update to the game files, the server is reloaded and people are disconnected. Perhaps it would be better to have an online version where all the users connect to and a testing version where only you (or a handful of select people) will connect to. When you want the changes to go live, you save them to the online version and restart the server. This means you won't have to restart the online version for every small change you want to make.Upend
This is not possible. However, you may be able to avoid it entirely by modifying your design.Bellyband
It's not for changing config, mainly to add new features/fix bugs (such as new commands, fix what happens when an user logs in, etc.) @Upend I do actually already have multiple possible servers so that can absolutely be done. I do like that way.Burnout
@MariusSolbakkenMellum the problem with no open connection is that the client does not know when something has happened for them. Luckily, I am running a turn-based game, but I do prefer that clients is told directly when something new has happened. Sending a whole bunch of web requests every now and then doesn't sound very efficient, as it would often happen that the server responds with "Nothing new".Burnout
@Bellyband suggestions for how to modify the design? Are you thinking about not using sockets at all and using "normal web requests" instead, or do you have something else in mind?Burnout
@SimonAndréForsberg: It depends on the nature of the changes and the current design of your application, it's hard to tell. Prototype-based programming is probably a good alternative here. That's what I would do. It's possible in 5.3, and a lot better in 5.4.Bellyband
You could do such thing in PHP using some hacks and leveraging AOP.Sheridansherie
@Sheridansherie You'd have to provide a little bit more details than that for that comment to be helpful. To me it doesn't matter anymore as I am doing things differently now (using Kotlin first and foremost), but you might have something that can be helpful to other readers.Burnout
C
10

Shouldn't it be possible to make changes to the php source without having to restart the whole script?

[...]

I'm planning on having a main.php file that is including user.php which contains the class MyUser

In your case, you can't. Classes can only be defined once within a running script. You would need to restart the script to have those classes redefined.

Clever answered 5/6, 2012 at 20:54 Comment(2)
Many thanks. Just for curiousity: Would it have been possible to redefine a function?Burnout
@SimonAndréForsberg: You can redefine lambdas at runtime. This is what I was referring to in my comment about prototype-based programming.Bellyband
S
3

I am not too familiar with PHP but I would assume that a process is created to run the script, in doing so it copies the instructions needed to run the program and begins execution on the CPU, during this, if you were to "update" the instructions, you'd need to kill the process ultimate and restart it. Includes are a fancy way of linking your classes and files together but ultimately the processor will have that information separate from where the file of them are stored and it is ultimately different until you restart the process.

I do not know of any system in which you can create code and actively edit it and see the changes while that code is being run. Most active programs require restart to reload new source code.

Shipp answered 5/6, 2012 at 20:55 Comment(3)
Check out Erlang for a language and runtime with support for hot loading of code in a running program.Torytoryism
This video comes into my mind as well, not really sure how it works but it is pretty cool: wimp.com/videogamesBurnout
@EmilVikström: That is very cool, I just looked into the hot swapping. It is an interesting idea but it still kind of requires a reload but I wonder how complicated it is for servers. Thanks I'll keep reading! (At Simon:) Yeah, I've seen that, I actually went to a talk of his before, but I think the structure of the framework would need to replay things and thus reload the code or do some fancy abstraction in which the program that is being used to do that editing and such expects variables to change and thus kind of already programs for that variability but yeah definitely awesome.Shipp
B
3

Runkit will allow you to add, remove, and redefine methods (among other things) at runtime. While you cannot change the defined properties of a class or its existing instances, it would allow you to change the behavior of those objects.

I don't recommend this as a permanent solution, but it might be useful during development. Eventually you'll want to store the game state to files, a database, Memcache, etc.

Brominate answered 5/6, 2012 at 21:4 Comment(0)
C
1

How about storing your User object into APC cache while your main script loads from the cache and checks every so often for new opcode.

To include a function in the cache, you must include the SuperClosure Class. An example would be:

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.

Chanellechaney answered 5/6, 2012 at 21:18 Comment(3)
Ok, now you completely lost me... APC?? Just checked it a little on php.net/manual/en/book.apc.php and it does look powerful. I doubt I will use it though, I don't think many would recommend it in my case..Burnout
It seems to only store data, I don't understand how this could be used for changing the code?Burnout
See this link: devzone.zend.com/1812/using-apc-with-php Go to the part where it says define functions on the fly.Chanellechaney
K
1

Simple solution use $MyUser instead of MyUser

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

Every declared class stay in memory but become unused when the last MyUserV1 logout
you can make them inherit from an abstract class MyUser for using is_a

Kucera answered 25/7, 2015 at 5:11 Comment(0)
F
0

You cannot include again a file with the same class, but you can do so with an array. You can also convert from array to class, if you really need to do so. This only applies to data, though, not to behavior (methods).

Freytag answered 5/6, 2012 at 21:7 Comment(1)
Yes, it's hard to write code into an array without using eval which would be very foolish. :)Burnout
L
-1

I don't know much about these things with the games on PC but you can try to get all the variables from your database for the user and then update the text fields or buttons using those variables

In web is using AJAX (change data without refreshing the page).Isn't one for programming?

Lollis answered 5/6, 2012 at 20:57 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.