session file - when does it get created exactly? - php

I'm curious to know exactly when the session text file is created? An easy and surface level answer to that would probably be,.. well, when you use session_start(). But is it?
Could it be all the way at the end when the php script ends?
What makes me think that it may be at the end is that I know PHP would not write to the session file everytime you make a change to a session variables while the execution of the page goes on. For example, if you got something like $_SESSION['x'] = $_SESSION['x'] + 1; in a loop, the session file does NOT get modified at each and every iteration of the loop. Only when the PHP scripts is done, then the PHP engine makes a change into the file, to store the final value of the $_SESSION['x'].
With the same taken of logic, I see no reason for PHP engine to create a file as soon as you call the session_start. It could just delay the process.
What that entails is this;
I can start a session with session_start(), set a few session variables, toss them around within functions, using them as globals, and at the end of script, I unset them, and destroy the session and as a result, I assume NO SESSION FILE IS CREATED, thus no overhead associated with creating the session text files is experienced.
I would like to hear your insights in this.
My purpose is to explore the possibilities of using session variables strictly as a temporary place holder to pass global variables left and right - without dealing with file I/O. In fact, I do not need those variables in the next page at all.
In this case, could sessions prove faster than using globals within functions?

Tested and it gets created immediately on session_start. However, session_destroy removes it too. Tested with:
mkdir sess && cd sess
vim main.php
session_save_path(dirname(__FILE__));
session_start();
sleep(5);
session_destroy();
php main.php &
ls # main.php sess_rm4bcun6ear943mf61mdads190
fg # wait for script to end
ls # main.php
There's the answer to your question. Your idea of using _SESSION for global variable purposes is not a good one .. you might as well juse use $GLOBALS. No file IO there.

Related

When and where should I use session_start?

Exactly when and where should I use session_start() in PHP?
For example, say I have a login script that sets a session variable to tell whether or not the user is logged in. Must I then put the session_start() at the top of the script, or only right before I actually set the session variable if the login was successful?
<?php
// session_start(); here?
if (login($username, $password)) {
// session_start(); or here?
$_SESSION["username"] = $username;
}
?>
Another case is this, according to w3schools
Note: The session_start() function must be the very first thing in your document. Before any HTML tags.
As others have said, the absolute requirements of what you must do are:
You must run session_start before you read or write to $_SESSION (otherwise it will just be an ordinary array and not saved anywhere).
You must not run session_start twice during a single script execution (page load) unless you use session_write_close to close it in between.
There is an extra rule that technically has exceptions, but is best treated as absolute:
Do not start the session after you have written any output (echo, HTML outside PHP blocks, etc), because PHP may not be able to send cookies to the browser if the server has already started sending the content.
There are two reasons you might want to avoid starting the session:
PHP locks the session when you open it to avoid two processes writing conflicting data into it, so if you have several requests happening at once, you want to avoid them waiting for each other unless they really need to. For instance, if you're responding to an AJAX request, and don't need any data from the session, don't open it.
As mentioned by symcbean, there is some cost to creating a new session, so if your site is busy with either legitimate or malicious traffic, you might want to serve some landing pages or error messages without starting it at all.
After that, it becomes a matter of style and architecture, but the rule of thumb that covers most of the above is "as soon as possible, if you're sure the page needs it".
Unless you have output buffering enabled, the session_start() must come before anything other than headers are sent to the browser (as it sets a cookie in the header).
It must come before you attempt to reference the $_SESSION data.
In your example there are no html tags being output before either instance - so both would work.
There some cost to opening a session, so if you are doing additional, non-session based validation of the request, then deferring session_start() till these checks have passed does give you a bit more resillience against DOS attacks.
Starting the session at the top of the page is most of the times the best. But if you don't need the session for the whole document/code, you could always put it, as in this example, after the if() clause.
The session_start() function can go anywhere in your code. You should just place it at the beginning of your document for consistency and call it a day. If you have a separate database or config file you are including on all your login/database driven pages, you should place it in there so you don't have to recode it into every page.

Coming from ColdFusion, where and how to set Session Variables in PHP

I've left ColdFusion and trying to get up to speed with PHP. First off, in building an app I'm trying to set an Application variable for the include paths, in CF I would use Application.FilePath = "/myWebApp/" and use to set up all includes template files. In PHP I'm not finding something similar.
I'm also struggling with setting Session specific variables. In CF, I would also set them in the Application.cfc/Application.cfm file as session.mySessionVarName. In PHP I'm not seeing a similar place to put these so they're available throughout the webapp, and the current session.
I thought this may be a common question but I didn't find anything related.
Thank you for your time.
To start a session, sesson_start:
session_start();
add a value to a session:
$_SESSION['name'] = 'value';
End a session, session_destroy:
session_destroy();
Save path for sessions, session_save_path:

PHP Sessions' internal mechanics

From the manuals, I draw that when a php session var is set, it is written to a text file in the session_save_path folder.
I am just curious to find out if this happens as soon as the interpreter hits the line with the session variable or does it ( writing to the text file ) takes place when the PHP interpreter exits processing the file?
For example, if I were to set and update a session variable in two consecutive lines, (as in the example I gave below), does the PHP interpreter saves the files twice back to back?
In other words, which code snippets has the right commenting?
$_SESSION['my_variable']=1; // writes to the session text file
$_SESSION['my_variable']=2; // writes to the session text file again
die(); //
versus
$_SESSION['my_variable']=1; // updates the session file contents in the memory
$_SESSION['my_variable']=2; // updates the session file contents in the memory
die(); // writes to the session text file
Data is written to file if:
session_write_close() is called
the script execution is finished
So provided that you don't do 1), your second assumption is correct.
Writing to the file every time a variable changes would be VERY expensive, because generally speaking accessing and writing to the disk is slow, hence why PHP won't do that. It should be noted however that caching systems such as memcache or redis will store changes as they happen, so it can be a good idea to rely on them when PHP sessions do not suffice in terms of reliability.
The second one, the $_SESSION[...] = ... they just set the value inside your $_SESSION array and die() triggers this function:
session_write_close
(PHP 4 >= 4.0.4, PHP 5)
session_write_close — Write session data and end session
Report a bug Description
void session_write_close ( void ) End the current session and store
session data.
Session data is usually stored after your script terminated without
the need to call session_write_close(), but as session data is locked
to prevent concurrent writes only one script may operate on a session
at any time. When using framesets together with sessions you will
experience the frames loading one by one due to this locking. You can
reduce the time needed to load all the frames by ending the session as
soon as all changes to session variables are done.
http://nl.php.net/manual/en/function.session-write-close.php
So, I tried to test this by doing the following.
test_1.php
session_start();
$_SESSION['my_variable']=1;
sleep(20);
exit;
and
test_2.php
session_start();
var_dump($_SESSION);
Here are the cases I tested:
Executing test_1.php then quickly executing test_2.php.
Result: test_2.php froze until test_1.php finished sleeping.
Executing test_1.php, removing the PHPSESSID cookie and THEN
executing test_2.php.
Result: test_2.php executed right away with no freezing (test_1.php in the meantime was still sleeping) and printed an empty array.
Novice conclusion:
PHP opens a stream to the text file related to that session until the script has finished executing and then it "commits" the changes. (I'm not an experts, so my terms might not be accurate)
Edit: yet another useless test due to not consulting the documentation
but as session data is locked to prevent concurrent writes only one
script may operate on a session at any time
Sessions will be written in cookies or whatever storage you choose only after flushing the setter page. ex:
having pageA and pageB :
setting in pageA :
session["foo"] = "bar";
session["foo"] will be available to pageB only after:
leaving pageA to pageB
or
leaving pageA and refreshing pageB
that considered, the best definition IMHO is the second one.
Happy coding!

Recommended way to detect sessions

I've created a little class to generate thumbnails with an external program (gm from ImageMagick, in case you're interested). The class issues an exec() call to launch gm.exe but I've hit a PHP bug that makes httpd.exe freeze when there are concurrent executions and there is an open PHP session. There is a workaround that looks like this:
session_write_close();
exec('gm convert -resize 100x100 source.jpg target.jpg');
session_start();
So far so good. Now I want to reuse the thumbnail class in other present and future projects. If I want to be able to just drop the code and call it without changes, I need to omit the session workaround when there aren't sessions and I need to do it programmatically. Otherwise, my thumbnailer will have the nasty side effect of starting a session by itself.
How can I properly detect whether there is an active session? Or, in other words, whether the PHP script that is calling my function has issued a call to session_id() and haven't closed or destroyed the session in any fashion so the operating system is probably holding an open handle that is locking the session file so it cannot be accessed by other running processes which can possibly freeze httpd.exe.
I've tried this:
if( session_id() ){
session_write_close();
exec('gm convert -resize 100x100 source.jpg target.jpg');
session_start();
}
But I've noticed that session_id() returns a value if the script ever used sessions, even if they're not active at this point. If the script has closed the session with session_write_close()... my thumbnailer will open it again!
You cant really. It doesn't look like there are any functions to do that. http://www.php.net/manual/en/book.session.php
You could maybe do some analysis of the files in the directory returned by session_save_path(). But you're going to have issues doing that reliably with different platforms and non-standard session handlers.
The only way I found was to use session_regenerate_id(), which will return false if there is no active session. But this has the obvious disadvantage that it might break any scripts coming after that rely on the old session id.
There isn't any method within PHP to do this. I ended up having to do a couple simple wrapper functions that check for a global variable (bleah) which my session-start wrapper function set once the session was started the first time.

two session_starts() hang PHP app

Context: I was going to build app using mod_rewrite (front page loading child pages), but got stuck on loading session_enabled pages from the front controller page.
Problem: The problem is that I use session_start() call twise, PHP page stops responding. Which is strange, the session_start function is harmless and they are called on different pages.
I've narrowed down the problem to this sample:
child.php file:
parent.php file:
Call to parent.php will make browser load infinitely. As soon as you comment one of session_start() calls - it loads instantly.
What is the source of the problem?
I badly need session-enabled pages.
PS I can work it around by including pages, but they rely on URL params, I would like to avoid fixing them for sake of some kind of parameter proxies.
You need to call session_write_close() once you no longer need to write to the session. Currently as both your scripts have the session open for their entire duration, you will only be able to have one running at a time.
From the manual:
Session data is usually stored after
your script terminated without the
need to call session_write_close(),
but as session data is locked to
prevent concurrent writes only one
script may operate on a session at any
time. When using framesets together
with sessions you will experience the
frames loading one by one due to this
locking. You can reduce the time
needed to load all the frames by
ending the session as soon as all
changes to session variables are done.
Besides that only one session can be used at a time. You need to call the session_regenerate_id function to generate a new ID:
if (session_id() != '') {
session_write_close();
}
session_start();
session_regenerate_id();
Otherwise the parent’s session ID would also be used for the child’s session.
Try using session_write_close() before loading your child page.
You can also check if a session is already started and only start a new one if not:
if (!isset($_SESSION)) session_start();
Having two session_starts() in your script is a bad thing anyway.
Why don't you just start the session on your parent.php file (and not child.php)?
Or just child.php and not parent.php
It's a good idea to have one page that is included by all other pages that initializes everything (SQL connect, session start, etc). And then include that page on all others.

Categories