English 中文(简体)
How to persist objects between requests in PHP
原标题:

I ve been using rails, merb, django and asp.net mvc applications in the past. What they have common (that is relevant to the question) is that they have code that sets up the framework. This usually means creating objects and state that is persisted until the web server is recycled (like setting up routing, or checking which controllers are available, etc).

As far as I know PHP is more like a CGI script that gets compiled to some bytecode each time it s run, and after the request it s discarded. Of course you can have sessions, to persist data between requests from the same user, and as I see there are extensions like APC, with which you can persist objects between requests at the server level.

My question is: how can one create a PHP application that works like rails and such? I mean an application that on the first requests sets up the framework, then on the 2nd and later requests use the objects that are already set up. Is there some built in caching facility in mod_php? (for example that stores the compiled bytecode of the executed php applications) Or is using APC or some similar extensions the only way to solve this problem? How would you do it?

Thanks.

EDIT: Alternative question: if I create a large PHP application that has a very large set up time, but minor running time (like in the frameworks mentioned above) then how should I "cache" the things that are already set up (this might mean a lot of things, except for maybe the database connections, because for that you have persistent connections in PHP already).

To justify large set up time: what if I m using PHP reflection to check what objects are available and set the runtime according to that. Doing a lot of reflection is usually slow, but one has to do it only once (and re-evaluate only if the source code is modified).

EDIT2: It seems it s APC then. The fact that it caches bytecode automatically is good to know.

最佳回答

Not sure if APC is the only solution but APC does take care of all your issues.

First, your script will be compiled once with APC and the bytecode is stored in memory.

If you have something taking long time to setup, you can also cache it in APC as user data. For example, I do this all the time,

            $table = @apc_fetch(TABLE_KEY);

            if (!$table) {
                    $table = new Table(); // Take long time
                    apc_store(TABLE_KEY, $table);
            }

With APC, the task of creating table is only performed once per server instance.

问题回答

PHP (and ruby for that matter) are interpretive languages. That is they parse the files each time they are requested and I suppose you could say are converted to a pseudo byte code. It is more apparent one could say that PHP is more like this than say RoR but they both behave the same way.

The feature of persisting data between requests is a feature of the server not of the language itself. For example, the RoR routing you speak of is in fact cached but that s cached in the server s local memory. It isn t compiled and stored for faster readins. The server (and by server I mean both the box & the web service instances) restarts this information is gone. The setting up the framework you speak of still involves parsing EACH file involved in the framework. Rails parses each file during the request again and again, the production level features may in fact cache this data in memory but certainly in development it does not. The only reason I mention that is because it illustrates that it s a feature of the server not the language.

To achieve the same thing in PHP you could use Zend Server. As far as I know this is the only PHP interpreter that will compile and use byte code when told to. Otherwise you ll need to find a way to store the data you want to persist over requests. APC as you mentioned is a very powerful feature, a more distributed one is Memcached and then of course there s more persistent forms like disc & sql.

I am interested in knowing why you d like this particular feature. Are you noticing performance issues that would be solved by doing this?

I think you re making some incorrect generalizations. All of those frameworks (ex: Rails) can be run with different configurations. Under some, a process is created for every request. This obviously hurts performance, but it shows that these frameworks don t rely on a long-running process. They can set things up (reparse config files, create objects, etc.) every request if needed.

Of course, mod_php (the way PHP is usually used) runs inside the web server process, unlike CGI. So I don t see anything fundamentally different between CakePHP (for example) and Rails.

I think perhaps you are looking for something like Python s WSGI or Ruby s Rack, but for PHP. This specifies an interface (independent of how the language is run) for an application. For a new request, a new instance of an application object is created. As far as I know, this does not exist for PHP.

The most common way developers runs PHP is by configuring Apache with CGI module as an adapter in front of PHP. When Apache receives HTTP requests, verifies if a route matches to a PHP file/path, then it delegates the execution to an external module/program, in this case, the CGI module. Which will then delegate the processing to the PHP executable. A new PHP process is then started by CGI, passing request data along its parameters, and then PHP starts doing this job, which is to open PHP files, read them, validating and parsing, executing instructions line by line, until there are no more code to interpret. The response produced then is sent back to Apache and finally its process exits. Memory is returned back to OS, and then all of this pipeline happens over and over again, for every request.

Knowing this, we notice that if a process is started and terminated in every request, the state is not being preserved. Node.js for example, works by starting a single thread, read .js files, parses it, optimize it all once, and keeps itself running in memory. There is no process ending and starting (except when it crashes).

I dont know why the developers of the PHP/ Language have decided to follow this modularized approach for such a long time, they spent much effort in optimizing this architecture (it s very fast all this pipeline), but I know some companies evolved with different solutions, like Facebook, Zend.

By the way, my advice as a Senior Engineer is: Keep it simple, just apply a simple solution that everyone does, despite language/stack being used. Store application state in a dedicated space, like Redis cache, MySQL DB, etc. It s the more common solution to address the state management server applications. Applications doesnt have to depend on hold data/state in his memory space. It must be stored outside, and retrieved in every request. This brings us several benefits, including the most important in all computer programs: to share data on multiple processes running in parallel. The name of this feature is: Scalability. Write stateless applications





相关问题
Brute-force/DoS prevention in PHP [closed]

I am trying to write a script to prevent brute-force login attempts in a website I m building. The logic goes something like this: User sends login information. Check if username and password is ...

please can anyone check this while loop and if condition

<?php $con=mysql_connect("localhost","mts","mts"); if(!con) { die( unable to connect . mysql_error()); } mysql_select_db("mts",$con); /* date_default_timezone_set ("Asia/Calcutta"); $date = ...

定值美元

如何确认来自正确来源的数字。

Generating a drop down list of timezones with PHP

Most sites need some way to show the dates on the site in the users preferred timezone. Below are two lists that I found and then one method using the built in PHP DateTime class in PHP 5. I need ...

Text as watermarking in PHP

I want to create text as a watermark for an image. the water mark should have the following properties front: Impact color: white opacity: 31% Font style: regular, bold Bevel and Emboss size: 30 ...

How does php cast boolean variables?

How does php cast boolean variables? I was trying to save a boolean value to an array: $result["Users"]["is_login"] = true; but when I use debug the is_login value is blank. and when I do ...

热门标签