7

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.
Community
  • 1
  • 1
Simon Forsberg
  • 13,086
  • 10
  • 64
  • 108
  • 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 ... –  Jun 05 '12 at 20:51
  • 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. – Marius Solbakken Mellum Jun 05 '12 at 20:54
  • 3
    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. – Mike Jun 05 '12 at 20:54
  • 2
    This is not possible. However, you may be able to avoid it entirely by modifying your design. – netcoder Jun 05 '12 at 20:56
  • 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.) @Mike I do actually already have multiple possible servers so that can absolutely be done. I do like that way. – Simon Forsberg Jun 05 '12 at 21:09
  • @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". – Simon Forsberg Jun 05 '12 at 21:13
  • @netcoder 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? – Simon Forsberg Jun 05 '12 at 21:17
  • @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. – netcoder Jun 05 '12 at 21:19
  • You could do such thing in PHP using some hacks and leveraging AOP. – tonix May 21 '19 at 17:01
  • @tonix 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. – Simon Forsberg May 21 '19 at 20:08

7 Answers7

9

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.

webbiedave
  • 48,414
  • 8
  • 88
  • 101
  • Many thanks. Just for curiousity: Would it have been possible to redefine a function? – Simon Forsberg Jun 05 '12 at 21:27
  • @SimonAndréForsberg: You can redefine lambdas at runtime. This is what I was referring to in my comment about prototype-based programming. – netcoder Jun 06 '12 at 19:15
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.

richardhsu
  • 878
  • 5
  • 13
  • Check out Erlang for a language and runtime with support for hot loading of code in a running program. – Emil Vikström Jun 05 '12 at 21:08
  • This video comes into my mind as well, not really sure how it works but it is pretty cool: http://www.wimp.com/videogames/ – Simon Forsberg Jun 05 '12 at 21:21
  • 1
    @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. – richardhsu Jun 05 '12 at 22:29
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.

David Harkness
  • 35,992
  • 10
  • 112
  • 134
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.

  • Ok, now you completely lost me... APC?? Just checked it a little on http://www.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.. – Simon Forsberg Jun 05 '12 at 21:24
  • It seems to only store data, I don't understand how this could be used for changing the code? – Simon Forsberg Jun 05 '12 at 21:34
  • 1
    See this link: http://devzone.zend.com/1812/using-apc-with-php/ Go to the part where it says define functions on the fly. –  Jun 05 '12 at 21:37
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

Steween
  • 354
  • 2
  • 6
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).

Walter Tross
  • 12,237
  • 2
  • 40
  • 64
-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?

Ionel Lupu
  • 2,695
  • 6
  • 29
  • 53