How reliable is a method of setting variables into a session and then retrieving them on another page?
I have a script where users drag and drop elements on a page utilizing jQuery UI. I record transactions using AJAX, however, sometimes I get results missing project ID, or to be exact I get 0. I set this ID into a session variable when users first get on this script page. The page has an included JS file with my functions and from there the transaction data is sent to an AJAX page where I store transactions into my db. Because the project ID is the same I get it from my session. It is not a consistent error, happens only once in a while, but it bothers me a lot.
Why is it happening randomly? And how can I fool-proof my code?
UPDATE: OK, it seems it's something else that may be interfearing with that particular session ID.
I do have session_start(); on every page where I use sessions and I set them the same way I set all my sessions: `$_SESSION['project'] = $projectID;
Back to debugging...
Yes, you can rely on PHP sessions. If you are getting odd results, it seems like your going to have to debug your code until you find the issue.
Related
I am currently writing a Magento 2 module that requires me to log customer actions like product views. This action needs to be added for both logged in customers and guest customers. My solution is to use a custom variable (array) in the session for the customer of all product ID's.
To get around full page caching I have implemented a frontend ajax request to log the product views.
I have a controller that when visited will save the product ID in the session. This works as expected when I visit the URL directly, however, when its visited via an AJAX request the saving of the session variable does not work.
I have spent hours trying to debug this, I have been outputting the contents of the session variable and when accessed with AJAX I can see the contents, it's just never updated.
```
public function setGuestCustomerProductView($productId)
{
$guestProductViews = $this->_sessionManager->getGuestProductViews();
$guestProductViews[] = $productId;
$this->_sessionManager->setGuestProductViews($guestProductViews);
return $guestProductViews;
}
```
The AJAX request will always return the contents of the session variable (plus the product ID you are viewing) but never sets the variable. If I visit the URL directly in the same browser the contents are shown and the session variable is updated.
Further AJAX requests show the new session variable data from the direct URL request.
Have I misunderstood something in regards to sessions and AJAX requests? The domain is the same so there is no cross domain issues.
Any help would be appreciated.
UPDATE
I am starting to think this is not a magento 2 issue and it's more of a general Session/AJAX issue.
I decided to test a theory and switch out the SessionManager and use PHP's $_SESSION global variable. This resulted in the same issue so it's not the handler that's the issue.
Further tests concluded the same session ID was being passed and used correctly. While using the SessionManager I called isSessionExists() directly before the set method. This method returned true which checks for not only a valid session ID but also confirms the headers haven't been sent.
I see no reason why this works directly in the browser but not over AJAX. I will continue to investigate unless someone posts and answer I can try out.
SECOND UPDATE
After several failed attempts to get this feature to work I have decided to drop the feature and try a different implementation. As it stands in my module I am not using cookies on the clients side to record the product views and then reading the cookie in PHP. This works perfectly.
I hope my investigations here helps someone in the future.
hello all i am having a website where i have a side pannel which is displaying the same thing on all the pages
i mean the data which is fetched by the database dosent change often.
like i have a pannel on the left side of my site which is displaying recent birthdays which is going to be change after 1 day only but the problem is that everytime the page is refreshed the same data needs to be fetched from the database again and again which can increase the database load and also page load time
i was wondering if there is anything which can display the side bar once the query is executed and after that the result will be fetched from session/cache or what ever the sollution is
i think it can be done by cache like memcache but i dont know how
i also tried to store them into session and cookies but there is error it say can not store objects into session and also i have to use loop to the results obtained by query the query is like
$birthday_query=mysqli_query($connection,"select name,email,id,date from members where dob 'some code here' ");
// this code fetches about 30-40 results and i am using the loop to display the results..
Yes, you can use memcache to store the information. This is your best option as it is going to stay in the server memory.
You can also use something very simple like a temp file where to keep the recent birthdays information - the HTML code. Update the information in this file once a day and read it from there. For every user you can read the information once (when they first come the website) and then store it and read it from the session.
For just 30-40 results, you don't need caching it will not add a great value, good will be to use Session to store the data as soon user browse your first page and then fetching data always from Session. using a file to cache html is also a good bet here.
you can check how to store object into session
The situation:
I have a site with multiple pages accessible through the menu, after login.
On the dashboard page (the page you see right after login), there is a AJAX call getting the data from the PHP-Controller (zend framework). This call does about 20 queries to 2 different databases and a lot of data manipulations. It can take up to 5 seconds to load everything. So far, so good!
My problem:
When I go to another page through the menu, right after seeing the home page, the ajax call gets cancelled, and a new request is send to a new PHP-Controller. But because I'm working with php-sessions (through the zend-framework), I'm not able to do a new request before session_write_close() is called (at the end of the long-taking AJAX request). Is there a possibility that the previous call gets cancelled?
A not decent solution:
Right now, I've called session_write_close() at the beginning of my AJAX request, and this fixes the problem. Afterwards I still read from the session, but I've read, and confirmed that this is not an issue. Nevertheless, calling session_write_close() is not the prettiest thing to do, and I'm working with a few guys on this project, which has a lot of files and code paths, and won't be finished in the next 5 years... So I can't use session_write_close(), since this would not be maintainable. Especially because when you write to the session, PHP would not throw an exception. The data would simply not be saved.
So my question is:
Is there a decent alternative to session_write_close(), that let me interrupt/cancel an AJAX call (PHP-wise), to instantly go to another page, or is there a possibility to change a setting so that PHP would throw an exception when trying to write after session_write_close() is called?
Thanks In advance!
One option would be to store the session values in a database. So once you have the session_id you can read and write to the DB with updated values. It would look something like this:
$session_id = session_id();
session_write_close();
$query = $dbh->prepare("select * from tbl_sessions where session_id=?");
$result = $query->execute(array($session_id));
$values = $result->fetch();
$session_values = json_decode($values->data); //data would be a text column with a json or serialized array
//you could update any values then update tbl_sessions if you needed
Or you can override the default session functions like in this answer: set session in database in php
Or as in another answer you can close and open the session as needed:
https://stackoverflow.com/a/10046611/1401720
I wanted to transfer value from 1 page to another or in another meaning, available to all page, I tried using global, it doesn't seems to work, I know I can use $_SESSION, but my superior asks me not to use $_SESSION as it may not work on some phone. I need to implement function that enables that variable that holds the value available in all page.
My page process:
Choose a prize > enter email (The values keeps into variable from here) > goes through database checking and so on (cannot change anything here as this stage is a secure page, it is prohibitive to edit anything to prevent any security issues > thanks page (The value will be used here)
Sorry, I can't post any code here as it is secret. I am really sorry about it.
I have tried using GLOBAL, $_GET and $_REQUEST, so are there any methods I can use?
If you're using COOKIEs, you can absolutely use sessions. Session ID's, by default are stored in a cookie on the browser. If for some reason the browser doesn't support cookies, you can still use the query string to transfer the session ID, but there are some security concerns around that (such as session hijacking).
By default, I believe PHP will always try to use a COOKIE for the session ID.
To enable URL-based session IDs, take a look at the PHP.INI option use_trans_sid:
http://www.php.net/manual/en/session.configuration.php#ini.session.use-trans-sid
If you really can't use sessions, your only other options would really be to use $_GET or $_POST.
Using $_POST would require you to have everything wrapped around a <FORM> tag and submit that form for every action on your site.
Using $_GET would require you to append a query string on the URL for every link / action on the site. You will be limited on the amount of data you can store a query string, though.
You could do it with a cookie... in jquery:
$.cookie('some_key','some_value');
or in vanilla javascript:
somekey = 'some_key'l
someval = 'some_val';
document.cookie=somekey+'='+someval;
and get to it in php
<?php
echo $_COOKIE["some_key"];
?>
it's going to be tough not having any code but to answer your question, you have 4 choices, get, post session and cookies. if your superiors dont want you using sessions, then i doubt they want cookies (sessions TYPICALLY USE cookies). I would seriously talk to your boss about using get and post variables because if your trying to keep it secure then passing a post/get variable is very insecure and can be altered in between steps. Session variables can not be.
what I would also check if you are trying to use a post variable is that the secured page in the middle has a form with the value as a hidden field otherwise it will be lost going to the third page because post values are only submitted as part of a form
So the chain of events is:
The user submits a form.
During the processing of the submission, there is a message generated, such as "Your record was saved."
The user is redirected to a new page, say the search results.
The new page needs to display the message.
So, the question is how to get the message from step 2 to step 3? This is only one simple example...there are many other much more complicated examples.
I am using PHP.
Needs:
supports multiple messages and need to be formatted on the receiving machine as required
messages can be added on the same page (such as within step 4)
messages added from inside any function or object
Some options I have come up with:
store in a session variable as an array and emptied after each display
pass as a get or query parameter; can get annoying as you are constantly processing this and have to remember to get it; as it can get long, it could easily go over the max length of the query string
store in the database on a per session basis (may not always be for a logged in user); this would require an extra insert on each page where they are added, possibly multiple, and an extra select on every page
Currently I have been storing the messages in the session in an array, but I'm wondering if there is a better way. I don't think the other 2 options above are very good.
Edit: I use 2 functions for the session method: AddStatusMsg() (adds an element to the array) and DisplayStatusMsg() (returns an HTML formatted message and empties the array).
I would recommend AGAINST storing these messages either in the database or in the session, for one simple reason: tabs. (Well, really, the stateless nature of HTTP.)
Think of a person who's got multiple tabs open of different sections of your website. This person performs some action and while that loads, switches to another tab and clicks on a link. If you're storing the messages in the session/database and the switched-to tab is a page that can display these messages too, the user has now entered a race condition where depending on which request the server responds to first, the messages may display where they were not intended.
Now, there are some situations where this legitimately might not matter, but it could also be extremely confusing in some cases.
Putting the messages in the request doesn't have to be as bad as it initially seems. Perhaps you could store all the messages you want to display in the database with a numeric (or, for bonus obfuscation, hash) ID, and pass a list of IDs in the query string. This keeps the query string short, and all you have to do is keep track of what ID corresponds to what message in your code.
I would stick with the session approach only perhaps adding support for this messaging system on the master page. You are on the right way as the all other approaches have a greater cost, of simplicity or performance.
I suppose you have a master page which is the template for all other pages. If you don't have it's a good reason to have one, so you don't need to take care of handling the displaying of the messages on every page you need it as long as you have a specific place to show them.
You can also use a specific div rendered by the master page for that and let the position be handled by the current page. If I understand correctly you need some kind of timing between the showing of the message and the user redirection to another page. This could be achieved using any AJAX library to show that div I said before and then redirecting to a new page.
I suggest taking a look into jQuery.
This is how I like to do it:
function set_message($message_type, $message)
{
$_SESSION['messages'][$message_type][] = $message
}
function get_messages()
{
$messages_array = $_SESSION['messages'];
unset($_SESSION['messages']);
return $messages_array;
}
where $message_type can be "warning", "error", "success", etc. and depending on the type you can show the user a different image/color/whatever.
This problem is a classic example of how to have data persist in a "stateless protocol" like http.
Your options are:
Pass it in the GET parameters (not
user friendly)
Store it in the DB
Store it in Session
Options 2) and 3) require the user to have a cookie (otherwise, there's no way to match the user to the message). Between them, I'd go with PHP's built in sessions. Simply set a session variable at your step 2, and have the search page always check for the variable in your step 4
Nothing to it. Don't over complicate things.
Probably the best way is to store it in the session. It's the simplest way and as John said, 'Don't over complicate things'.
Store it in the database as well as the session. This way the user can get to his history if he needs it, and you have easy access through the session data.
Don't use a query parameter, it'll only confuse the user at some point when the message is displayed when it shouldn't be.
Displaying the messages should be a part of your main template (in other words; done once).
Maybe a slight improvement would be to store, instead of an array, an object's instance that gets populated and knows how to display the messages appropriately, deleting the data itself after any display routine gets called. That way you don't have to repeat the display and delete logic everywhere, plus, you can code different output routines in the object depending on the need.
I think you're doing it the right way. You should stay away from the database for this and putting it in the URL is ugly. You could write a nice little class for this which can make it simpler.
Here's a little session class:
<?php class session
{
public function __construct()
{
session_start();
}
public function set($name, $value)
{
$_SESSION[$name] = $value;
}
public function get($name)
{
return (isset($_SESSION[$name])) ? $_SESSION[$name] : false ;
}
public function delete($name)
{
unset($_SESSION[$name]);
}
public function destroy()
{
$_SESSION = array();
#session_destory();
#session_regenerate_id();
}
}
A little message class can be built on that pretty easily.
I'm at this crossroad myself and I've considered all options extensively.
How about storing two browser
cookies, one called page and the
other called message.
On redirect you overwrite the cookie.
When the page loads you check if
said cookie exists (in the http
headers sent by the client).
Check if it's for that page, if it
is, store the message in a variable
and unset the cookies.
If it's not for that page, ignore
it, it will be output on the other
tab that is loading or if it is for
a page that for some reason never
unset the cookie it will eventually
expire.
This avoids using the database and session cookies.