如何用PHP实现会话同步?

我正在用PHP开发WebApp。用户单击一个按钮,PHP代码就可以调用系统执行程序。由于WebApp使用AJAX,因此用户有可能单击两次按钮,或者实际上单击另一个按钮启动另一个exec进程。 我知道我可以编写一些JavaScript来禁用按钮,直到单个事件完成为止。但是,客户端强制执行很容易被覆盖。 PHP方面是否可以做一些事情来阻止这种事情的发生? 我有一个想法,让会话变量充当“信号量”,并且在执行每个脚本之前检查此变量,并且必须返回0才能继续脚本。 这样做正确吗?

You could use jQuery.ajax() and set the option async to false:

async Default: true By default, all requests are sent asynchronously (i.e. this is set to true by default). If you need synchronous requests, set this option to false. Cross-domain requests and dataType: "jsonp" requests do not support synchronous operation. Note that synchronous requests may temporarily lock the browser, disabling any actions while the request is active

You could use it like this:

$.ajax({
    type: "POST",
    url: "file.php",
    async: false,
    data: data,
    success: function(return){
        alert("Success: "+return);
    }
});

If you want to add a loader just apply it as:

startLoader();
$.ajax({
    type: "POST",
    url: "file.php",
    async: false,
    data: data,
    success: function(return){
        alert("Success: "+return);
    }
});
endLoader();

However you PHP idea is simply not a good one. Opening a session and do all the process for this kind of thing is just useless and slow your script down. You should be asking yourself: Do I really need to block this?

If the answer is yes then do this: Create a table called processes in you database. Inside that table create 2 fields: One will be the process identifier: process_id; the second will be the process status: process_status. The first is an integer you will define with sha1(IMAGE). The second will be an integer: 1 for "busy", 0 for "free".

Then you could do something like this:

SELECT process_status FROM vps_processes WHERE process_id = sha1(CURRENT_IMAGE);

And check whatever it is 1 or 0. If it is 1 then block the script; If it is 0 then you query:

UPDATE vps_processes SET process_status = 1 WHERE process_id = sha1(CURRENT_IMAGE);

then run what you have to run and at the end of the script query:

UPDATE vps_processes SET process_status = 0 WHERE process_id = sha1(CURRENT_IMAGE);

The fact that you want it to be a server-side solution makes me suspect that you don't trust the user here. Then you obviously can't use the session structure since that's also possible to circumvent by the client. Instead, you'll have to lock the single IP address or some similar approach. Maybe have a folder with lock files, where you create a file named after the IP performing the request.

Unless you want to enforce the per-user limit between different machines, you could always use http://php.net/manual/en/function.flock.php to lock the operation on a file called lock.$username

Alternatively, you could simply not care about enforcing the limit, since there are only limited number of php processes that are going to run at the same time anyways.