I'm making somewhat of a "module" that gets included into another unrelated PHP application. In my "module" I need to use sessions. However, I get the 'session has already been started...' exception. The application that my "module" is included into is starting the session. If I cannot disable sessions in this application, what are my options? I'd like to use Zend_Session, but it seems upon first glance that it is not possible. However, maybe there is another way? Any ideas?
Thanks!
With PHP’s session implementation, there can only be one session at a time. You can use session_id to check if there currently is a session:
if (session_id() === '') {
// no current session
}
Now if there is already an active session, you could end it with session_write_close, change the session ID’s name with session_name to avoid conflicts, start your session, and restore the old session when done:
$oldName = session_name();
if (session_id() !== '') {
session_write_close();
}
session_name('APPSID');
session_start();
// your session stuff …
session_write_close();
session_name($oldName);
session_start();
The only problem with this is that PHP’s session implementation does only send the session ID of the last started session back to the client. So you would need to set the transparent session ID (try output_add_rewrite_var) and/or session cookie (see setcookie) on your own.
Try setting a custom "name" parameter for your application.
The default is PHPSESSID. You can change it to PHPSESSID_MYAPP to avoid conflicts with the other app.
Add the following code before you want to use the Session feature:
#session_start();
Related
Newbie question, but I'm wondering if I'm missing something elementary here.
If I register a session variable in a page - isn't this variable supposed to be accessible from another page on the same site?
First, I register a variable in the file session_var_register.php:
<?php
$_SESSION["myusername"] = 'user';
if (isset($_SESSION['myusername'])) {
echo 'Session var myusername is set to '.$_SESSION['myusername'];
}
?>
When I open this page, it writes:
Session var myusername is set to user
As expected.
Then I open another tab and another page, check_session_var.php:
<?php
if (isset($_SESSION['myusername'])) {
echo 'Session var myusername is set to '.$_SESSION['myusername'];
}
?>
This page is blank.
Isn't the point of a session variable that it should be accessible in the browser session, until the session is programatically destroyed or the browser closed?
I'm using IE 8 and Firefox 24, btw. Identical results.
You forgot
session_start()
On top, before using
$_SESSION
PS: Remember to call session_start() in every page you want to use $_SESSION.
The PHP docs state that you must call session_start() to start or resume a PHP session. This must be done before you try to access or use session variables. Read more here.
session_start();
Your session variables will be available on different pages of the same site but on top of each of these pages you must have at least:
session_start();
It works but not in all cases. You must also use the same session name (essentially a cookie name that stores id of your session) on all pages. Moreover cookies (which are essential (mostly) for sessions to work) may be made visible only in specific directory. So if for example you share the same host with other guys that use sessions too you do not want to see their variables and vice versa so you may want to have sth like that:
1) session_name( 'my_session_id' );
2) session_set_cookie_params( 0, '/my_dir', $_SERVER['HTTP_HOST'], false, true );
3) session_start();
You may also want to see your session variables on other servers and in such case custom session handlers may be useful. Take a day or two to implement yourself - great way to understand how sessions work hence I recommend.
Method
session_start();
Description
session_start() creates a session or resumes the current one based on a session identifier >passed via a GET or POST request, or passed via a cookie.
Usage in your case (and in the most of cases):
Put it before the $_SESSION usage.
Reference: session_start()
First Of all start session on that page
session_start();
your page like this way
<?php
session_start();
if (isset($_SESSION['myusername'])) {
echo 'Session var myusername is set to '.$_SESSION['myusername'];
}
?>
I want to implement a PHP custom session ID, while avoiding calling session_start() more than necessary.
Basically, one simple algorithm is
session_start();
if ( ! isset( $_SESSION['MyStuff'] )) {
session_write_close();
session_id( generate_my_id() );
session_start();
}
$_SESSION['MyStuff'] = some stuff...;
In case the session expired or didn't exist in the first place, the first session_start() will create its own ID and send a cookie to the browser. Then the session is ended, and another one is created, with another cookie sending (plus the overhead of creating and closing a session file).
Another solution would be to test if a PHPSESSID cookie exists, and its value having the format according to the - home cooked - generate_my_id() function - then test again if the $_SESSION value. But if the session expired (no $_SESSION['MyStuff']), again, a non-necessary session_start() will have been called.
So the question is, based on my observations, actually two questions
is there a way to specify how PHP should create the session ID (doesn't seem to be possible), before calling session_start()?
is there a way to check if session_start() will have to create a new session, or will just use the one available server side? (that would eliminate its first call)
Any good alternative is welcome.
Edit
Clarification about what is a custom id.
The session ID is the string key used by PHP to retrieve a session on the server, each user having a different key. That key is usually stored in a cookie, then the browser sends that cookie with its requests to the server / PHP to "connect" to the session.
PHP sets the session ID key automatically, based on MD5(user-and-time-related-data) or SHA1(same-related-data), based on settings. Thus, the session ID is either a MD5 or a SHA1 key - hopefully unique.
A custom ID is a key created manually by the programmer (me), bypassing the md5/sha1 creation.
Yes, from 5.3 onwards you can specify the hash algorithm with session.hash_function when a session id gets generated; using your own hash algorithm is not recommended, especially since the ones that come with hash are extensively tested for spread, speed, collisions, etc.
Since cookies are typically used to perpetuate sessions, you can use that information to determine whether session_start() will create a new session or not.
The following illustrates a way to minimize the number of session_start() statements you need; it's deduced from existing code (which is OO):
do {
// discover session by cookie
if (isset($_COOKIE[session_name()])) {
session_start();
// validate session contents
if (!isset($_SESSION['MyStuff'])) {
// destroy session and regenerate id
session_destroy();
session_regenerate_id(true); // skip this if you generate your own
} else {
// validation passed, no need to populate
break;
}
}
// populate new session
// you can use session_id($your_id) here
session_start();
$_SESSION['MyStuff'] = 'foobar';
} while (false);
The strange do { } while loop is just a glorified goto so that you can skip the second session_start() if the current session is valid.
Late answer but check the changelog for PHP v5.5.1
It refers a new interface called SessionIdInterface which only method is create_sid, although it's still undocumented.
interface SessionIdInterface {
public function create_sid ();
}
I have a situation where I've started a session with:
session_id( $consistent_session_name_for_user );
session_start();
$_SESSION['key'] = $value;
but then later I decide I don't actually want to "commit" (write) this session. PHP doesn't seem to have any kind of session_abort_write() function. I don't want to destroy the session variables from prior script runs, so I can't use session_destroy()
I tried session_id(""), but that call fails. I could "redirect" the session so it writes to another session, like session_id("trash"), but that would cause a lot of PHP (Apache) connections to try to write to the same session "file", which I want to avoid.
I'm highly simplifying the problem here, we're actually storing sessions in Memcached and this is a complex codebase. So I don't want to be sending unnecessary "trash" sessions to the Memcached server all the time.
From PHP.net,
session_regenerate_id
will replace the current session id with a new one, and keep the
current session information.
session_unset will free all registered variables
session_unregister ( string $name ) will unregister a specific variable
I haven't actually determined if this method prevents writing the session to the session store, but here's the solution I finally used:
session_id( 'trash' ); // or call session_regenerate_id() as someone else suggested
$_SESSION = array(); // clear the session variables for 'trash'.
I'm hoping this has the effect that nothing will get written, but I'm guessing it still will write a blank file, because PHP can't know that sess_trash isn't already there.
If you want to completely avoid writing the session, you'll have to use a custom session handler in PHP and set a global flag to prevent writing the session.
You could probably use something with session_set_save_handler to put dummy functions in for session handling.
<?php
function fakeIt() {
return true;
}
session_set_save_handler("fakeIt", "fakeIt", "fakeIt", "fakeIt", "fakeIt", "fakeIt");
There is session_write_close(). It dumps out the session array to storage and then "closes" it - $_SESSION will still be available and read/writeable, but any changes will no longer be saved, unless you do a session_start() again later on within the script.
For logging out a user from my website, I am redirecting the page to logout.php where I am using session_destroy() function. Even there also, logout functionality is not working without session_start() function. By adding session_start() function before session_destroy() function, I am able to logout the user successfully.
Why do I need to use session_start() function everytime and in every page where I am doing something related to sessions?
session_destroy() destroys the active session. If you do not initialized the session, there will be nothing to be destroyed.
Why do I need to use session_start() function everytime and in every page where I am doing something related to sessions?
So PHP knows which session to destroy. session_start() looks whether a session cookie or ID is present. Only with that information can you destroy it.
In the default configuration, PHP Sessions operate off of the hard disk. PHP asks you to explicitly tell it when you need this support to avoid unnecessary disk IO.
session_start() also tells PHP to find out if the user's session exists.
session_start() creates a session or
resumes the current one based on a
session identifier passed via a GET or
POST request, or passed via a cookie.
as per http://php.net/manual/en/function.session-start.php
Essentially by calling session_start(), PHP reads the header and cross references that session ID to what is on your system(file system/database/etc), which can then populate the $_SESSION that is relavent to that specific user. Which in turn allows you to call session_destroy() because it knows what session to actually destroy.
consider session_start() as your way of telling the php engine.... that you want to work with sessions.
and, as i understand it, always make that to be the first line ever in php page.
I was confused with the usage of session_start(); and every time I was using a session variable, I was calling session_start. Precisely, I had session_start(); more than once on each page (without even calling session_destroy()). For example,
// 1st call
session_start();
if (!isset($_SESSION['UserID']))
{
// Do something
}
else
{
// Do something else
}
// .... some other code
// 2nd call
session_start();
if (!isset($_SESSION['UserID']))
{
// Do something totally different
}
else
{
// Do something else totally different
}
This was creating a performance issue for me. So I ended up calling session_start(); just once at the very top of the page and everything seems to be working fine.
You have to call session_start once (and only once) in every file you want sessions to work in.
A common approach allowing you to only call it once is to have a dispatcher file as your index.php; call session_start in here and have this page include others based on the url's $_GET.
<?php
session_start();
if(isset($_GET['page']) && file_exists('pages/'.$_GET['page'].'.php') {
include $_GET['page'];
}
?>
//www.mysite.com/index.php?page=fish will display /pages/fish.php with session access
I have two apps that I'm trying to unify. One was written by me and another is a CMS I am using. My authentication happens in the one I coded and I'd like my CMS to know that information. The problem is that the CMS uses one session name, and my app uses another. I don't want to make them use the same one due to possible namespace conflicts but I'd still like to get this information.
Is it possible to switch session names in the middle of a request? For example, doing something like this in the CMS:
//session_start already called by cms by here
$oldSession = session_name();
session_name("SESSION_NAME_OF_MY_APP");
session_start();
//get values needed
session_name($oldSession);
session_start();
Would something like this work? I can't find anything in the docs or on the web if something like this would work after session_start() has been called. Tips?
Baring this solution, I've been considering just developing a Web Service to get the information, but obviously just getting it from the session would be preferable as that information is already available.
Thanks!
Here is a working example how to switch between sessions:
session_id('my1session');
session_start();
echo ini_get('session.name').'<br>';
echo '------------------------<br>';
$_SESSION['value'] = 'Hello world!';
echo session_id().'<br>';
echo $_SESSION['value'].'<br>';
session_write_close();
session_id('my2session');
session_start();
$_SESSION['value'] = 'Buy world!';
echo '------------------------<br>';
echo session_id().'<br>';
echo $_SESSION['value'].'<br>';
session_write_close();
session_id('my1session');
session_start();
echo '------------------------<br>';
echo $_SESSION['value'];
Log will look like:
PHPSESSID
------------------------
my1session
Hello world!
------------------------
my2session
Buy world!
------------------------
Hello world!
So, as you can see, session variables saved and restored while changing session.
Note: the answer below is not correct, please don't use or vote up. I've left it here as a place for discussion
You solution should work (not that I ever tried something like that), except that you have to manually close the previous session before any call to session_name() as otherwise it will silently fail.
You can try something like this:
session_write_close();
$oldsession = session_name("MY_OTHER_APP_SESSION");
session_start();
$varIneed = $_SESSION['var-I-need'];
session_write_close();
session_name($oldsession);
session_start;
There's no need to actually mess with the session ID value, either through PHP session ID manipulation routines or through manual cookie mangling - PHP will take care of all that itself and you shouldn't mess with that.
I've been working on perfecting this and here is what I've come up with. I switch to a parent session using session names in my child apps and then back to my child app's session. The solution creates the parent session if it does not exist.
$current_session_id = session_id();
$current_session_name = session_name();
session_write_close();
$parent_session_name = 'NameOfParentSession';
// Does parent session exist?
if (isset($_COOKIE[$parent_session_name])) {
session_id($_COOKIE[$parent_session_name]);
session_name($parent_session_name);
session_start();
} else {
session_name($parent_session_name);
session_start();
$success = session_regenerate_id(true);
}
$parent_session_id = session_id();
// Do some stuff with the parent $_SESSION
// Switch back to app's session
session_write_close();
session_id($current_session_id);
session_name($current_session_name);
session_start();
session_regenerate _id()
The manual explains this pretty well but here's some example from the manual
session_start();
$old_sessionid = session_id();
session_regenerate_id();
$new_sessionid = session_id();
echo "Old Session: $old_sessionid<br />";
echo "New Session: $new_sessionid<br />";
print_r($_SESSION);
You should use session_id, you can use it to set / get the session id (or name).
So instead of using session_name (in your pseudo code), use session_id.
Zend_Session offers Namespacing for sessions.
Zend_Session_Namespace instances are
accessor objects for namespaced slices
of $_SESSION. The Zend_Session
component wraps the existing PHP
ext/session with an administration and
management interface, as well as
providing an API for
Zend_Session_Namespace to persist
session namespaces.
Zend_Session_Namespace provides a
standardized, object-oriented
interface for working with namespaces
persisted inside PHP's standard
session mechanism. Support exists for
both anonymous and authenticated
(e.g., "login") session namespaces.
It is possible. But I think you have to do the session handling yourself:
session_name('foo');
// start first session
session_start();
// …
// close first session
session_write_close();
session_name('bar');
// obtain session id for the second session
if (ini_get('session.use_cookies') && isset($_COOKIE[session_name()])) {
session_id($_COOKIE[session_naem()]);
} else if (ini_get('session.use_trans_sid') && !ini_get('session.use_only_cookies') && isset($_REQUEST[session_name()])) {
session_id($_REQUEST[session_naem()]);
}
// start second session
session_start();
// …
But note that you might do some of the other session handling things like cookie setting as well. I don’t know if PHP does this in this case too.