The site I'm renovating writes session data to their database using the session_set_save_handler function as follows:
session_set_save_handler (array(&$ses_class, '_open'),
array(&$ses_class, '_close'),
array(&$ses_class, '_read'),
array(&$ses_class, '_write'),
array(&$ses_class, '_destroy'),
array(&$ses_class, '_gc'));
I have the _open, _close, etc. functions log any calls they receive to the error_log
file but upon opening I only see calls to _write and _close. Why would these be the
only functions being called?
Also, depending on the page I'm on the _write function can or cannot write to the
database, returning an 'Access denied...(using password: NO)' mysql_error.
I'm at a loss. Any good resources I should look at?
You're definitely calling session_start() after session_set_save_handler?
'Access denied...(using password: NO)'
mysql_error.
That usually indicates that the the database hasn't been connected to, so PHP is attempting to connect with the default username and no password, which 99.999% of the time doesn't work. E.g. mysql_query() is being called before mysql_connect()
Sounds like problems with the ordering of the code.
PHP 5.1 had a bug where objects were destroyed before the session was closed. My solution was to create a destructor function for my DB object that explicitly closed the session.
The other problem is that you might have code starting up the session before the database connection is initialized. That requires carefully tracing through your includes looking for global code unexpectedly calling $_SESSION. This will also play hop with your session_set_save_handler() call. I had that problem in a previous job. The only solution was to re-order how things initialized so they didn't happen in the wrong order.
My question was two-part and this answer corresponds to the second part, the issue of not being able to write to the database.
The session object the site I'm working on uses did not store the database resource and so database connections made downstream in the code were clobbering the session's connection. I created an object variable to store the database resource and explicitly referred to it in all session queries, i.e.
$result = mysql_query($query)
became
$result = mysql_query($query, $this -> db);
and I'm now able to write to the database just fine.
Related
I'm facing a problem which I don't know how to solve. Let's start explaining:
I've got the following class:
class MyClass{
function MyClass($mysql_dbcon){
$this->mysql_dbcon = $mysql_dbcon;
}
function execute(){
include("myscript.php");
}
}
myscript.php is an HTML template which uses Ajax to comunicate with other PHP scripts. Since these other PHP scripts aren't included directly in the class I'm not able to get the variable mysql_dbcon and use a different connection for each instance. Let's guess I've got the following instances:
$i1 = new Myclass($dbcon1);
$i1->execute();
$i2 = new Myclass($dbcon2);
$i2->execute();
Both instances will execute an Ajax function which call other processing scripts but these scripts can't access the instance's mysql_dbcon variable due to they're independent script executions.
How can I solve this? Is it correct to store the MySQL connection in $_SESSION so all the scripts can access it? Maybe this:
$_SESSION['instance_identifier'] = $this->mysql_dbcon;
What I want to achieve
I want to create a class in which the developer can set a MySQL connection and each instance can access to different databases so each instance will show data from different databases. The problem is the dynamic loading of that data.
Thanks in advance
You cannot solve it.
but this script can't access the instance's mysql_dbcon variable due to it's an independent script execution
Exactly. Period. You're starting an entirely different PHP script which shares absolutely nothing with the previous script. In fact, by the time the AJAX request is initiated by the browser, the "existing" MySQL connection will already be torn down and closed since the entire PHP script has already stopped.
"myscript.php" will simply have to open a new connection. You cannot serialise a connection into a session; it's not data which can be represented in a serialised form. This is exactly the same mechanism as any other two independent PHP files, the fact that include and AJAX are involved changes nothing.
Also see https://stackoverflow.com/a/13840431/476
Is it correct to store the MySQL connection in $_SESSION so all the scripts can access it?
No.
I'm facing a problem
You probably aren't, or at least it's not the problem you think it is. It's likely there is no reason for you to need to try to "share" the same database connection across the scripts, even if you could. If you provide more context about why you want to access the same connection, then further advice can be given. There is probably a better way to achieve what you want.
Perhaps you are trying to access one query's result set in different places, in which case the answer would not be trying to share a connection but probably to pass the result set itself.
Additional note about your syntax
class MyClass {
function MyClass($mysql_dbcon) {
Looks like you're using outdated PHP 4 syntax for your constructors. See the manual entry on constructors in PHP 5 for the modern standard.
It's also good practice to define the visibility of your class members using the public/protected/private keywords. See the manual entry on visibility.
I'm trying to save all my session data in the Database and have this class that should handle all that and have used session_set_save_handler to set that up. Now, I don't know if it's because I don't fully understand the whole idea behind that function but the problem I'm running into is that the read() function of my Session handler class is called BEFORE the write() function is. And the reason why that is not good is because read() is trying to look for information in the database that has yet to be written into the database and of course it gets empty results.
So I decided to read the documentation behind session_set_save_handler and it looks like the only time write() is called is when the session is terminated or when PHP is closed. From my perspective this seems pretty useless... why would anyone write() or store this information at the END before they could ever get a chance to retrieve it?
What I'm trying to do is when someone creates a use session, this information is written into the database and whenever I want to check for authentication or lookup user values I want to retrieve said information.
Am I going about this all wrong?? I appreciate any clarification. If anyone needs any code to demonstrate what I'm trying to do I'll update this.
From my perspective this seems pretty useless... why would anyone write() or store this information at the END before they could ever get a chance to retrieve it?
What do you mean before they got a chance to retrieve it?
To retrieve it, the read method is called – and it is called before, so that you already have the info. But somehow this is what you are complaining about …?
Am I right in assuming that you don’t have much understanding of how PHP’s session mechanism works at all?
You call session_start on top of every script. If PHP finds a session id in the parameters passed to the script, it looks for an existing session with that id, and if it finds one, it reads the data from it. From that point on, you can work with that data – PHP has put it into the super-global array $_SESSION for you. You can access it from there, and you can put new data into it or alter the existing data.
And then, when the script ends, or session_write_close is called, the data is written back.
So of course the read function is called before the write function.
I'm using a PHP web application to connect to MySQL, what I would like to do is set the userID of the client who has logged in and then use that MySQL variables within views and functions to limit data returned.
Currently, I'm simply using:-
SET #UserID = 3;
And then referencing this within views/functions.
Is this a suitable and reliable method to do this across multiple concurrent user sessions? Will this be present for the lifetime of that users MySQL connection (or page load) from PHP and I obviously want to ensure no other connections leverage this. It's set on every page load (or MySQL reconnection from my app).
Thanks all!
As it clearly states in the first paragraph of the mysql variables man page: http://dev.mysql.com/doc/refman/5.0/en/user-variables.html
User-defined variables are session-specific. That is, a user variable defined by one client cannot be seen or used by other clients. All variables for a given client session are automatically freed when that client exits.
e.g. they exist while the php<->mysql connection is kept alive, PER connection, and automatically removed when the connection is closed/terminated. Unless you're using persistent connections in PHP (which you shouldn't be anyways), the mysql variables would basically exist for the life of that particular script invocation, and will NOT be available when the same user comes back with another http request later.
So, strictly speaking, what you're doing shouldn't be a problem (each PHP connection exists more-or-less independantly). But, that said, it isn't the best approach.
I think you've got a "if all you have is a hammer, everything looks like a nail" problem. MySQL is not designed with the request lifecycle in mind, and it shouldn't need to be aware of it. PHP, on the other hand, is designed with exactly that idea.
Instead of:
mysqli_query('Set #UserID=' . $id);
$output = mysqli_query('SELECT * FROM FOO WHERE ID=#UserID');
Why not just use bound variables?
I store a resource link identifier (specifically an LDAP connection link) in a global variable and check in my first initialisation to create it only if it's not already in $GLOBALS array.
I bind to the LDAP connection with correct credentials when logging a user in, but when I later try to search LDAP directory, I realise that the connection has lost its state (from the fact that I can't do searches).
Is there a way of keeping an LDAP connection's state across pages? I can't store them in session variables as they can't be serialised.
No, they do not. Just like you always need to connect to the database each request, you'll need to create a new connection to LDAP too.
In essence: every request starts with a clean slate, you'll need to fetch resources, open connections each time.
I debugged and searched for quite a while and I can't figure out what is happening. This is my first time doing a custom session handler, so I'm afraid I'm overlooking something painfully obvious. I want to implement a custom session handler so I can store additional information with the sessions and be able to temporarily disable access to protected areas of the site for certain groups of users.
My login page (which was working fine with basic file-based php sessions), includes a php file with a lot of functions including the session handler functions and my error handler. That included file includes a third file that does the database connection. The connection is made using mysqli_connect() and the resulting link is stored in a variable, $dbc. That same connection is used throughout the site for logging errors, loading/editing site content, etc. I decided to use the same database connection, since it is used already on every page and my session handler will need to be used on almost every page as well. Nowhere in my code do I manually close the database connection, but I think perhaps it is automatically closing somehow.
My functions access the database connection ($dbc) with a global statement. Ex:
function sess_write($id, $data)
{
global $dbc;
...
My open, read, and write functions are supposed to use the variable in this manner. I checked the database connection variable in the open and read functions and it is non-null as expected, but in my write function it suddenly shows up as null. Is PHP doing something between read and write that could potentially be closing that connection? I created a test variable in the same included file that creates the database connection, and used the same global $test; statement in the write function, and that variable appears just fine, so I'm guessing it has something to do with the database being closed. I tried using a second variable to store the database connection (to only be used by the session handler) and that didn't work either. Any ideas? Am I just being dumb as usual?
Per your note, that is correct -- objects will be disposed of before write and close. The traditional workaround for this is to use the register_shutdown_function. PHP 5.4 now has an interface you can use to write a session handler class that simplifies this process. If you implement the interface in a session class, when you pass it to session_set_save_handler() it defaults to setting things up to register the shutdown call for you.