/    Sign up×
Community /Pin to ProfileBookmark

Is $_SESSION still a thing in PHP 7?

Okay, so I built an app on our dev server, which is running PHP 5.4.16, and when IT set up a production server it was running PHP 7.2; now I’m sure I’m in for a steep learning curve and plenty of debugging, but this first one has been a real hair-jerker: After spending hours pouring over my code, throwing error_logs everywhere, and scouring the interwebz praying for a clue, I eventually came to the conclusion that apparently, something has changed between v5 and v7 in how PHP handles sessions. My theory appears to be validated by these two pages I threw together:
`//a.php
<?php
session_start();
$_SESSION[“test”] = “Testing sessions.”;
var_dump($_
SESSION);

// b.php
<?php
session_start();
var_dump($_SESSION);`

The first one prints: array(1) { [“test”]=> string(17) “Testing sessions.” }
The second prints: array(0) { }

I’ve confirmed that the session settings (in php.ini) are the same on dev and production, and phpinfo() says sessions are enabled. So………..???????? while(true) { $frustration++; $hair–; } lol

Any ideas?

EDIT: After further struggleshooting, I also discovered that session_id is returning a different string for every page (even if i.e. refresh a.php a bunch of times). This makes about as much sense as multiplying 3.14159 * the square root of cheese, but whatever’s got PHP’s bits in a bunch, I’m sure someone somewhere understands it. πŸ˜€

to post a comment
PHP

16 Comments(s) ↴

Copy linkTweet thisAlerts:
@NogDogJan 26.2021 β€”Β > @mfox#1627207 I also discovered that session_id is returning a different string for every page

Well, that's going to be a problem, so need to figure out why. First thing I'd check is the session cookie lifetime, I guess? Maybe add this to your debug scripts after the session_start():
<i>
</i>echo "&lt;pre&gt;".print_r(session_get_cookie_params(), 1)."&lt;/pre&gt;";
Copy linkTweet thisAlerts:
@mfoxauthorJan 26.2021 β€”Β That gave me:

Array<br/>
(<br/>
[lifetime] =&gt; 0<br/>
[path] =&gt; /<br/>
[domain] =&gt; <br/>
[secure] =&gt; <br/>
[httponly] =&gt; <br/>
)


Now lifetime=0 is a bit of a red flag, though the bottom line is I have no idea what these settings represent. We're waiting on an SSL cert from IT, so I guess "secure" and "http_only" could be involved?

**EDIT:** Looked up the function you suggested in the PHP docs, and it looks like those are the default values... still not sure what to do about it tho. I've played with all these settings in php.ini and they don't seem to make a difference.
Copy linkTweet thisAlerts:
@NogDogJan 26.2021 β€”Β > @mfox#1627211 lifetime=0 is a bit of a red flag,

0 actually means no expiration, so that shouldn't be a problem. path should be fine (I think). domain is probably okay, unless it's possible a user might hit yourdomain.com sometimes and www.yourdomain.com at other times, in which case you'd probably want domain to be ".yourdomain.com" (note the leading dot to basically say "include sub-domains").
Copy linkTweet thisAlerts:
@mfoxauthorJan 27.2021 β€”Β Yeah, I've been over the docs on those 4 values in php.ini, and didn't see anything about them affecting sessions. didn't think the www in the domain is the issue (but thanks for the info - good to know a wildcard will work there if that comes up). Anyway, they just upgraded my dev server to PHP 7, and reinstalled PDO, and it works fine! So it's definitely something external (not my code). So let me ask you this: besides php.ini, what other settings could be affecting sessions? Apache? idk the first thing about Apache's role in the "big picture" scheme of things so I wouldn't be surprised lol.
Copy linkTweet thisAlerts:
@NogDogJan 27.2021 β€”Β To be embarrassingly honest, I have very little experience with PHP 7 in any non-trivial context. The only sizeable PHP app I work on is still 5.6...and whenever we start looking into what it would take to migrate to a recent 7.x version, we get sad and decide to worry about more urgent issues. :(

If you haven't already, maybe a little temporary page to do a phpinfo() might help confirm which php.ini file is being used, show stuff about session settings, and so forth that might be helpful. (Sorry I can't be more helpful.)
<i>
</i>&lt;?php
phpinfo();
Copy linkTweet thisAlerts:
@mfoxauthorJan 27.2021 β€”Β Hey, no worries! I appreciate all your suggestions to help troubleshoot this. At this point I'm thoroughly convinced that it's not php.ini; I copied over what I had in dev to the new one, restarted Apache, and... same deal (and yes, I backed up what was on the other one lol). phpinfo() says that I'm editing the right file (/etc/php.ini) so idk how it could possibly be *that* file. But phpinfo() did show me some other things that might help:

**Scan this dir for additional .ini files:** /etc/php.d

**Additional .ini files parsed :** /etc/php.d/20-bz2.ini, /etc/php.d/20-calendar.ini, /etc/php.d/20-ctype.ini, /etc/php.d/20-curl.ini, /etc/php.d/20-exif.ini, /etc/php.d/20-fileinfo.ini, /etc/php.d/20-ftp.ini, /etc/php.d/20-gettext.ini, /etc/php.d/20-iconv.ini, /etc/php.d/20-json.ini, /etc/php.d/20-mysqlnd.ini, /etc/php.d/20-pdo.ini, /etc/php.d/20-phar.ini, /etc/php.d/20-sockets.ini, /etc/php.d/20-sqlite3.ini, /etc/php.d/20-tokenizer.ini, /etc/php.d/30-mysqli.ini, /etc/php.d/30-pdo_mysql.ini, /etc/php.d/30-pdo_sqlite.ini

Then under "session":

**Session Support:** enabled

**Registered save handlers:** files user

**Registered serializer handlers:** php_serialize php php_binary

**session.auto_start:** Off

**session.cache_expire:** 180

**session.cache_limiter:** nocache

**session.cookie_domain:** no value

**session.cookie_httponly:** no value

**session.cookie_lifetime:** 0

**session.cookie_path:** /

**session.cookie_secure:** 0

**session.gc_divisor:** 1000

**session.gc_maxlifetime:** 1440

**session.gc_probability:** 1

**session.lazy_write:** On

**session.name:** MyAppName

**session.referer_check:** no value

**session.save_handler:** files

**session.save_path:** /var/lib/php/session (local), no value (master)

**session.serialize_handler:** php

**session.sid_bits_per_character:** 5

**session.sid_length:** 26

**session.upload_progress.cleanup:** On

**session.upload_progress.enabled:** On

**session.upload_progress.freq:** 1%

**session.upload_progress.min_freq:** 1

**session.upload_progress.name:** PHP_SESSION_UPLOAD_PROGRESS

**session.upload_progress.prefix:** upload_progress_

**session.use_cookies:** 1

**session.use_only_cookies:** 1

**session.use_strict_mode:** 0

**session.use_trans_sid:** 0

This is by far (also a bit embarrassingly) the deepest I've ever gotten into the php.ini file. Now I'm sure once we get an SSL cert set up I'll want to change session.cookie_secure to 1, and there are probably a bunch of other settings I don't understand yet. But anyway, it looks like there's a TON of other config files it reads - could it be one of those?

**EDIT:** Another interesting slice of random: "session.save_path" is set to "/var/lib/php/session" (local), and "no value" (master). But I just looked at /var/www/cgi-bin (where I've seen session data before) and there were a bunch of files there with my session variables. Could that be it? **Edit 2:** Tried changing it, restarting Apache again, etc. No dice, changed it back. **Edit 3:** Even stranger: I looked at the cookie in my browser (in the response headers) and it said: "Set-Cookie

MyAppName=2m08jle31u00k6bvsrniq9m530; path=/;HttpOnly;Secure"

But doesn't php.ini say cookie_httponly and cookie_secure are off?
Copy linkTweet thisAlerts:
@NogDogJan 27.2021 β€”Β Might be interesting to try this:
<i>
</i>$session_config = ini_get_all('session');
echo "&lt;pre&gt;".print_r($session_config, true)."&lt;/pre&gt;";

Theoretically that would show any settings that have been overruled (such as via .htaccess). My eye was drawn to the session save path as well, as that does need to be read/writable by whatever server user is actually running the PHP stuff (typically nobody or apache under Apache).

Also, if you haven't already tried it, the good old "turn on all errors" might reveal something:
<i>
</i>&lt;?php
ini_set('display_errors', true); // turn off in production
error_reporting(E_ALL);
session_start();
// etc....

🤞
Copy linkTweet thisAlerts:
@mfoxauthorJan 27.2021 β€”Β wow, okay, so that gave me:

Array<br/>
(<br/>
[session.auto_start] =&gt; Array<br/>
(<br/>
[global_value] =&gt; 0<br/>
[local_value] =&gt; 0<br/>
[access] =&gt; 2<br/>
)

<i> </i><CODE>[session.cache_expire] =&gt; Array
<i> </i> (
<i> </i> [global_value] =&gt; 180
<i> </i> [local_value] =&gt; 180
<i> </i> [access] =&gt; 7
<i> </i> )

<i> </i>[session.cache_limiter] =&gt; Array
<i> </i> (
<i> </i> [global_value] =&gt; nocache
<i> </i> [local_value] =&gt; nocache
<i> </i> [access] =&gt; 7
<i> </i> )

<i> </i>[session.cookie_domain] =&gt; Array
<i> </i> (
<i> </i> [global_value] =&gt;
<i> </i> [local_value] =&gt;
<i> </i> [access] =&gt; 7
<i> </i> )

<i> </i>[session.cookie_httponly] =&gt; Array
<i> </i> (
<i> </i> [global_value] =&gt;
<i> </i> [local_value] =&gt;
<i> </i> [access] =&gt; 7
<i> </i> )

<i> </i>[session.cookie_lifetime] =&gt; Array
<i> </i> (
<i> </i> [global_value] =&gt; 0
<i> </i> [local_value] =&gt; 0
<i> </i> [access] =&gt; 7
<i> </i> )

<i> </i>[session.cookie_path] =&gt; Array
<i> </i> (
<i> </i> [global_value] =&gt; /
<i> </i> [local_value] =&gt; /
<i> </i> [access] =&gt; 7
<i> </i> )

<i> </i>[session.cookie_secure] =&gt; Array
<i> </i> (
<i> </i> [global_value] =&gt; 0
<i> </i> [local_value] =&gt; 0
<i> </i> [access] =&gt; 7
<i> </i> )

<i> </i>[session.gc_divisor] =&gt; Array
<i> </i> (
<i> </i> [global_value] =&gt; 1000
<i> </i> [local_value] =&gt; 1000
<i> </i> [access] =&gt; 7
<i> </i> )

<i> </i>[session.gc_maxlifetime] =&gt; Array
<i> </i> (
<i> </i> [global_value] =&gt; 1440
<i> </i> [local_value] =&gt; 1440
<i> </i> [access] =&gt; 7
<i> </i> )

<i> </i>[session.gc_probability] =&gt; Array
<i> </i> (
<i> </i> [global_value] =&gt; 1
<i> </i> [local_value] =&gt; 1
<i> </i> [access] =&gt; 7
<i> </i> )

<i> </i>[session.lazy_write] =&gt; Array
<i> </i> (
<i> </i> [global_value] =&gt; 1
<i> </i> [local_value] =&gt; 1
<i> </i> [access] =&gt; 7
<i> </i> )

<i> </i>[session.name] =&gt; Array
<i> </i> (
<i> </i> [global_value] =&gt; MyAppName
<i> </i> [local_value] =&gt; MyAppName
<i> </i> [access] =&gt; 7
<i> </i> )

<i> </i>[session.referer_check] =&gt; Array
<i> </i> (
<i> </i> [global_value] =&gt;
<i> </i> [local_value] =&gt;
<i> </i> [access] =&gt; 7
<i> </i> )

<i> </i>[session.save_handler] =&gt; Array
<i> </i> (
<i> </i> [global_value] =&gt; files
<i> </i> [local_value] =&gt; files
<i> </i> [access] =&gt; 7
<i> </i> )

<i> </i>[session.save_path] =&gt; Array
<i> </i> (
<i> </i> [global_value] =&gt;
<i> </i> [local_value] =&gt; /var/lib/php/session
<i> </i> [access] =&gt; 7
<i> </i> )

<i> </i>[session.serialize_handler] =&gt; Array
<i> </i> (
<i> </i> [global_value] =&gt; php
<i> </i> [local_value] =&gt; php
<i> </i> [access] =&gt; 7
<i> </i> )

<i> </i>[session.sid_bits_per_character] =&gt; Array
<i> </i> (
<i> </i> [global_value] =&gt; 5
<i> </i> [local_value] =&gt; 5
<i> </i> [access] =&gt; 7
<i> </i> )

<i> </i>[session.sid_length] =&gt; Array
<i> </i> (
<i> </i> [global_value] =&gt; 26
<i> </i> [local_value] =&gt; 26
<i> </i> [access] =&gt; 7
<i> </i> )

<i> </i>[session.upload_progress.cleanup] =&gt; Array
<i> </i> (
<i> </i> [global_value] =&gt; 1
<i> </i> [local_value] =&gt; 1
<i> </i> [access] =&gt; 2
<i> </i> )

<i> </i>[session.upload_progress.enabled] =&gt; Array
<i> </i> (
<i> </i> [global_value] =&gt; 1
<i> </i> [local_value] =&gt; 1
<i> </i> [access] =&gt; 2
<i> </i> )

<i> </i>[session.upload_progress.freq] =&gt; Array
<i> </i> (
<i> </i> [global_value] =&gt; 1%
<i> </i> [local_value] =&gt; 1%
<i> </i> [access] =&gt; 2
<i> </i> )

<i> </i>[session.upload_progress.min_freq] =&gt; Array
<i> </i> (
<i> </i> [global_value] =&gt; 1
<i> </i> [local_value] =&gt; 1
<i> </i> [access] =&gt; 2
<i> </i> )

<i> </i>[session.upload_progress.name] =&gt; Array
<i> </i> (
<i> </i> [global_value] =&gt; PHP_SESSION_UPLOAD_PROGRESS
<i> </i> [local_value] =&gt; PHP_SESSION_UPLOAD_PROGRESS
<i> </i> [access] =&gt; 2
<i> </i> )

<i> </i>[session.upload_progress.prefix] =&gt; Array
<i> </i> (
<i> </i> [global_value] =&gt; upload_progress_
<i> </i> [local_value] =&gt; upload_progress_
<i> </i> [access] =&gt; 2
<i> </i> )

<i> </i>[session.use_cookies] =&gt; Array
<i> </i> (
<i> </i> [global_value] =&gt; 1
<i> </i> [local_value] =&gt; 1
<i> </i> [access] =&gt; 7
<i> </i> )

<i> </i>[session.use_only_cookies] =&gt; Array
<i> </i> (
<i> </i> [global_value] =&gt; 1
<i> </i> [local_value] =&gt; 1
<i> </i> [access] =&gt; 7
<i> </i> )

<i> </i>[session.use_strict_mode] =&gt; Array
<i> </i> (
<i> </i> [global_value] =&gt; 0
<i> </i> [local_value] =&gt; 0
<i> </i> [access] =&gt; 7
<i> </i> )

<i> </i>[session.use_trans_sid] =&gt; Array
<i> </i> (
<i> </i> [global_value] =&gt; 0
<i> </i> [local_value] =&gt; 0
<i> </i> [access] =&gt; 7
<i> </i> )</CODE>

)<br/>


So there are definitely some differences... but I'm not sure I even understand what this data is referring to. There's only one php.ini, so what are "global" and "local" values, and what's this "access"? I checked and /var/lib/php/session has the right ownership and permissions (apache:apache 0700) but that doesn't seem to be it...

PS: Thanks for all your great ideas on this!
Copy linkTweet thisAlerts:
@NogDogJan 27.2021 β€”Β @mfox#1627261

Apparently the "access" relates to where that setting can be set, as per https://www.php.net/manual/en/configuration.changes.modes.php, though I don't know what the number actually means -- but I think we don't need to worry about it. Ignoring that, the one thing I noticed was this:
<i>
</i>[session.save_path] =&gt; Array
(
[global_value] =&gt;
[local_value] =&gt; /var/lib/php/session
[access] =&gt; 7
)

The global_value would be what's in php.ini or the default if not defined there, while local_value would imply it's set elsewhere, either a .htaccess file or some start-up script?
Copy linkTweet thisAlerts:
@mfoxauthorJan 27.2021 β€”Β I haven't learned the .htaccess "language" so I haven't used it (but like I said I don't know much about Apache in general so for all I know there's one hidden somewhere outside the web root lol). I don't use ini_set at all in my code (though I tried that just now, thinking along the same lines as you, to set the session save path). So it's not like there's a startup script somewhere that's goofing things up. But even if there were, my code works on our other server! So if it's not my code, and it's not php.ini or calls to ini_set, and I didn't use .htaccess, what else could it be? lol I'm totally clueless here...
Copy linkTweet thisAlerts:
@NogDogJan 28.2021 β€”Β PHP settings can also be in the httpd.conf file (the Apache config), because why not have them in as many places as possible. ;)

PS: According to a user comment on the PHP manual page for ini_get_all():
<i>
</i>Constant Value Meaning
PHP_INI_USER 1 Entry can be set in user scripts
PHP_INI_PERDIR 2 Entry can be set in php.ini, .htaccess or httpd.conf
PHP_INI_SYSTEM 4 Entry can be set in php.ini or httpd.conf
PHP_INI_ALL 7 Entry can be set anywhere

So I don't think it tells us where it was set, but with a 7 it could have been anywhere that's possible. :
Copy linkTweet thisAlerts:
@mfoxauthorJan 28.2021 β€”Β lol wow, seriously? Okay, I'll try calling ini_get_all and see what that gives me. And I'll definitely check out that other config file! I really appreciate all your input on the subject. Hopefully I'll be posting a solution tomorrow lol
Copy linkTweet thisAlerts:
@NogDogJan 28.2021 β€”Β I guess since we moved our app into an infrastructure using Docker containers a few years back, I've been fortunate not to have to worry about this kind of thing any more. If the container works on my macbook, it's 99.9+% likely to work when we deploy that container to the servers. Not saying you should drop everything and dockerize your app, as there's a definite learning curve -- and fortunately my team leader knows it very well -- but something to think about if it makes sense for your team and deployment options (e.g. needs a hosting option that supports container usage).
Copy linkTweet thisAlerts:
@mfoxauthorJan 28.2021 β€”Β lol wow, seriously? Okay, I'll try calling ini_get_all and see what that gives me. And I'll definitely check out that other config file! I really appreciate all your input on the subject. Hopefully I'll be posting a solution tomorrow lol

**EDIT:** @NogDog You are a rock star! THANK YOU! 😀

Sure enough, at the bottom of /etc/httpd/httpd.conf, was this bit of code:

Header edit Set-Cookie ^(.*)$ $1;HttpOnly;Secure

I temporarily commented out that line and then replaced it with:

Header edit Set-Cookie ^(.*)$ $1;HttpOnly

Restart Apache one more time and BINGO! Problem solved, sessions work!

PS: Now for future reference, in case anyone else finds this thread looking for help, let me just add this: I reverted the Apache config to how it was, because our IT team is still working on setting up SSL (and if you're doing this for a production machine, as in my case, that "Secure" is a setting you'll want, wherever you may happen to find your config stuff. 😆
Copy linkTweet thisAlerts:
@NogDogJan 28.2021 β€”Β Cool...it's fun helping people who work with you and aren't just looking for a fix they can copy/paste. :)
Copy linkTweet thisAlerts:
@Elizabeth14Dec 04.2021 β€”Β Thank you for your answer
Γ—

Success!

Help @mfox spread the word by sharing this article on Twitter...

Tweet This
Sign in
Forgot password?
Sign in with TwitchSign in with GithubCreate Account
about: ({
version: 0.1.9 β€” BETA 4.26,
whats_new: community page,
up_next: more Davinciβ€’003 tasks,
coming_soon: events calendar,
social: @webDeveloperHQ
});

legal: ({
terms: of use,
privacy: policy
});
changelog: (
version: 0.1.9,
notes: added community page

version: 0.1.8,
notes: added Davinciβ€’003

version: 0.1.7,
notes: upvote answers to bounties

version: 0.1.6,
notes: article editor refresh
)...
recent_tips: (
tipper: @Yussuf4331,
tipped: article
amount: 1000 SATS,

tipper: @darkwebsites540,
tipped: article
amount: 10 SATS,

tipper: @Samric24,
tipped: article
amount: 1000 SATS,
)...