In my application, I am currently storing about 7 pieces of information that are dependent on $_SERVER[‘DOCUMENT_ROOT’] to indicate which system I am running on. These are used extensively throughout the application for such things as secured and unsecured web file base directory name, file directory name, the include file to use for the db connection, etc. So if I am running on a dev machine, I don’t need to change anything to get to the production machine.
I have been told that it is better to store this in constants rather than session variables. I am curious as to what the advantage or disadvantage are. I am already calling a session_start() in every controller and most of the pages that are called by redirected headers.
So if I were to use constants for all of these, I would have to (I assume) create an include file that I would call every time I am calling a session_start() and derive the values again based on $_SERVER[‘DOCUMENT_ROOT’].
My fear is I am misunderstanding the correct use of the session object. Is that true? Any insight would be greatly appreciated. Thanks
I am not sure what you are trying to do.
$_SERVER[‘DOCUMENT_ROOT’] has nothing to do with sessions.
A session stores information about the current user, for example if a the user is online or not…
As I think you mean by a constant, you can set the value of a constant like this
define(“DOC_ROOT”, $_SERVER[‘DOCUMENT_ROOT’]);
and then access DOC_ROOT in your scripts.
Let’s take the example of the db connection file, I currently work in 3 environments, one local for initial development, one online for testing and one online production environment. I have 3 db connection files and depending on the value of $_SERVER[‘DOCUMENT_ROOT’], I know which one to use. So I set the name of that file in a session variable and it is available any time I need to make a db connection, as in include dbfile which has been set to the correct value.
I understand that I could make a file for each environment with the same name and call it that way but that requires making sure the file is not overwritten when uploading the entire site, etc. Using a session var it is done, you set it once at the beginning of the session and forget it, it works no matter what environment and there is no chance of overwriting anything.
If I use a constant, I would need to set it every time I make a db call, which is all through the application. So if I were to use a constant instead of the session var, I assume I would have an include file with constants in it and call that from every controller, function or class. Basically every time I now call a session_start(). First of all, is that how you would handle constants? And second, if that is, how is that easier or better?
I guess what I’m really asking is from a best practices perspective, how and when do you use constants vs. session vars? It seems to me that since I am already calling session_start(), the use of session vars is easier and quicker. I’m pretty sure I’m wrong, I just don’t understand why.
By sticking those values in $_SESSION, all you really save is the overhead of parsing $_SERVER[‘DOCUMENT_ROOT’] and setting those 7 constants appropriately. The trade-off is that you’re putting all those values in the session of every single user, so you’re adding overhead in the form of duplicate data into your session store.
If the performance penalty of parsing $_SERVER[‘DOCUMENT_ROOT’] is really significant, then a cache mechanism (apc, memcache) would probably be more appropriate, since the values aren’t user-specific. If it’s insignificant, then don’t even worry about it…just parse it and create the constants on each request in your front controller or bootstrap. What you’d lose in performance, you’d most likely gain in code simplicity.
Okay, so if I understand this, I should create an include a file that parses my doc root to determine my db file name and include that in the top of each controller file. Access to my pages is all through controllers, so if I do it at the head of each of the controller files that should get me there, right?
Regarding the second point, I don’t currently use cookies for sessions, I just use the $_SESSION[‘var1’] variable and call session_start() at the head of each page. Are you saying I should so all that with cookies instead? Aren’t there security concerns? And if they don’t have cookies enabled, don’t you lose your session info?
yes - at some point early in the logic flow you can simply do a switch statement to include the correct database file, i.e.
switch($_SERVER[‘DOCUMENT_ROOT’]) {
case ‘domain1’:
include domain1-database.php;
break;
// etc
}
I think you might be misunderstanding how sessions work. Sessions are essentially a text file on the server. when you call session_start(), it creates a unique session id and adds a line to the text file with that session id. that same line can contain arrays of information in a serialized format, i.e. if you define $_SESSION[‘somevar’] == ‘foo’, that information is written to the text file in association with the session id. From a client’s computer, they have to send that same session id to the server in order to access the variables assigned to the id. there are 2 ways to do that: either the session id is passed in the query string, or its stored in a cookie. If your urls do not look like http://www.example.com/?PHPSESSID=SA09DF84302J98R234JFN then you have php configured to store the session ids in cookies. Storing the id in cookies is preferred because it lessens the chance of session hijacking.
Ideally you’d just include this script once, in a more central location in your web app instead of including it in a bunch of different places…but that just depends on your overall architecture, which is a different (but important) issue altogether.
Sessions rely on cookies by default (but only to pass the session_id between the client & server), so don’t worry about it. aamonkey was just pointing out another potential weakness of relying on session values to determine which DB to connect to. A browser with cookies disabled, combined with a server that doesn’t pass the session_id as a URL param, will most likely result in a visitor who gets a brand new session created each time he hits your site. So the DB would probably get chosen properly, and even stored in the session file on the server properly but the visitor wouldn’t be able do much else since he won’t have a session_id to identify him.
And the fog just lifted. I think I got it now. And yes in my case I use a session var to determine if all this has been processed and set so if the session id changed, I would just reprocess it but I see the weakness in that now. Thanks
Regarding the calling it in a more central location, let’s go there for a second. My architecture is such that it starts with a home index page and then there are ‘subject’ directories under that each with it’s own controller index.php. Then there are classes and includes that are in two other directories. So I’m thinking I have to call it at least for each controller or ‘entry point’ into the system and also after any header redirects if I use the information on the page creation scripts. Is that not the proper way to set up the overall architecture?
You’ll want to keep it as “high” or early as you can in flow of your app, like aamonkey suggests, i.e., as close to the start of the request as possible, though that depends on all the information you really need access to. For things like the database, since it only depends on the environment (dev, production, etc), not the specific request (/some/section/of/content), you’d want to set it in your root index.php. The only reason to wait until a specific page to set one of these values is if the value actually depends on the content of page that was requested. It might help to show us what these 7 values are that you are using…just dump the code that parses the docroot.
Yes - if you have multiple entry points you would need to include all your startup / environment settings at each entry point. Ideally (as cholmon pointed out) you would only have one entry point and that would call the appropriate controller.
If I set it in my root index the first time someone comes in to the site and I then present them a home page, the variable is lost at that point once the page loads, right? So if they click a link that goes to the My_Account section controller, I need to re-initialize it, correct?
Are you suggesting that the request for the My_Account page, and any other pages for that matter, should first come through a central controller and then be sent on their way? Wouldn’t that be huge? Or am I missing the point?
You can look up the front controller pattern, but it can be implemented very simply - you could even do it procedural style like this:
<?php
// index.php file - every request hits this page
// using mod-rewrite, urls like http://www.example.com/my-account/ get sent as http://www.example.com?controller=MyAccount
// note that this is a simple example devoid of any checking of the $_GET['controller'] variable
include('important-configuration-and-database-connections-and-stuff.php');
$controller = (class_exists($_GET['controller'])) ? $_GET['controller'] : 'DefaultController';
include ($controller.'.php');
$controller = new $controller;
$controller->run();
Just a quick update. I went out and did some research and reading on the front controller pattern and implemented your recommendation and played with that and got it working okay but found myself heading in a direction that is, at least currently, outside my comfort zone. Also, I don’t really see enough performance or maintenance benefits to undertake the curve. I am changing over to using constants where beneficial and reviewing my use of session variables to make sure that is the best way to go.
One more question, do you code applications for people who don’t have cookies turned on? I am assuming if they don’t have cookies turned on and your system is a log in based system, there is no way to keep them logged in, correct?
Again, thanks for the patience and help. It was very useful and a great learning experience and by the time I get ready for the project after this one, I will try to incorporate more of it.
It depends on your PHP configuration. There’s a setting in your php.ini called “session.use_only_cookies”. If this is set to 1 (which is also the default setting), users won’t be able to login if they have cookies disabled because PHP won’t accept GET or POST session ids. If you change the setting to ‘0’, PHP will also accept session ids passed by GET and POST, and it will automatically switch to them in the case that a user has his cookies disabled.