Question

I have recently finished reading about PHP MVC and am wanting to make an ajax version of an MVC but am having trouble with the MIME type. What I am trying to do is redirect all server calls to the index.html page, so if the user goes to a page which doesn't exist the page will load the index page and then ajax can do it's thing with the uri.

Everything works fine without the htaccess file, but when it is uncommented I get the issue of the browser not being able to read the CSS, JS and any linked images as the MIME type is set to HTML according to the console.

[edit]

after Inspecting it further in fiddler it appears that the browsers are being sent the index.html file in place of the CSS and JavaScript files, so it seems I need to be able to make an exception in the case that it is a CSS or JS file. but I thought that was the purpose of the RewriteCond -f || -d in the htaccess file..

from the last edit I found that I could make an exception to the rewriteCond to allow CSS and JS files through. but now the PHP files that are used in the ajax calls are showing the HTML content... the change I made to the htaccess file is as follows

RewriteEngine On
RewriteCond &{REQUEST_FILENAME} !-f
RewriteCond &{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !css$
RewriteCond %{REQUEST_URI} !js$
RewriteCond %{REQUEST_URI} !php$
RewriteRule (.*) index.html [L]

[/edit]

here are the pieces to replicate what I am testing that you can run on your localhost.

https://www.dropbox.com/s/qx0d76xjvfuz681/ajaxTest.zip

thanks for any help,

Andrew

htaccess

RewriteEngine On
RewriteCond &{REQUEST_FILENAME} !-f
RewriteCond &{REQUEST_FILENAME} !-d
RewriteRule (.*) index.html [L]

index.html

<html>
    <head>
        <meta charset="utf-8">
        <title>ajax mvc test</title>
        <link rel="stylesheet" type="text/css" href="main.css">
    </head>
    <body>
         <nav>
            <ul>
                <li><a href="one" class="links link1">one</a></li>
                <li><a href="two" class="links link2">two</a></li>
                <li><a href="three" class="links link3">three</a></li>
            </ul>
        </nav>
            <div class="main"></div>
     <script type="text/javascript" src="main.js"></script>
    </body>
</html>

main.css

body{
    background: #f2f2e6;
    font-family: sans-serif;
}

h2{
    font-size: 2em;
    color: #5a2306;
}

main.js

(function(){

    // get the address of the webpage
    var url = window.location.pathname,
        // get the breadcrumb
        urlrep = url.match(/(.*)index\.html/)[1],
        // create regEx to test later
        address = new RegExp(urlrep);

    function update(method){
        // update the history of the webpage 
        var state = {
            data: "this is the data",
            title: "title",
            url: method
        }
        
        updated(method);
        history.pushState(state, state.title, state.url);
    }

    function updated(method){
        // run the ajax call
        if(method !== 'index'){
            console.log("not matched index no ajax call");
            ajaxPost(method + '.php');
        }
    }

    var nav = document.getElementsByClassName('links');
    
    // set event listeners on links
    for (var i = 0; i < nav.length; i++) {
        (function(x){
            nav[x].addEventListener('click', function(e){
                e.preventDefault();
                console.log("textContent: " + e.target.textContent);
                update(e.target.textContent);
            });
        })(i);
    };
    
    // set event listener to browser popstate
    window.addEventListener('popstate', function(e){
        var rep = window.location.pathname.replace(address, '').replace(/\.html/, '');
        console.log("popstate: " + rep);
        updated(rep);
    });
    
    // run the ajax call.
    function ajaxPost(address){
        var ajax,
            main = document.getElementsByClassName('main')[0];
        console.log("address: " + address);
        ajax = new XMLHttpRequest();
        
        ajax.onreadystatechange = function(){
            if(ajax.readyState == 1){
                // sendFunc
                main.innerHTML = "";
            }
            if(ajax.readyState == 4){
                // returnFunc
                main.innerHTML = ajax.responseText;
            }
        }
        
        ajax.open('post', address, true);
        ajax.setRequestHeader("content-type", "application/x-www-form-urlencoded");
        ajax.send();
    }

})();

one.php

<?php

echo "<h2>one</h2>";

echo "<p>Its like a symbology of this of your mouth is eating food, from your mouth to your heart, is your freedom and your independence and your identity. The best way to communicate is compatible. Compatible communication is listening with open ears and an open mind, and not being fearful or judgemental about what you're hearing.</p>"; 

echo "<p>Ipsum text generated by<a href=\"http://www.buseyipsum.com\"> Busey Ipsum </a> </p>";
?>

two.php

<?php

echo "<h2>two</h2>";

echo "<p>This is just common superficiality. Is thats whats so special about a woman? Superficiality with their face colours? This is just common superficiality. Is thats whats so special about a woman? Superficiality with their face colours?</p>";


echo "<p>Ipsum text generated by<a href=\"http://www.buseyipsum.com\"> Busey Ipsum </a> </p>";
?>

three.php

<?php

echo "<h2>three</h2>";

echo "<p>I would like to give you a backstage pass to my imagination. Have you urinated? Have you drained your bladder? Are you free? Because if you havent it will only come out later. I'm giving you some information that your bodily fluids may penetrate your clothing fibre's without warning.</p>";     

echo "<p>Ipsum text generated by<a href=\"http://www.buseyipsum.com\"> Busey Ipsum </a> </p>";
?>
Was it helpful?

Solution

I figured out the solution. What is happening is my css and js files are relative so when I use a uri that is two levels deep it will rewrite the relative path to include the first part of the uri. eg my url's are two deep to select the correct class and apply the correct method.

www.website.com/className/method

my css and js addresses take on the class name so instead of looking in the top folder in this example href="style.css" it is taking the name of the class and prepending it to the relative string eg href="className/style.css" which doesn't exist. The way I got around it initially was to have an if statement checking the exploded count of the uri. but a better solution is to do it in the htaccess file like this

RewriteEngine On
# rewrite the css and js files if they have the className prepended to them.
RewriteCond %{REQUEST_URI} ^(.+)\/(.+)\.(css|js)$ [NS]
RewriteRule ^(.+)\/(.+)\.(css|js)$ $2.$3 [L]

# rewrite the uri to a get superglobal
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-l

RewriteRule ^(.+)$ index.php?url=$1 [QSA,L]

developer tools still shows the wrong filepath, but the correct file is served so it's not a big issue.

hopefully this helps someone avoid the headache I went through

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top