Search code examples
jqueryajaxsingle-page-applicationhistory.js

Deep-Links in One-Page Layout using AJAX is accessing .php-Files directly


Quick structure overview:

domain.com will call the index.php. In it's JavaScript file I check for the current location.pathname, pass that info via AJAX to a class/nav.php which in turn gets and returns the contents from the specific file.

E.g: domain.com/about returns the contents of about.php which will be inserted into a part from index.php. domain.com and domain.com/ will return contents of home.php.

That worked fine in all web-apps I've build so far. But currently I have the following problem:

Accessing the app via domain.com will correctly insert contents from home.php. Following a link on the site like href="/about" will also correctly return the contents of about.php. But calling domain.com/about directly, is displaying the about.phpfile directly (locally) or showing a 404 error (live server). index.php is not called, hence the JavaScript is not executed and of course everything breaks apart.

I can't figure out why this is happening.

You can see the problem live here: www.einzelstueck-shop.com

Open the navigation on the top left and click Ringe - the page navigates correctly. Now reload the page or open www.einzelstueck-shop.com/ringe manually and you'll see the described behaviour.

Code i used (everytime) for navigating: (I use history.js and jQuery)

JS:

var History = window.History;
History.Adapter.bind(window,'statechange',function () {
    console.log('statechange');
    var State = History.getState();
    navigateTo(null);
});

function navigateTo(target) {

    if(!target) {
        target = removeSlash(window.location.pathname);
    }
    console.log('navigate to: ' + target);

    $.ajax({
        type: "POST",
        dataType: 'json',
        url: "class/nav.php",
        data: { location: target }
    }).done(function (data) {

        if(data) {
            // insert HTML
        } else {
            console.log('not happening...');
            History.pushState("1", 'Home', '/');
        }

    }).fail(function (data) {
        console.log('FAIL');
        console.log(data);
        return false;
    });
}

PHP:

<?php

$targetLocation = $_POST['location'];

if($targetLocation == '/' || $targetLocation == '' || $targetLocation == 'home') {
    $file = 'home';
    $targetLocation = '';
} else {
    $file = $targetLocation;
}

if(file_exists('../'.$file.'.php')) {
    $data['target'] = $targetLocation;
    $data['html'] = file_get_contents('../'.$file.'.php');
} else {
    $data = null;
}

echo json_encode($data);

?>

Solution

  • Okay I found it. The .htaccess, redirecting all URLs to index.php, was missing which is fixing the problem on the live server. Locally (using vmware and vagrant) the .htaccess was missing one line that needed to be added: Options +FollowSymlinks -MultiViews

    .htaccess:

    Options +FollowSymlinks -MultiViews
    RewriteEngine On
    RewriteBase /
    
    # remove trailing slash from URLs
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_URI} (.*)$
    RewriteRule ^(.+)/$ http://%{HTTP_HOST}/$1 [R=301,L]
    
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    
    RewriteRule ^ index.php?request=%{THE_REQUEST} [L]