PHP Processing Fragment Identifier in URL

2.9k Views Asked by At

I've got quite a dilemma here and would like some suggestions from the community. Here's my problem:

I've created a website that has lots of dynamic content, all content is pulled via AJAX and displayed via JS. The way I'm currently allowing direct links to my content is by modifying the fragment identifier on the fly with JS, here's an example:

http://www.mysite.com/home#/123

Where 123 is the ID of the content. When the content is closed it strips the fragment identifier off again.

This works wonderfully, and when people load the page my AJAX request is successfully requesting the '123' article. But I've just implemented a Facebook like button on all the articles, and now I've hit a brick wall.

Basically, the way Facebook finds what thumbnail and titles and URL to associate with your 'liked' content is to check the meta tags of the URL passed into the fb like iframe. It does this by doing a GET request at the URL, checking the content of the meta tags, and then displaying those on Facebook.

The problem is that fragment identifiers are not passed to the server, so I have no way in PHP (that I'm aware of) to dynamically generate these meta tags with the content from the specifically requested article.

For example, I wanted to be able to do something like this:

$id_vals = get_id_values($hash_fragment);
echo '<meta property="og:title" content="'.$id_vals['title'].'" />';

Your first thought is probably: Why not use a GET request or query string? i.e.:

http://www.mysite.com/home?id=123

However the problem with this approach is that Javascript cannot dynamically change this portion of a URL, it can only change the fragment identifier. This means that all direct links to our articles will require page refreshes. This goes against our whole 'dynamic' approach we have going - which I might add is really nice :)

So I'm kind of stumped at the moment. The only semi-solution I can think of is to use an approach of both:

In the fb like requests use get parameters and for direct links use fragment identifier.

But this poses the following problems:

  • If a direct link is pasted on Facebook from a user it will include the fragment identifier, and the correct meta data won't display on Facebook.
  • I would need to do some weird redirection magic to fix the format of the URL to remove the ID (i.e. detect if GET parameter is passed in and redirect to the fragment identifier equivalent). But I don't know if FB would also follow the redirect and fetch the meta tags from the redirected page instead of the first page, which would effectively make this solution useless anyway.

Sorry for the wall of text! Appreciate any input you can provide.

EDIT: I just tested my proposed solution involving a combination of both, and I can confirm Facebook follows the redirect, so this solution doesn't work at all. This is depressing!

EDIT EDIT: One possible way to implement my 'mix' idea is to use a window.location redirect instead of a PHP header() call redirect, so Facebook fetches the meta tags from the original page, for those of you with a similar problem.

Thanks.

3

There are 3 best solutions below

1
On

PHP's parse_url function returns everything including the hash fragment, so you could either use parse_url and access the fragment key of the returned array

$url = 'http://www.mysite.com/home#/123';
$parts = parse_url($url);
$fragment = $parts['fragment']; // => '/123'

or alternatively pass in the component flag PHP_URL_FRAGMENT, and just retrieve the fragment itself

$fragment = parse_url($url, PHP_URL_FRAGMENT); // => '/123'
0
On

index.php simply just echoes the session['refer'] and when it gets refreshed by Navigasyon.js id adds a /kill to the end of the fragment you enter in to stop refreshing process being looped!

<?php session_start(); ?>
<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>Boom - test</title>
        <script type="text/javascript" src="js/jquery.js"></script>
        <script type="text/javascript" src="js/Navigasyon.js"></script>
    </head>
    <body onLoad="if (location.href.indexOf('/kill')==-1) location.replace(location.href+'/kill')">
        <?php
//echo $_GET['url'];
//echo parse_url();
//echo $_SERVER["SERVER_NAME"].$_SERVER["REQUEST_URI"].$_SERVER['PHP_SELF'];;
        if (isset($_SESSION['refer']))
            echo $_SESSION['refer'];
        ?>
    </body>
</html>

Navigasyon.php all the magic happens here! simply just sends the fragment via ajax to the navg.php and registers it in a session and responds the same fragment from the server when it gets to make sure to kill the refresh loop index php adds a /kill frag and it stops

var whereAmI = window.location.hash;
var prsdUrl = window.location.hash.split("/");
var a = 0; //#!
var b = 1; //Sayfa dil
var c = 2; //Sayfa id

if(prsdUrl[a] == "#!")
{
    $.post("navg.php", {
        refer: whereAmI
    },
    function(data) {
        //if(data='ref') document.location.reload();
        if(data==whereAmI) {
            if(prsdUrl[c] != 'kill') {
                document.location.reload();
            }
        } 
    });
}

navg.php you tell whats going on in this part!

<?php
session_start();
$_SESSION['refer'] = $_POST['refer']; ?>
<?php echo $_SESSION['refer'];
?>
0
On

If you can rejigger your site to use hashbang #! URLs, Facebook somewhat quietly supports Google's AJAX crawling spec.

On encountering a URL containing #!, it will automatically convert that and the following text to the GET-friendly query string ?_escaped_fragment_=. Your server-side code can key off that GET param, if it's present.