How to organize country/state/city browsing in MVC

2019-04-16 01:59发布

问题:

I'm creating an ajax-based website that includes a country/state/city browsing interface. For SEO purposes, I want to include the name of the country/state/city in the URL. For example, the url may include additional variables, and would be something like:

 http://www.website.com/browse#!USA/NY/Albany
 http://www.website.com/browse#!USA/NY/Albany?Category=sports

I need to fit this functionality into an MVC framework (specifically CodeIgniter) through AJAX. I'm not sure how to organize the major components, specifically the Controller, AJAX Handlers, and possible Library class. Is there a standard or best practice approach?

回答1:

Yes, Google wrote some good stuff on this subject, particularly maintaining ajax application state with fragment identifiers: http://code.google.com/web/ajaxcrawling/docs/specification.html

Here's some code I put in my index.php file to handle this:

// Special handler for ajax partials ("AHAH" paradigm)
if (isset($_GET['_escaped_fragment']))
{
    // Grab just the fragment
    $fragment = $_GET['_escaped_fragment'];

    // See if we have GET parameters to extract from the fragment
    if (FALSE !== ($p = strpos($fragment, '?')))
    {
        // Make sure to save additional GET parameters
        $additional_params = array_diff_key($_GET, array('_escaped_fragment' => 1));

        // Parse the querty string
        parse_str(substr($fragment, $p+1), $_GET);

        // Add the originals back in
        $_GET = array_merge($_GET, $additional_params);

        // The beginning part of the fragment is the base URI
        $fragment = substr($fragment, 0, $p);
    }

    // Otherwise, clear the $_GET array
    else
    {
        $_GET = array();
    }

    $_SERVER['PATH_INFO']   = $fragment;
    $_SERVER['REQUEST_URI'] = $fragment;

    // Add a constant for use throughout the app
    define('IS_FRAGMENT', 1);
}
defined('IS_FRAGMENT') OR define('IS_FRAGMENT', 0);

The approach is this:

1) If it's an ajax request and IS_FRAGMENT == 1, then display just the partial results you need to populate your front-end changes

2) Otherwise, assume it's either a search engine or a direct page load. Display the fully built page.

You shouldn't necessarily created separate endpoints just for the ajax requests. It's probably better to extend the Output class to provide a response in the requested format. It's more RESTful that way.

It's also good practice to leverage the HTML5 History API for browsers that can handle it, and fall back to the onhashchange event for the others.

A few more pointers:

Use "#!" to indicate ajax-triggered content changes, rather than just a "#". You might at some point want to use the default anchor functionality that the fragment provides (but the exclamation point is "safe" as you probably won't have element IDs starting with that particular character).

I would also recommend using an absolute URI (i.e. #!/USA/NY/Albany), as it will be easier to stay consistent in your ajax partial loading mechanism.

Additionally, if someone reloads the page with the ajaxed-fragment in the URL, it can get pretty messy if you don't just do a window.location.href = '...' to load the page fresh. You'll run into all kinds of issues with back/forward at that point.