Updating $_SESSION variable - PHP - php

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?

Related

Page updates while processing

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.

Why is my PHP $_SESSION cleared when doing an AJAX Post?

I'm trying to get some values from my $_SESSION variable but it seems to be cleared everytime an AJAX request is initiated.
I have pasted the code below, any help much appreciated :
/*
* The input request from angularjs
*/
$data = file_get_contents("php://input");
$data = json_decode($data, true);
switch( strtolower($data['action']) ) {
case 'products': getAllProducts($data['fields']);
break;
default : echo json_encode(array('success' => false));
}
//fb is a firebug debug function, prints PHP vars to console.
fb($_SESSION['var'); //when loading the php file the first time $_SESSION is set
UPDATE
I'm using AngularJS for my AJAX calls, it works great but now I want to read data from my $_SESSION variable and all I get is an empty $_SESSION. Does this have anything to do with my file_get_contents("php://input");
SOLVED
I found the problem, the previous developer did not take into account that one might desire to include files from 2 levels deep :) As such, I scanned through the PHP error logs and saw that a previous script was not loading - this particular script was included with the session_start and $_SESSION variable values.
Checking the error logs will be my first priority from now on
I found the problem, the previous developer did not take into account that one might desire to include files from 2 levels deep :) As such, I scanned through the PHP error logs and saw that a previous script was not loading - this particular script was included with the session_start and $_SESSION variable values. Checking the error logs will be my first priority from now on

PHP session: two values are ALWAYS sent

I'm pretty new to PHP but trying to find my way which has worked quite well up till now.
Problem is the following: I have a website with 2 links. Both should redirect to the same second website but depending on the link clicked, some values should change. I was trying to use a PHP session for this.
Here is the code up to now:
Link 1:
<a href="<? echo $link ?>" class="helsinki" onclick="<? $_SESSION['clicked']= "helsinki"; ?>"^^Helsinki^^</a>
Link 2:
^^Seattle^^
Now if I try to read which link was clicked on the next side like this:
<? if(isset($_SESSION['clicked']))
echo "clicked ". $_SESSION['clicked'];
?>
I always see "Seattle", Helsinki never appears although (I thought) I input Seattle if the Seattle link is clicked. Apparently it's not like that... Can anyone help me here?
This is because PHP code is server side, and thus executed at the time of the page request. So $_SESSION['clicked'] is set to helsinki then reset to seattle at the time your first page loads. You may want to use $_GET variables instead of $_SESSION variables.
Wait wait wait a second: PHP is "server-side", javascript is "client-side". That means you will ALWAYS execute PHP before javascript.
What you are trying to achieve can be simply done with a GET variable:
^^Seattle^^
^^Helsinki^^
And than in the second site you can get the value of our parameter:
$city = $_GET['city'];
Not sure if this is useful, but you could create a "redirector". It takes the user to a server side page that will redirect them to the final page and at the same time change the session.
The page:
...
...
The code for redirector.php:
<?php
session_start();
// determine where to redirect user (could be done with database or array of options)
switch ($_GET['link']) {
case 'helsinki':
header('Location: /link/to/helsinki');
break;
case 'seattle':
header('Location: /link/to/seattle');
break;
default:
return;
}
$_SESSION['clicked'] = $_GET['link'];
You're mixing up Javascript and PHP.
PHP is server side, that means that all PHP code is parsed and executed on the server side, and then is sent to the client.
So if you write
line #1: ^^Helsinki^^
and then
line #2: ^^Seattle^^
the value of $_SESSION['clicked'] is always first "Helsinki" (line #1), but then immediately overwritten by "Seattle" (on line #2).
In order to achieve what you want the script to achieve, is, for example, as follows:
^^Helsinki^^
^^Seattle^^
and then catch the sent variables from the PHP variable $_GET:
if (isset($_GET['location'])) {
if ($_GET['location'] == "helsinki") {
// Whatever
}
elseif ($_GET['location'] == "seattle") {
// You want
}
}
"^^Helsinki^^
"^^Seattle^^
and use $_GET['location'] at the other page to check weather it is helsinki or seattle.
$link should be the same for both links.
Also you can't mix PHP (server-side) with Javascript (client-side). Look it up for why that is.
You cannot write PHP code in the onclick event. If you want to do it like that, you should use Javascript/AJAX. Even if you do it like that, you won't still get the result as you desire, since AJAX request will delay some seconds.
I think the right way to do this kind of thing is like below:
Helsinki"
and this is the change_city.php:
<?php
$_SESSION["clicked"] = $_GET["city"];
?>
if you want to still use the $link, then you just put this above code top of your PHP file.

How to store search result?

I am working on my personal site, where I want to store my customers recent search result limited to that particular session.
I am using PHP platform and Javascripts.
Here is an example of what I am exactly looking at :
It stores your previously searched domain name for that particular session so that user can make decision by comparing those results.
Thanks.
EDIT- Well Thanks for all of your answers and suggestions.
But If you have noticed
above example
It looks like some kind of script loading a new content on the same page without refreshing it and keeping previous search content <div> as it is.
How to achieve this using javascripts or some sort of div layer ????
UPDATE START
This example uses page reload. If you want to do it without page reload, you can but you'll have to use AJAX to load new search results. But then, it's not a PHP question. I suggest looking at jquery library, as it makes it easy. Tutorials: http://docs.jquery.com/Tutorials and e.g. this one ( http://docs.jquery.com/Tutorials:Getting_Started_with_jQuery#Rate_me:_Using_Ajax ).
When loading data via AJAX, the page rendering result (in my example search.php) should return only HTML for results part, not whole HTML page. This is generally a first part of my tutorial (without session).
But I really think that AJAX in here is not really needed. Session is more reliable and allows access to your page from older / mobile browsers where not always JS works correctly.
UPDATE END
Ok then. Let's try the simple tutorial then. Sorry if too simple, but I don't know your exact level.
PHP has mechanism called sessions. In reality they are just bytes stored on server. Server knows which session is for each client by reading session cookie from client browser.
Not every page uses sessions (not every page needs it, and session uses server space, even if only temporarily), session is not enabled by default. To turn on session you use command
<?php session_start(); ?>
In most cases this is either run by PHP framework you use, or put near the top of your site. Session is definitely needed if you want to authenticate user somehow. Or in your case :)
To access session you can use superglobal $_SESSION variable (superglobal means that you can access it anywhere). It's an array, so session element will be e.g. $_SESSION['search'] etc.
As example, let's assume that your page looks like that
<html>
...
<form action="search.php" method="post">
Search: <input type="text" name="searchQuery" />
<input type="submit" value="Search" />
</form>
...
</html>
this very form will send user search to file named search.php. It can be the same file where the form resides - in simplest case when you put both your code and HTML in one file. Beginners often use this schema, although it's not advisable as result is a mess and hard to further change.
In search.php then, you'll use similar code:
<?php
if (!empty($_POST['searchQuery'])) //we have a new search
{
$result = do_search($_POST['searchQuery']);
}
?>
Then, somewhere below you'll display your search result ($result variable). do_search() function is your search mechanism, I guess you have it somewhere. You may have it not 'wrapped' in a function, then I advise to create it like that, it's much more useful.
function do_search($searchQuery)
{
...
return $result;
}
mind it, the above code doesn't use sessions yet. Let's add saving previous search results in session. The code may then look like that:
<?php
session_start(); //Starting session
//let's create session variable used to store results
if (!isset($_SESSION['searches']))
$_SESSION['searches'] = array();
if (!empty($_POST['searchQuery'])) //we have a new search
{
if (isset($_SESSION['searches'][$_POST['searchQuery']]) //User already searched on this value, delete previous result from sesion
{
unset($_SESSION['searches'][$_POST['searchQuery']]);
}
$result = do_search($_POST['searchQuery']);
//Let's add new search on the begining of session array to make iterations easier.
$result = array($_POST['searchQuery'] => $result); //convert result to same format as session table
$_SESSION['searches'] = array_merge($result, $_SESSION['searches']);
}
?>
In display you'll now not iterate on $result variable as before, but instead you will do something like
foreach ($_SESSION['searches'] as $query => $result)
{
...//display of single result
}
I haven't tested following code and it's not a full program. Parts to display result and to do actual search are not described but I guess you have them already prepared. Also, this is only one possible approach of countless possibilities. But I hope this helps :)
Possible modification - now I always perform search, even if user already searched on this term. You may want to receive the result from cache without second search. Then the code will look like
if (isset($_SESSION['searches'][$_POST['searchQuery']]) //User already searched on this value
{
$result = $_SESSION['searches'][$_POST['searchQuery']];
unset($_SESSION['searches'][$_POST['searchQuery']]);
}
else
{
$result = do_search($_POST['searchQuery']);
}
For more in-depth information about sessions and some other constructs used in my example I suggest PHP manual
http://pl.php.net/manual/en/book.session.php
and various tutorials over the network. Or you can add a comment here :)
Put this code near the beginning of your script(s):
if (!isset($_SESSION['previous_searches']) || !is_array($_SESSION['previous_searches'])) {
$_SESSION['previous_searches'] = array();
}
[edit]
This code snippet checks if if there is already an array with prevous searches and if not it will be created.
[/edit]
Then when the user hits the search page put this code in the receiving script of the search:
$_SESSION['previous_searches'][] = $_GET['what_ever_your_search_value_might_be'];
[edit]
This code snippet adds the current search value to the and of the array with previous search values
[/edit]
Now you have all previous search values in $_SESSION['previous_searches']
If your website is a web application where you never reload the page nor change the page, you can keep it JavaScript in a global store (declare at top level something like var StoredSearch = []; and use it). If not, then use $_SESSION to store this and AJAX to save/load searches from JavaScript to PHP.

Saving variables (not sessions)

This may be a silly question, but how do I save variables that are not specific to a particular session. An simple example of why you might want to do this would be a visitor counter - a number that increases by one each time someone visits a web page (note - I'm not actually doing that, my application is different, but that is the functionality I need). The only ways I can think of doing this are either writing the variables to a file, or putting the variables into a database. Both seem a bit inelegant. Is there a better way to to this kind of thing?
If you need to save global state, you need to save global state. This is typically done in either a file or a database as you already noted.
It's not "inelegant" at all. If you need to save something (semi-)permanently, you put it in a database. That's what databases are for.
Have a look at the serialize() function in PHP http://uk3.php.net/serialize where you'll be able to write an array or such to a file and re-retrieve:
<?php
// Save contents
$var = array('pageCounter' => 1);
file_put_contents('counter.txt', serialize($var));
// Retrieve it
$var = unserialize(file_get_contents('counter.txt'));
?>
Otherwise save the value to a database.
Given that PHP is stateless and that each pageload is essentially re-running your page anew, if you're going to be saving variables that will increment over multiple pageloads (e.g., number of distinct users), you'll have to use some form of server-end storage - file-based, database, whatever - to save the variable.
You could try installing APC (Alternative PHP Cache) which has cool features for sharing data between all PHP scripts, you could try using shared memory too or like you said, use a file or database
I think I've found the answer - session_name('whatever') can be used to have a fixed name for a session, I can refer to that data as well as the session specific session.
If you want it to be permanent, database and files are really your only two choices.
If you only want to temporarily store these values in memory, if APC is installed, you can do this:
// Fetch counter value back from memory
$success = false;
$counter = apc_fetch('counter', &$success);
if ($success) {
// fetch succeeded
} else {
// fetch failed
$counter = 0;
}
// Increment the counter and store again
// Note that nothing stops another request/page from changing this value
// between the fetch and store calls.
$counter++;
apc_store('counter', $counter);
That was just an example.
For a counter, you're better off using apc_inc('counter') / apc_dec('counter').
Presumably other opcode caches have similar methods. If you're not running an opcode cache... really? You want PHP to recompile a page every time its requested?
Elegant, no database and no file ?
Store it in your server memory with shmop and hope your server does not reboot !

Categories