2
\$\begingroup\$

I'm tasked with building a PHP web application where the content displayed on each page depends on a number of variables & must be re-usable across multiple pages.

A simple example of this is a search page with multiple elements:

  • A "basic search" div, displayed to all users.
  • An "advanced search" div, displayed to some users.
  • A "previous search history" div, displayed to all users, relevant to only their search history. This element should auto-refresh every 60 seconds.

I need each element to be re-usable & have the ability to be refreshed independent of all other elements on the page, thus decoupled from the overall page view.

For example, on a "user_info.php" page, I may want to display the same "previous search history" div. This means I can't build everything into "search.php", otherwise I'd have to build or include "previous search history" twice - once in "search.php" and again in "user_info.php". Since the search history must auto-update, an "include" statement won't work if we use a single page view.

The approach I'm leaning towards is to start by drawing a "search template" containing a bunch of placeholders which will then be populated with HTML via XHR calls.

I'm hoping to get feedback on this approach. Please note that this is a VERY basic example which illustrates how it works. The full implementation will be more complex (ie using proper route mapping, authentication, interval timers for auto div refresh if needed, etc).

If no $_GET variables are set, let's say index.php draws this page template (assuming jQuery & Bootstrap are loaded):

<body>
    <div class="row">
        <div class="col-md-4 contentPlaceholder" data-route="basicSearch"'></div>
        <?php if ($advancedSearchAccess) { ?>
        <div class="col-md-4 contentPlaceholder" data-route="advancedSearch"></div>
        <?php } ?>
    </div>
    <div class="row">
        <div class="col-md-6 contentPlaceholder" data-route="searchHistory"></div>
    </div>
</body>

Then once the page has finished loading, we populate each placeholder:

$(".contentPlaceholder").each(function(e) {
    $(this).load("index.php?route=" + $(this).data("route"));
});

The divs will be populated as determined in index.php if $_GET["route"] is set. Example:

switch($_GET["route"]) { 
    case "basicSearch":
        include ("basicSearch.php");
        break;
    case "advancedSearch":
        include ("advancedSearch.php");
        break;
    case "userSearchHistory":
        include ("userSearchHistory.php");
        break;
}

Example of output

Now on any page I can simply include the .contentPlaceholder with the relevant data-route and that element will be displayed wherever I want, with the ability to have it re-loaded without redrawing the entire page.

I'm keen to hear any feedback on this approach; is there a better way to do this? Please keep in mind the client has requested any frameworks (React, Angular, Laravel, etc etc) not be used (Bootstrap + jQuery are allowed, hence used in my example). Also I'm aware of maximum simultaneous XHR requests; this application should have no more than 6 at a time anyway.

\$\endgroup\$
  • 1
    \$\begingroup\$ This is a code review site. What is the code you want us to review? \$\endgroup\$ – Nathan Davis Aug 26 '17 at 3:38
  • \$\begingroup\$ I want to know if the code, the Javascript calling PHP to display content based on HTML data tags, follows any common best practices. \$\endgroup\$ – codeRage Aug 26 '17 at 4:24
1
\$\begingroup\$

I think your general approach of moving towards reusable components is one that is very popular across a broad range of applications. Since you pretty much only have trivial code in your question, I will talk more towards the design.

You mentioned a polling feature for search history. This doesn't make sense to me. You know exactly when a user performs a search, so I don't know why you would need to poll for this information. In initial page load you can load into initial page source, but for asynchronous AJAX searches you should be able to simply update the history in response to the search events.

Be very careful when designing your components to decide what content needs to be loaded on initial page view vs. what content should be loaded asynchronously.

I also find it to be an odd pattern to have this route/switch construct when you are doing nothing but including a separate file anyway. Why not make these different end points on your API?

What is the difference between basic search and advanced search? Should this really be treated as two separate components?

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.