Is there a way to prevent a code-block or a function within a code from running more than once even if I re-execute (or reload) the PHP file?
I mean, can I restrict someone from executing a php script more than once? I can't seem to find the way to do this.
Yes, you can use a $_SESSION variable to determine if the code has been executed. The session variable will be set until the user closes their browser. If you want to extend it further than that, you can set a cookie. Please see the following links for more details.
Session Variables
Cookies
If you are using sessions, then you can set a flag in the user's session array after the code has executed:
function doSomething(){
if (empty($_SESSION['completed'])){
//Do stuff here if it has not been executed.
}
$_SESSION['completed'] = TRUE;
}
You should also check the sesison variable to see if the task has been executed previously. This assumes that the user can accept a session cookie.
I have an app that does that.
What we did was create a table in the db called version, and stored a version number in there. When the script is ran, it compared the version number in the database with that in the php script. And perform whatever it needs to "upgrade" it to the new version, and then updates the version number in the database.
Of couse, if the version table does not exist, the code will create it and mark it as storing version zero.
Just put a counter in the function. If the counter is greater that 0, then don't do anything. The counter variable should be static so it "remembered" across multiple calls.
function sample() {
static $call_counter = 0;
if ( $call_counter>0 ) {
return;
}
...
$call_counter++;
}
As for making sure a file is only executed once, just use "include_once()" instead of "include()".
Related
I'm trying to stop the execution of an php script in runtime triggered by the user.
My planned approach is to make an ajax call to the server, setting a session variable which is then looked up by the first already running script every now and then to determine if the process should stop or continue running. Hope that makes sense:)
I already found some examples of people doing the same here or with files instead of sessions here.
Now my problem is that I would like to use the session for my approach instead of the solution doing it with temporary files and the mentioned approach with sessions doesn't seem to work for me in Laravel 9.
The result I'm looking for:
start first php script (runs maybe 30 seconds)
make ajax call to server & set session variable stop_execution = true
the first php script which is still running detects the change in stop_execution === true & stops execution.
The behaviour I get:
start first php script (runs maybe 30 seconds)
make ajax call to server & set session variable stop_execution = true
the first php script which is still running doesn't detect the change in stop_execution === true & runs until it finishes by itself.
the next time I run the first php script again it immediately detects the change in stop_execution === true & stops execution.
My thought on why this is happening is that the session variables doesn't get refreshed inside the first script after checking them for the first time. Maybe there is a way to force pull all new changes from the session variables while the first script is running? Did somebody have the same issues with Laravel? It seems like this is working with session variables when not using Laravel. I think it has something to do with Laravel and how the sessions are handled.
I would appreciate any advice 😊
Thanks a lot!
Code:
First script executed at the beginning
private function longRunningFunction()
{
// check session variable every iteration and exit while loop if === true
while ($condition === true && ! session('cancel_computation')) {
// do stuff ...
}
// reset session variable to false after finishing
session(['cancel_computation' => false]);
return $result;
}
Second script executed on ajax call
public function cancelComputationFunction()
{
// set session variable to be true
session(['cancel_computation' => true]);
}
I would not advice you to use sessions for this.
They are initialized on script start and I have never seen somebody re-fetch them in the same script.
Nor am I able to find such functionality when researching online.
What you could do though, is to utitlize the Cache facade.
It is very well suited for what you want and it very lightweight no matter which driver you choose to use under the hood in Laravel.
So instead of:
public function cancelComputationFunction()
{
// set session variable to be true
session(['cancel_computation' => true]);
}
You could do something like this:
public function cancelComputationFunction()
{
// set cache variable to be true
Cache::put('cancel_computation_' . session()->getId(), true);
}
And likewise inside the long-running part of the script.
How to make functions in PHP synchronized so that same function won't be executed concurrently ? 2nd user must wait till 1st user is done with the function. Then 2nd user can execute the function.
Thanks
This basically comes down to setting a flag somewhere that the function is locked and cannot be executed until the first caller returns from that function.
This can be done in a number of ways:
use a lock file (first function locks a file name "f.lok", second function checks if the lock file exists and executes or doesn't based on that evaluation)
set a flag in the database (not recomended)
use semaphores as #JvdBerg suggested (the fastest)
When coding concurrent application always beware of race conditions and deadlocks!
UPDATE
using semaphores (not tested):
<?php
define('SEM_KEY', 1000);
function noconcurrency() {
$semRes = sem_get(SEM_KEY, 1, 0666, 0); // get the resource for the semaphore
if(sem_acquire($semRes)) { // try to acquire the semaphore. this function will block until the sem will be available
// do the work
sem_release($semRes); // release the semaphore so other process can use it
}
}
PHP needs to be compiled with sysvsem support in order to use sem_* functions
Here's a more in depth tutorial for using semaphores in PHP:
http://www.re-cycledair.com/php-dark-arts-semaphores
You are looking for a Semaphore
Bear in mind that using a semaphore (or any other blocking mechanism) can have serious peformance issues, as the requests can not be handled while the semaphore is up.
off the top of my head:
function checks if a database field called isFunctionRunning is equal 1. if not start executing
you update the database field called isFunctionRunning to 1
function does magic here
you update the database field called isFunctionRunning to 0
but somehow i think what you are trying to do is "wrong" and can be achieved in another way. could help if you said more details
edit: wasn't aware of php semaphores, the answer above will be way faster.
You can use the "flock" (file locking) function with the "LOCK_EX" (exclusive lock) flag to create a custom "synchronized" function that accepts a handler to be synchronized.
You may may found the code here.
I hope this helps.
How to make functions in PHP synchronized so that same function won't be executed concurrently ? 2nd user must wait till 1st user is done with the function. Then 2nd user can execute the function.
Thanks
This basically comes down to setting a flag somewhere that the function is locked and cannot be executed until the first caller returns from that function.
This can be done in a number of ways:
use a lock file (first function locks a file name "f.lok", second function checks if the lock file exists and executes or doesn't based on that evaluation)
set a flag in the database (not recomended)
use semaphores as #JvdBerg suggested (the fastest)
When coding concurrent application always beware of race conditions and deadlocks!
UPDATE
using semaphores (not tested):
<?php
define('SEM_KEY', 1000);
function noconcurrency() {
$semRes = sem_get(SEM_KEY, 1, 0666, 0); // get the resource for the semaphore
if(sem_acquire($semRes)) { // try to acquire the semaphore. this function will block until the sem will be available
// do the work
sem_release($semRes); // release the semaphore so other process can use it
}
}
PHP needs to be compiled with sysvsem support in order to use sem_* functions
Here's a more in depth tutorial for using semaphores in PHP:
http://www.re-cycledair.com/php-dark-arts-semaphores
You are looking for a Semaphore
Bear in mind that using a semaphore (or any other blocking mechanism) can have serious peformance issues, as the requests can not be handled while the semaphore is up.
off the top of my head:
function checks if a database field called isFunctionRunning is equal 1. if not start executing
you update the database field called isFunctionRunning to 1
function does magic here
you update the database field called isFunctionRunning to 0
but somehow i think what you are trying to do is "wrong" and can be achieved in another way. could help if you said more details
edit: wasn't aware of php semaphores, the answer above will be way faster.
You can use the "flock" (file locking) function with the "LOCK_EX" (exclusive lock) flag to create a custom "synchronized" function that accepts a handler to be synchronized.
You may may found the code here.
I hope this helps.
I have a JavaScript functions which calls a PHP function through AJAX.
The PHP function has a set_time_limit(0) for its purposes.
Is there any way to stop that function when I want, for example with an HTML button event?
I want to explain better the situation:
I have a php file which uses a stream_copy_to_stream($src, $dest) php function to retrieve a stream in my local network. The function has to work until I want: I can stop it at the end of the stream or when I want. So I can use a button to start and a button to stop. The problem is the new instance created by the ajax call, in fact I can't work on it because it is not the function that is recording but it is another instance. I tried MireSVK's suggest but it doesn't worked!
Depending on the function. If it is a while loop checking for certain condition every time, then you could add a condition that is modifiable from outside the script (e.g. make it check for a file, and create / delete that file as required)
It looks like a bad idea, however. Why you want to do it?
var running = true;
function doSomething(){
//do something........
}
setInterval(function(){if(running){doSomething()}},2000); ///this runs do something every 2 seconds
on button click simply set running = false;
Your code looks like:
set_time_limit(0);
while(true==true){//infinite loop
doSomething(); //your code
}
Let's upgrade it
set_time_limit(0);
session_start();
$_SESSION['do_a_loop'] = true;
function should_i_stop_loop(){
#session_start();
if( $_SESSION['do_a_loop'] == false ) {
//let's stop a loop
exit();
}
session_write_close();
}
while(true==true){
doSomething();
should_i_stop_loop(); //your new function
}
Create new file stopit.php
session_start();
$_SESSION['do_a_loop'] = false;
All you have to do now is create a request on stopit.php file (with ajax or something)
Edit code according to your needs, this is point. One of many solutions.
Sorry for my English
Sadly this isn't possible (sort of).
Each time you make an AJAX call to a PHP script the script spawns a new instance of itself. Thus anything you send to it will be sent to a new operation, not the operation you had previously started.
There are a number of workarounds.
Use readystate 3 in AJAX to create a non closing connection to the PHP script, however that isn't supported cross browser and probably won't work in IE (not sure about IE 10).
Look into socket programming in PHP, which allows you to create a script with one instance that you can connect to multiple times.
Have PHP check a third party. I.E have one script running in a loop checking a file or a database, then connect to another script to modify that file or database. The original script can be remotely controlled by what you write to the file/database.
Try another programming language (this is a silly option, but I'm a fan of node). Node.js does this sort of thing very very easily.
here is my code
echo ("<br/>");
if ($APIkbpersec < 30) {
global $SpeedTest;
echo ("Slow speed");
$SpeedTest--;
}
if ($APIkbpersec > 30) {
global $SpeedTest;
echo ("High speed");
$SpeedTest++;
}
echo $SpeedTest;
the page this code is in gets reloaded every second with AJAX and the $APIkbpersec changes between 40 and 0.
I basically want to have a variable ($SpeedTest) increase or decrese depending on what $APIkbpersec is.
if $APIkbpersec is less than 30, I want $SpeedTest to decrease by 1 every refresh to a minimum of 0.
if $APIkbpersec is greaterthan 30, I want $SpeedTest to increase from by 1 every refresh to a maximum of 10.
the problem is I dont know what the porblem is....Im currently trying to write $SpeedTest to a txt file so I can read it in every refresh to do the maths on it every refresh without it being reset in PHP
any help would be appreciated
It's being reset because the HTTP request is stateless. Each AJAX call is an isolated event to a PHP script. To make the variable persist, it has to be stored in $_SESSION.
You have not shown the code you're using to write it to a text file, but unless you need it to persist beyond a user session, that's the wrong approach. You're better served using $_SESSION. If you do need long-term persistence, you should use a database instead.
session_start();
// Initialize the variable if it doesn't exist yet
if (!isset($_SESSION['SpeedTest'])) {
$_SESSION['SpeedTest'] = 0;
}
echo ("<br/>");
if ($APIkbpersec < 30) {
echo ("Slow speed");
$_SESSION['SpeedTest']--;
}
if ($APIkbpersec > 30) {
echo ("High speed");
$_SESSION['SpeedTest']++;
}
echo $_SESSION['SpeedTest'];
You should use $_SESSION for that purpose.
See HERE for an explanation, but basically you would need to do the following:
session_start();
$SpeedTest = isset($_SESSION['speedTest']) ? $_SESSION['speedTest'] : 0;
if ($APIkbpersec < 30)
{
echo ("Slow speed");
$SpeedTest--;
}
if ($APIkbpersec > 30)
{
echo ("High speed");
$SpeedTest++;
}
$_SESSION['speedTest'] = $SpeedTest;
echo $SpeedTest;
Either:
Return $SpeedTest in the response and pass it back and forth.
Use some kind of persistent storage such as a cookie or PHP sessions.
Both are pretty easy to implement. If you want with persistent storage, I'd suggest a cookie as both JS and PHP could share it. Session, although the obvious candidate, are a bit overkill in this case - IMO.
If this is all of your code, the problem is simple. Each time the script is run, the values of all the variables are initialized. For your case, this means that the value of $SpeedTest does not persist - it's reset to zero each time the script is called. You can use a session as #Michael suggests (probably my recommendation), read the value out from a text file or database and then write a new value out, or you could return the value of $SpeedTest to your AJAX script and pass it back into the php script as a parameter. Each of these have various advantages and disadvantages, but using the $_SESSION superglobal is easy to do and takes little modification to your code.
If you want to do it with files you can use a single file to store a single global value for your variable:
Read data from file (docs here):
$data= file_get_contents('file.txt');
Put data into file (docs here)
$bytesWritten = file_put_contents( $data );
Else you can use sessions or database as other suggested.
Without cookies or sessions you cannot have a real "per user" solution so if you need that stick with other answers or use an hybrid solution with sessions/files
If you use the request solution (that kind of ping-pong with POST or GET variables) always pay attention because those variables can be altered by users.
Other things to remember:
Files and database records last until you delete them (so maybe you have to manage undeleted files or records).
Session duration is configured within your server (so they can last too short if you need long term persistency).
Usually database are better than files (the do more tasks and provide your application more scalability) but in some cases files solution is faster (tested) specially if your database resides in another host and is not on the same host as your webserver.