tags:

views:

195

answers:

5

I'm relatively new to php, and I'm working on a project using a mysql database. The project consists of users being able to write posts, which are then shown in a list format. The problem is, the posts are shown in different locations on the site, like the index (main) page, and the users profile page. Similar to twitter if you're confused. My question is, what is the best way to display the posts? Currently I'm using a class that I created. It has functions to retrieve posts from the database, save them all in a multidimensional array. Then another function in the class formats the entire list using foreach, and then returns the formatted HTML list of posts. All I have to do is echo what is returned. But I read somewhere that it's bad practice to write functions (especially class functions) that output HTML. What would be the best way to do this, without having to rewrite the same code on every page the posts are shown. Is it really bad practice to use HTML in functions?

Example... a profile page looks something like this.

<

require('class.php'); 

require('header.php');

$profile = new Profile(); 

$userProfile = $profile->GetUserProfile($userID); 

echo $userProfile;

$class = new Posts(); 

$posts = $class->GetUserPosts($userID); 

echo $posts;

require('footer.php'); 

?>

And the main page looks something like this

<

$class = new Posts(); 

$posts = $class->GetAllPosts(); 

echo $posts;


?>

where the profile class would take a user id and output the users profile, already formatted in HTML. And the posts class has functions to return a determined number of posts already formatted in an HTML list.

Should I keep everything in the class, or is there a better way?

Thanks

+1  A: 

Well, if you're not using an MVC framework of some kind, then I would say that having functions that output HTML isn't going to kill anyone.

Generally however, it's helpful to separate HTML from logic, and this is usually done by creating an HTML template and template fragments with interspersed PHP. Something like this:

<div>
    <h1><?php echo $title; ?></h1>
</div>

You could then set up a $title variable (and others), and include('title_fragment.php') to output that bit of HTML. You can extend this to work with entire pages, making it so that your code only has to deal with small amounts of data that get passed to the template.

When it comes time to make changes to the page layout or look, you don't have to go hunting through the code to find the bits of generated HTML... you can go straight to the template files.

zombat
+1  A: 

This is important for maintainable design as well as code, and it makes it easier to produce other output types later on.

With PHP, one of the simplest libraries for separating the two is Smarty templates. Using Smarty (or any other templating library), you can write an HTML file with the layout and some simple loops or other constructs, and then render that template using a data structure. At the very least, I would suggest altering your class to utilize a template and produce output that way, rather than a mish-mash of print or echo statements with a bunch of HTML in them.

I'd even shy away from @zombat's solution of echo statements in HTML fragments, they quickly become ugly.

Example Smarty template to achieve something like what you want:

{section name=i loop=$posts}
   <li>{$posts[i].author} &mdash; {$post[i].text}</li>
{/section}

And some PHP supporting code:

// Instantiate Smarty object
$smarty = new Smarty();

// Assign a hash of data
$smarty->assign('posts', array(
    array('author' => 'Jim',   'text' => 'Hi this is my post!'),
    array('author' => 'Sally', 'text' => 'My first post to the system')
  )
);

// Use the file with the above template in it
$smarty->display('posts.html');

The part where you assign data to the template should probably be done via some programmatic means to convert your list of class objects into a list of hashes.

This way you can easily change the way the output looks just by editing the HTML template and you don't have to worry about touching any code to change the output.

John Ewart
A: 

Your class should ideally provide the data only. Use another PHP file or generic class to output HTML, so later you could output e.g. XML, JSON, etc from the same data class. This separates your data processing (model/controller) from your data representation (view).

I would disagree with using a template engine like Smarty. PHP is a template engine.

Al
I guess my thought is that PHP is ugly enough, you don't want to go throwing code in your output. Plus you can use Smarty or other template engine to output any other format you like without changing the code, except picking which template gets used ;)
John Ewart
What i have so far is a class that contains a functions to gather the posts, and save them into an array. Within the same class, I have seperate functions that deal only with formatting the given data into html, using a foreach. I also have functions that get user data and a seperate function to format the profile using that data. Is this good enough, or is this bad practice. Should i create an entire new class to deal with formatting only?
A: 

You can use output buffering. It's helping to build your templates and not be forced to process data in the display order.

<?php
  $posts = take_data_from_class();
  ob_start();
  require_once('path/to/posts.php');
  $html_posts = ob_get_clean();

  // you can do the same with other parts like header or footer
  ob_start();
  require_once('path/to/header.php');
  $header = ob_get_clean();

  ob_start();
  require_once('path/to/footer.php');
  $footer = ob_get_clean();

?>

In posts.php you can display the posts:

<? foreach ($posts as $p) { ?>
<div class="...">
  post data here
</div>
<? } ?>

Now, to display the whole thing:

<?php echo $header . $html_posts . $footer; ?>

More at http://us3.php.net/manual/en/book.outcontrol.php

Enjoy!

A: 

Im not familiar with Smarty at all...how exactly does that work, and what are the benefits of using a smarty vs. just creating functions to take large amounts of data and return html containing that data just to be echoed later?

BDuelz