I've found already Own SuperGlobal Variable in PHP?
here it says that there is no way to somehow define/use a "server variable" that would be same for different users/sessions. But since few years has passed may be something has changed? And now such would be possible?
Basically I want to run a php script triggered by user event, but I don't want to run more often then e.g. once per 30mins. So my frst thought was keep a "server side var (that is visibles for all sessions/clients)" and if user trigger the event (e.g. open some page) check if script been running last 30 mins then just open the page, if no then before opening page e.g. purge outdated/passed things.
Yes I do understand I can do workaround with mySQL etc... but why to do workaroud if PHP would support what I need.
Thank you in advance!
A regular PHP variable cannot be persisted beyond the current execution of the script. Once a script ends, all its variables are gone. That's the basic nature of PHP; in fact it's the basic nature of all computer programs, it's just that PHP is typically always terminated very quickly. To persist data beyond a single script invocation, you have several options where to store that data:
a database
a file
shared memory (though this may be purged at any time)
a memory cache like memcached (basically an in-memory database server)
run a persistent PHP script and communicate with it via sockets (basically a memcache)
don't terminate your script, write it as a daemon
Nothing of this has changed recently.
Related
I have an AJAX script that takes about 10 minutes to do its thing. I would like to be able to tell the user 'Hey listen, the task is being completed, we'll let you know how it turns out', but it won't let the user run any other scripts on the server until that one completes (I believe this is a consequence of PHP being single threaded, but I'm not sure). Is there a way to assign that AJAX script to a separate PHP or Apache process, so that the user can continue to click around in the application without having to wait for the task to finish?
You can use database or files to insert some lock mechanism to prevent task from running multiple times simultaneously. Then you need to just spawn PHP process using command nohup (no hang up), for more details look at this article: https://nsaunders.wordpress.com/2007/01/12/running-a-background-process-in-php/ or this question: nohup: run PHP process in background .
I seek for hours, at least, the solution was very easy for me using Cron Jobs. In cPanel you can go to Advanced -> Cron Jobs, and there schedule a task using a PHP script in Command line.
A Command example that execute a script php:
/usr/bin/wget http://www.example.com/miscript.php
or better:
php /home/USER/public_html/miscript.php
Are you using PHP sessions? If so, then a likely cause is that the long-running script keeps the session locked until it finishes. Any other request trying to access that same session will have to wait until the first one is done (usually it'll exceed request timeouts).
To fix that you'll need session_write_close():
Session data is usually stored after your script terminated without the need to call session_write_close(), but as session data is locked to prevent concurrent writes only one script may operate on a session at any time. When using framesets together with sessions you will experience the frames loading one by one due to this locking. You can reduce the time needed to load all the frames by ending the session as soon as all changes to session variables are done.
So simply call that function right around where you tell the user hey ya gotta wait. If you need (read) access to session variables later on in that script, consider storing them in local variables, then close the session immediately afterwards before moving on to whatever's taking a long time. If you need write access you could try re-running session_start() at the end, but if the session is currently locked elsewhere it'll have the same blocking problem. You could work around that by e.g. storing something in the database from the background script and fetching it from the regular user session, for example.
I want to have my own variable that would be (most likely an array) storing what my php application is up to right now.
The application can trigger few processes that are in background (like downloading files) and I want to have a list what is being currently processed.
For example
if php calls exec() that will be downloading for 15mins
and then another download starts
and another download starts
then if I access my application I want to be able to see that 3 downloads are in process. If none of them finished yet.
Can do that? Only in memory, not storing anything on the disk?
I thought that the solution would be a some kind of server variable.
PHP doesn't have knowledge of previous processes. As soon has a php process is finished everything it knows about itself goes with it.
I can think of two options. Write knowledge about spawned processes to a file or database and use it to sync all your php request, (store the PID of each spawned process)
Or
Create an Daemon. The people behind PHP have worked hard to clean up PHP memory handling and such to make this more feasible. Take a look at their PEAR package - http://pear.php.net/package/System_Daemon
Off the top of my head, a quick architecture would compose of 3 peices
Part A) The web app that will take in request for downloads, and report back the progress of all request
Part B) You daemon, which accepts requests for downloads, spawns process, and will report back status of all spawned reqeust
Part C) The spawn request that will perform the download you need.
Anyone for shared memory?
Obviously you would have to have some sort of daemon, but you could use the inbuilt semaphore functions to easily have contact between each of the scripts. You need to be careful though because sometimes if you're not closing the memory block properly, you could risk ending up with no blocks left.
You can't store your own variables in $_SERVER. The best method would be to store your data in a database where and query/update it as required.
I am looking for the PHP equivalent for VB doevents.
I have written a realtime analysis package in VB and used doevents to release to the operating system.
Doevents allows me to stay in memory and run continuously without filling up memory and allows me to respond to user input.
I have rewritten the package in PHP and I am looking for that same doevents feature.
If it doesn't exist I could reschedule myself and exit.
But I currently don't know how to do that and I think that would add a lot more overhead.
Thank you, gerardg
usleep is what you are looking for.. Delays program execution for the given number of micro seconds
http://php.net/manual/en/function.usleep.php
It's been almost 10 years since I last wrote anything in VB and as I recall, doevents() function allowed the application to yield to the processor during intensive processing (usually to allow other system events to fire - the most common being WM_PAINT so that your UI won't appear hung).
I don't think PHP has such functionality - your script will run as a single process and end (either when it's done or when it hits the default 30 second timeout).
If you are thinking in terms of threads (as most Windows programmers tend to do) and needing to spawn more than 1 instance of your script, perhaps you should take look at PHP's Process Control functions as a start.
I'm not entirely sure which aspects of doevents you're looking to emulate, so here's pretty much everything that could be useful for you.
You can use ob_implicit_flush(true) at the top of your script to enable implicit output buffer flushing. That means that whenever your script calls echo or print or whatever you use to display stuff, PHP will automatically send it all to the user's browser. You could also just use ob_flush() after each call to display something, which acts more like Application.DoEvents() in VB with regards to keeping your UI active, but must be called each time something is output.
Naturally if your script uses the output buffer already, you could build a copy of the buffer before flushing, with ob_get_contents().
If you need to allow the script to run for more time than usual, you can set a longer tiemout with set_time_limit($time). If you need more memory, and you have access to edit your .htaccess file, place the following code and edit the value:
php_value memory_limit 64M
That sets the memory limit to 64 megabytes.
For running multiple scripts at once, you can use pcntl_exec to start another one running.
If I am missing something important about DoEvents(), let me know and I will try to help you make it work.
PHP is designed for asynchronous on demand processing. However it can be forced to become a background task with a little hackery.
As PHP is running as a single thread you do not have to worry about letting the CPU do other things as that is already taken care of. If this was not the case then a web server would only be able to serve up one page at a time and all other requests would have to sit in a queue. You will need to write some sort of look that never expires until some detectable condition happens (like the "now please exit" message you set in the DB or something).
As pointed out by others you will need to set_time_limit($something); with perhaps usleep stopping the code from running "too fast" if it eats very much CPU each loop. However if you are also using a Database connection most of your script time is actually the script waiting for the Database (by far the biggest overhead for a script).
I have seen PHP worker threads created by using screen and detatching it to a background task. Other approaches also work so long as you do not have a session that will time out or exit (say when the web browser is closed). A cron that starts a script to check if the script is running every x mins or hours gives you automatic recovery from forced exists and/or system restarts.
TL;DR: doevents is "baked in" to PHP and you don't have to worry about it.
I'm trying to use ajax to make multiple simultaneous requests to a php script, however, it only seems to do 1 instance at a time and I cannot connect to do the next call until the previous one is finished. What do I have to do in order to make it do them all at the same time? I'm using apache (xampp) on windows. I've also tested this on my unix server and the same thing is happening there as well.
In theory, there is nothing preventing one PHP script from being executed several times in parallel -- else, a lot of websites would have big problems ;-)
So, there is probably, in your situation, some locking mecanism that prevents this...
If your script is using sessions, and those are file-based (which is the default), those sessions could cause that kind of problem : with the default session handler, it's not possible to have several files accessing the same session data (i.e. the session data that corresponds to a given user) at the same time ; that's to prevent one script from overriding the data of another, and should probably not be disabled.
So, if your script is using sessions : would it be OK for you to stop using sessions ?
If not, you should try to close them as soon as you don't need them -- to unlock the files that are used to store them.
Here's a quote from the manual page of session_write_close, about that :
Session data is usually stored after
your script terminated without the
need to call session_write_close(),
but as session data is locked to
prevent concurrent writes only one
script may operate on a session at any
time. When using framesets
together with sessions you will
experience the frames loading one by
one due to this locking. You can
reduce the time needed to load all the
frames by ending the session as soon
as all changes to session variables
are done.
if one web user is entering my php site and interacts with it then this php file will open one process (with one thread) and then after the php file is finnished with the logic and sent the output to the browser then the process is closed?
cause if it wasnt closed then it would mean that the values in the variables in that php file will be undeleted right? but since you always have to initialize new variables with values it means that the process is closed?
i just thought about this cause in a traditional desktop application i think the process doesn´t close unless you shut it down.
PHP is REQUEST driven. The interaction of a web server is as you described.
The REQUEST comes in to the server
Apache (example) creates a thread for the php executable
Your PHP script(s) are fired up, variables are init'd
Your script(s) complete execution, variables die
Apache cleans up
Your get a RESPONSE from the server
Yes, a desktop application and a php script running on a server are very different in those terms.
It depends on the configuration. For example, if php is running as FastCGI, the process will not be closed and will keep running waiting for a new request.
Regardless of the configuration though you can be sure of one thing: all the variables/etc will be uninitialized when the script ends, so you (the programmer) don't have to worry about this. Regardless of the configuration and whether the process closes or not it will behave the same.