So I have this piece of code that is executed each iteration. The iterations are not ordinary loops but part of a series of ajax request iterations. The first ajax request determines a filename that is assigned to e.g $_SESSION['filename'] and then this variable is pushed into and array etc. Now the problem occurs when i have multiple files being processed.
It happens often that one of the filenames that is generated gets duplicated and inserted into the database which it should not.
First callback function:
case 'upload':
...
$_SESSION['upload_filename'] = random_filename($alphas).'.'.$fileExt;
...
break;
second callback function:
case 'insert_db':
array_push($someGlobalArray, $_SESSION['upload_filename']);
insert($_SESSION['upload_filename']);
break;
So as I said a new filename is generated properly like 70% of the time. I'm not sure why the old filename from the previous "iteration" lingers and $_SESSION['filename'] does not contain a new filename. I've tried unset the filename after insert() in the second callback function, but that causes a problem where no filename is available to be either pushed into the array or inserted into the database since what I think is that it gets unset before? I've also tried sleep(2) after the insert() and then unset but does not help.
Here is more of the code: http://pastebin.com/g4fereQx
My best guess is that your code may not be executing the the exact order you think it is.
Its hard to say with the snippets you've posted though.
could you show a little more of your code, like the ajax calls that send off the data and such. I know I've had problems in the past where I wasn't setting async: false in my ajax call and so it would try to process and act on information that hadn't properly been set yet
Related
I have a script in php that does some operations before insert the results into my table, but I'm trying to prevent the execution twice or more of the same script if i open it in more than one tab in my browser, I'm working to do a kind of trick to do this, for this I'm using sessions, I got a specific session variable that is updated when I run the script but my question is..
if I got something like this
session_start();
if (isset($_SESSION['lock'])) {
if ($_SESSION['lock'] === false) {
$_SESSION['lock'] = true;
}
}
that code is into a file that is executed with ajax request, once the variable has been updated with a new value it will be update globally?, I mean I have open two tabs with the same page (tab1 and tab2) after execute the script in tab1 when I do the same in tab2 the value $_SESSION['lock'] will be true or false?, I hope this explanation to be good, thanks.
NOTE: both tabs were opened at same time
Yes, changing $_SESSION is a global change for that particular user. But note that changes to $_SESSION are NOT pushed out to multiple windows "live". Only on subsequent hits in ANY window/tab will the new value have a chance to affect those tabs/windows.
Yes, sessions are bound to a unique User, so they are spreaded over tabs. Why don't you just test it though?
I have a PHP script that can take a few minutes to be done. It's some search engine which executes a bunch of regex commands and retrieve the results to the user.
I start by displaying a "loading page" which does an AJAX call to the big processing method in my controller (let's call it 'P'). This method then returns a partial view and I just replace my "loading page" content with that partial view. It works fine.
Now what I would like to do is give the user some information about the process (and later on, some control over it), like how many results the script has already found. To achieve that, I do another AJAX call every 5 seconds which is supposed to retrieve the current number of results and display it in a simple html element. This call uses a method 'R' in the same controller as method 'P'.
Now the problem I have is that I'm not able to retrieve the correct current number of results. I tried 2 things :
Session variable ('file' driver) : in 'P' I first set a session variable 'v' to 0 and then update 'v' every time a new result is found. 'R' simply returns response()->json(session('v'))
Controller variable : same principle as above but I use a variable declared at the top of my controller.
The AJAX call to 'P' works in both cases, but everytime and in both cases it returns 0. If I send back 'v' at the end of the 'P' script, it has the correct value.
So to me it looks like 'R' can't access the actual current value of 'v', it only access some 'cached' version of it.
Does anyone have an idea about how I'm going to be able to achieve what I'd like to do? Is there another "cleaner" approach and/or what is wrong with mine?
Thank you, have a nice day!
__
Some pseudo-code to hopefully make it a bit more precise.
SearchController.php
function P() {
$i = 0;
session(['count' => $i]); // set session variable
$results = sqlQuery(); // get rows from DB
foreach ($results as $result) {
if (regexFunction($result))
$i++
session(['count' => $i]); // update session variable
}
return response()->json('a bunch of stuff');
}
function R() {
return response()->json(session('count')); // always returns 0
}
I would recommend a different approach here.
Read a bit more about flushing content here http://php.net/manual/en/ref.outcontrol.php and then use it.
Long story short in order to display the numbers of row processed with flushing you could just make a loop result and flush from time to time or at an exact number or rows, the need for the 5 seconds AJAX is gone. Small untested example :
$cnt = 0;
foreach($result as $key => $val) {
//do your processing here
if ($cnt % 100 == 0) {
//here echo smth for flushing, you can echo some javascript, tough not nice
echo "<script>showProcess({$cnt});</script>";
ob_flush();
}
}
// now render the proccessed full result
And in the showProcess javascript function make what you want... some jquery replace in a text or some graphical stuff...
Hopefully u are not using fast_cgi, beacause in order to activate output buffering you need to disable some important features.
I believe you have hit a wall with PHP limitations. PHP doesn't multithread, well. To achieve the level of interaction you are probably required to edit the session files directly, the path of which can be found in your session.save_path global through php_info(), and you can edit this path with session_save_path(String). Though this isn't recommended usage, do so at your own risk.
Alternatively use a JSON TXT file stored somewhere on your computer/server, identifying them in a similar manner to the session files.
You should store the current progress of the query to a file and also if the transaction has been interrupted by the user. a check should be performed on the status of the interrupt bit/boolean before continuing to iterate over the result set.
The issue arises when you consider concurrency, what if the boolean is edited just slightly before, or at the same time, as the count array? Perhaps you just keep updating the file with interrupts until the other script gets the message. This however is not an elegant solution.
Nor does this solution allow for concurrent queries being run by the same user. to counter this an additional check should be performed on the session file to determine if something is already running. An error should be flagged to notify the user.
Given the option, I would personally, rewrite the code in either JSP or ASP.NET
All in all this is a lot of work for an unreliable feature.
NEW INFORMATION:
I used the print_r function on the $_REQUEST and something very strange is happening there too. Some values are being correctly passed by the GET such as a value on another form which passes in "TRUE". This can be seen in the print_r output but isn't written to the file... Still no closer to finding a solution to my problem however.
I'm working on a page with a lot of forms which are loaded in as needed by AJAX. This all works fine as does parsing the name:value pairs and storing them appropriately.
My error happens when the PHP parses the GET request sent by AJAX when the user is finished, it only seems to retrieve the values from certain fields.
The idea is that the user can add data from any number of forms, which are then turned into a GET request and sent to the server.
The JavaScript is building my request perfectly and all forms are sent correctly.
Depending on the forms the user submits, the data is processed by a large switch statement which passes the relevant names to a variadic function which grabs the values, and creates a string for writing to a file.
The strange error is that only some values get written to the file with others only having a blank line. No error reported by Apache or PHP, no error reported in the JavaScript console either.
I'll use the Colour form for example as this is one of the more complex.
So I add a colour action and click the button to submit all forms (this time, it's just the colour form though)
My get request looks like this:
actionIDs=Colour&coOptionSelect=Tinting&coColourEffect=Sepia&coRemoveColour=#000000&coRemoveFuzzNumber=0&coRemoveHueSelect=None&coReplaceColour=#000000&coReplaceFuzzNumber=0&coReplacementColour=#000000&coReplacementAlphaNumber=0&coReplaceHueSelect=None&coReplacementHueSelect=None
Next, the PHP parses the actionIDs part as sometimes, there will be many actions. This works fine.
We now jump to the Colour part of the switch statement.
case "Colour":
$config = processAction("coOptionSelect", "coColourEffect", "coRemoveColour", "coRemoveFuzzNumber", "coRemoveHueSelect", "coReplaceColour", "coReplaceFuzzNumber", "coReplacementColour", "coReplacementAlphaNumber", "coReplaceHueSelect", "coReplacementHueSelect");
file_put_contents($confpath . "colour.conf", $config);
break;
That writes to the correct file, but strangely, only coOptionsSelect and coColourEffect have their values written to the file. It isn't their input type as they are select statements similar to the other selects on the form. On other forms, it may be a number input or a text input that submits properly instead.
It isn't random either, the same ones will always write out properly. It also isn't positional as I moved around the values and it's still the same ones that write correctly, their position doesn't affect anything.
Finally here is processAction function.
function processAction()
{
$config = "";
foreach(func_get_args() as $field)
{
$temp = isset($_REQUEST[$field]) ? $_REQUEST[$field] : null;
$config = $config . $temp . "\n";
}
return $config;
}
The end result should be all values should write to their relevant files correctly, rather than the current issue where only a few values from each form are written, with the rest of the values being written as blank lines.
You probably need to encode your # sign to a encoded method %23
you could also use urlencode to do it before passing it to your variable.
Reference: http://php.net/manual/en/function.urlencode.php
Update:
If you are going to try to encode through javascript I would try and use this method
var newURL =
"http://example.com/index.php?url=" + encodeURIComponent(actionIDs);
or
var newURL =
"http://example.com/index.php?url=" + escape(actionIDs);
Reference: Encode URL in JavaScript?
You have three options:
escape() will not encode: #*/+
encodeURI() will not encode: ~!##$&*()=:/,;?+'
encodeURIComponent() will not encode: ~!*()'
But in your case, if you want to pass a URL into a GET parameter of other page, you should use escape or encodeURIComponent, but not encodeURI.
See Stack Overflow question Best practice: escape, or encodeURI / encodeURIComponent for further discussion.
I've made an img editor which works fine in 99.9% of the situations.
However, in that rare 0.1% something weird happends, my session remember doesn't the proper value.
I have this in the page that inits the class:
$imgScreen = new img4crop();
// And here some settings like $imgScreen->setExtraJs($extraJs);
In this class I have a functions to save the $this data to an array:
private function save(){
$_SESSION['cropper'][$this->uniqid] = serialize($this);
}
In init-page.php I open a fancybox, loading the settings back into the class:
$info = unserialize($_SESSION['cropper'][$_GET['id']]);
// Should now be the same as $imgScreen
The problem
Sometimes $_SESSION['cropper'][$_GET['id']] is set to NULL. I have no clue why. This only happens very rarely. The key is set.
When I debug, and appendecho $_SESSION['cropper'][$this->uniqid]; to the save() function, it gives me the value I want it to have.
So, where does my session value go, only in that rare occation? Why isn't it there in the fancybox screen?
After 1st comment: It is possible for the init-page to start multiple instances, they each get their own value in $_SESSION['cropper']. In the situation above, they all work, just that one doesnt. On reload, I start new instances and the exact same screen doesnt work, even though I now has a new, fresh id
Edit: It gets weirder: If the location where the image has a file with the same name as the class will use, there are no problems. Weird part: The whole class has no code regarding to files, apart from the final step (the screen has 3 steps), where I use ImageMagick.
Important to know: When I installed the page where this occurs, the targetfile didn't exist either, started blank.
When you are serializing objects you have to make sure you load the base class (prototype) before unserializing the object. For PHP native objects you don't have to do anything, it will load the base classes.
Your variable $this is an instance of a class. In order for $this to exist the base class need to exist. Perhaps it's working most of the time because of an autoloader or the particular sequence you are loading items.
Turns out the solution was, as to be expected, a quircky little something unrelated to the actual code:
In my index.php I do $_SESSION['cropper'] = array(); to reset the array, then let the function which shows an editorscreen set new settings to the cropper, this works perfectly fine.
In that html I have an image with an anti cache:
echo '<img src="'.$image_url.'?'.time.'" />';
The problem occured when $image_url is empty/undefined, resulting in a source something like the following: ?1420793438. It starts with a ?, so it's effectively calling index.php?1420793438.
And at the beginning of that index.php we reset, resulting in an empty array.
OK, so I have searched around for long enough to finally post this one here. Sure enough, it has been asked before a zillion time...
What I have, is one file, which includes another. No magic here. The trouble is, the included file then includes another file, which... includes yet another... Yep, a pain. Actually it's all working quite nicely, except that I now wanted to read the URL of the original file in the last of the included files.
So I thought in the original file, file_1.php I just say
$var_foo = dirname(__FILE__);
or
$var_foo = $_SERVER['SCRIPT_NAME'];
and then read that value in the first include, file_2.php, passing it on like
$var_foo_2 = $var_foo;
then in file_3.php
$var_foo_3 = $var_foo_2
etc, until I arrive at the final file, file_4.php, where I'd like to know the exact value of the original file's URL. Passing it on the first level works OK, but then it gets lost somewhere along the way. Tried going GLOBAL in file_1 -- to no avail.
Since file_3 and file_4 must both execute to produce data, setting a breakpoint a la echo / exit to spoof the current value (if any) is no option. I can live without that particular value, but I just would like to have it -- for the fun of it... Any ideas how to accomplish this?
Your examples use filesystem paths, not "URLs";I am assuming the filepath of the parent file is what you actually want.
You don't need to "pass" the variable on each included page. It will automatically be available to the code on the new page.
(If it is not, you may not be in the right scope: e.g., if you're inside a class or function, you'll need to pass it deliberately or use some other method - global, maybe, or even define the filename as a constant instead of a variable.)
main script
$parent_filename = __FILE__;
// alternatively
// define( 'PARENT_FILENAME',__FILE__ );
include "other-file.php";
other-file.php
include "other-dir/somefile.php";
other-dir/somefile.php
print $parent_filename;
// alternatively
// print PARENT_FILENAME;
/* prints something like:
/path/to/main.php
*/
As mentioned before, the issue has been solved like so:
set variable before the first include
add variable to query string
Thanks all for the input, appreciated.