6

Basic situation and basic relevant info: I have a php code that executes before the opening <doctype> tag. The hope was to (if necessary) send a redirect based on user's browser's language preferences before anything else loads.

The script attempts to do two things based on highest supported language preference:

  1. Use php: setcookie() to create a cookie with the two-letter language code.
    • Example cookie name = value: x_language = es
  2. Use php: header("Location: " . $requestedSite); to redirect to a subdomain,
    • Example domain: es.domain.com

Example:

if (isset($_COOKIE['x_language'])) {
    -Determine correct subdomain based on cookie value-
    -If not currently on that subdomain, redirect to it-
} else {
    setcookie('x_language','es',time() + 31536000 ,'/','.domain.com' );
    header("Location: " . $requestedSite);
}

The problem: Firefox works perfectly. Chrome (and other browsers) fail to recognize the cookies at all.

I've boiled it down to this:

  • print_r($_COOKIE) works properly in Firefox, and returns a lovely, populated array.
  • print_r($_COOKIE) fails in Chrome, and returns an empty array.

This is the core of the problem, my function doesn't recognize the existence of a cookie because Chrome doesn't.

  • I've made sure every browser accepts cookies.
  • I've checked dev tools to make sure the cookie is in place on all browsers, (it is).
  • I realize a cookie's value isn't available until the next page load, but that isn't an issue here. Even after it is set, it won't read.
  • There is no output above the initial setcookie();

So how do I get Chrome (and other browsers) to recognize its own cookies?! Does anyone know why this would all work flawlessly on Firefox but fail elsewhere?


On a lark I decided to try this. I created a file that only contains:

<?php
print_r($_COOKIE);
?>

Again, I see the cookie array in Firefox. Meanwhile, in Chrome, IE, Opera, Safari, I get an empty array. Could this be a server issue?

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
FourStair
  • 81
  • 1
  • 7
  • I've had this issue before. The order that you send the `Location` header and the `Set-Cookie` header matters here. I don't remember which goes first though. Bumped to other wise gurus... – landons Mar 08 '13 at 19:52
  • 2
    Webkit bug? http://stackoverflow.com/questions/1144894/safari-doesnt-set-cookie-but-ie-ff-does – landons Mar 08 '13 at 19:53
  • Thanks, landons. But it doesn't seem to be either of these. The problem is in reading the cookie, rather than in the writing. The cookie is being written exactly as it should be (I can see it in the Dev Tools console), but it's unavailable to my php script for some reason. – FourStair Mar 08 '13 at 23:21
  • Chrome can be pickier about subdomain cookie sharing, when you print $_COOKIE, are you on domain.com or subdomain.domain.com? http://stackoverflow.com/questions/7880305/issue-with-session-across-subdomain-only-for-google-chrome – Sarah Kemp Mar 09 '13 at 00:24
  • Is this behavior observable somewhere online? – Wrikken Mar 13 '13 at 21:20

2 Answers2

2

OP returns with answer:

Alright, I'm adding this as an 'Answer' in case anyone else comes across this (totally bizarre) behavior and lands here:

It turns out my hosting provider was doing some seriously aggressive caching with my WordPress site that I was unaware of.

At the time I posted my question, I didn't think being on WordPress was relevant, but apparently it was.

Basically it was doing this:


With a clean Cache:

  • Visitor 1 visits the site.
  • The php processes and produces output as expected.
  • Visitor 1 is served php output (based on his browser's parameters and such).

  • Visitor 2 visits the site. Visitor 2 sees *Visitor 1's version of the site.

The php is processed once and only once per Cache-clear.

This caching behavior meant that accessing cookies through php was simply not going to work right, but accessing them with Javascript WOULD work.

(Important note: It turns out the above-stated caching behavior is disabled for any user viewing the site while logged into wordpress, and this is common behavior for WordPress Cache plugins. That is why I was seeing different behavior in Firefox than I saw in other browsers, because I was actively logged in with Firefox. This could be a helpful piece of information for someone out there.)


My solution:

Use Javascript to run an AJAX query to a .php file which would process the language preferences of the visitor and return the output as a 2-character code, (i.e. 'en' 'es' 'pt' 'de', etc).

Using AJAX to call php allowed me to use php's server-side access to a browser's language preferences while circumventing the super-agro caching of my host.

I hope this helps someone! And thanks to everyone who tried to help me out with this.

FourStair
  • 81
  • 1
  • 7
0

I was not having this problem with the code below. I was able to go to example.com and be redirected immediately to en.example.com and see the cookie in $_COOKIES. If I used en.example.com?set=fr I would be redirected to fr.example.com every time I tried example.com. Hopes this is what you were looking for!

<?php
print_r($_COOKIE);

if(isset($_GET['nuke'])) {
    setcookie('x_language','',time()-1000,'/','.example.com');
    echo 'It has been nuked!';
    exit;
} else if(isset($_GET['set'])) {
    setcookie('x_language',$_GET['set'],time() + 31536000, '/','.example.com');
    $_COOKIE['x_language'] = $_GET['set'];
}

if (isset($_COOKIE['x_language'])) {
    $redirect = $_COOKIE['x_language'].'.example.com';
    if($_SERVER['HTTP_HOST'] != $redirect)
        header('Location: http://'.$redirect);
} else {
    setcookie('x_language','en',time() + 31536000,'/','.example.com');
    $redirect = 'http://en.example.com';
    header('Location: '.$redirect);
}

echo '<br />Cookie: '.$_COOKIE['x_language'].' Domain: '.$_SERVER["HTTP_HOST"];
?>
TylerH4
  • 463
  • 1
  • 5
  • 12