Question

I have a function that loops through different types of listings pulled from MySQL and displays them as a Facebook-esque "feed". Each type of listing has a different appearance, and therefore requires a different template.

Here is the below function example might be called 100 times (if there are 100 listings):

function display_listing($id,$type) {
    global $abs_path;

    switch($type) {

        case 'photo':
            include($abs_path . '/templates/photo.php');
            break;

        case 'video':
            include($abs_path . '/templates/video.php');
            break;

    }

}

Is there a better way to do this, where I don't potentially end up with 100 includes - which may slow my process down? Can I somehow save the include once on the page, and refer to it as many times as needed?

...or is this the best practice?

Also, I want to know how to do this on my own, without a template engine...

EDIT: The problem isn't solved just by include_once (I dont believe)...I need to be able to reuse the included file multiple times, replacing the variables each time.

Was it helpful?

Solution

Although a switch is not the most scalable way to write this code, I'm afraid that includes is the only way to keep your templates in separate files, here.

You could, conceivably, encapsulate each template's code in a function, however:

/*
photoTemplate.php
*/

<?php
function loadPhotoTemplate($id) {
?>
  <div id="photo">
...
  </div>
<?php
}
?>


/*
listing.php
*/

function display_listing($id,$type) {
    global $abs_path;

    switch($type) {

        case 'photo':
            include_once($abs_path . '/templates/photo.php');
            loadPhotoTemplate($id);
            break;

        case 'video':
            include_once($abs_path . '/templates/video.php');
            loadVideoTemplate($id);
            break;
    }

}

This will load each template file at most once, and then just call the function each time you want to display the template with the specific data for that item.

Edit

It would probably be even better to include all template files at the beginning, then just call the appropriate function in the switch. PHP's *_once() functions are slow, as they must consult the list of previously included/required files every time they are called.

OTHER TIPS

create an array of allowed templates. have you function look to see if the requested template is in the array. if it is, then use the $type variable to include the file. yes, in general you shouldn't use user-supplied data in an include file name, but since you've validated it against a known-good array of values, it's safe.

If your concern is performance, I personally wouldn't get into this loop at all.

Presuming that items in the list are viewed more frequently than they're created, I would generate the HTML as the items are created and store the output alongside the data in the database. (Or in memcache or files or somewhere else - but generate it and store it.)

In doing so you'd move this logic back into the creation process of the items so you're doing the same switch statement, but only for one item at a time - you're cutting out the loop.

Then at display time, instead of calling display_listing(), you just echo out the HTML you've already stored.

I think you ought to look at a few things. Firstly, is there even a possibility you will include the same "template" 100 times? That seems like a massive amount of content to put on a page.

If I'm using tiny "snippets" - say, a table row that's repeated many times - I tend to use a function that returns a string, like this:

/* snippets.php */
function tableRow( $row )
{
    return
        '<tr><td>' . $row['var1'] . '</td>' .
        '<td>' . $row['var2'] . '</td></tr>';
}

/* main page/view */
foreach ( $data as $row )
    echo tableRow( $row );

The main advantage here is you can have loops and all sorts in the function.

If you're looking for a straight variable-replacement, you could create your own mini-templates in an HTML file; something like:

<p>{name}<br />
  Posted {date} by {author}</p>

Then read in the template, pass the whole string to your display_listing function, which runs str_replace on all the {variables}. I don't think there would be too much of a performance hit, but you'd have to try it to be sure.

You want to use the include_once function instead of include.

The include_once() statement includes and evaluates the specified file during the execution of the script. This is a behavior similar to the include() statement, with the only difference being that if the code from a file has already been included, it will not be included again. As the name suggests, it will be included just once.

If you're going to be including templates using a switch for different keywords, then you should set a variable, say $template_filename, in the switch and then once you break out of the switch, do the include like so:

include_once("/templates/{$filename}.php");

If you don't want to use including at all, then you might as well use a templating engine...

This method seems reasonable to me however.

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