PHP Keeping HTML Clean
I've been working with php for about a year now and am finally starting to make some headway in my understanding of OOP. So, now that I'm writing classes I'm looking for the cleanest methods of working my PHP into my HTML. I essentially have written a few classes that output data stored in my database.
For instance I'll instantiate an instance of a "user" class for which I'd written a function called g开发者_JAVA百科etUserNameByIndex($index) which "echos" a value that I can then write into my HTML in my preferred manor like:
<h1> The <?php $user->getUserNameByIndex($index) ?> is not online </h1>
That's great. What's bumming me out is if I have an array of strings I need returned I then need to write more PHP into my HTML, making my output page look more like another PHP script.
For instance:
<span> His likes are:<br> <?php foreach($user->likes as $like){ if($like != foo){echo $like . '<br>' }} ?>
It just doesn't seem as clean to me, but if I write the output into the class method, I'm taking away some of my style control. I'm wondering if there is a balance here I should be looking for. Or if there is a standard method for handling arrays of strings that you intend to display in your HTML. I hope this makes sense and is not a dumb question. I'm so thrilled to be writing HTML that looks like HTML again, that anyway to minimize the PHP footprint in my code is a big bonus.
Thanks for your consideration.
A good way to separate code from design is the Model-View-Controller (MVC) design pattern.
Specifically, in your case you are looking for a separation of model (data handling) and view (display).
There are many implimentations of it already in existence in PHP. A few that are worth looking at are:
CodeIgniter
Kohona
Symfony
Zend
(And, if you are not against using a templating language as a templating language parser, may I suggest looking at Tiny But Strong.)
You can always use a more friendly HTML PHP syntax:
<?php foreach($user->likes as $like) :
if($like != foo):
?>
<?=$like?><br>
<?php
endif;
endforeach; ?>
Jascha, I'd be tempted to build a page class with methods for writing everything you want to in php, such that you can write mid-html:
/* at the top of the file somewhere... */
$page = new PageWriter();
....
<!-- in the html body -->
<p><?php $page->print_users_likes($user); ?></p>
Of course, you could add such methods to your existing classes, or just use them as ordinary methods on an include or require.
The reason for doing this is purely cosmetic - this way you can see in your html page what is going on, rather than a few for-loops, algorithms etc.
I'd suggest looking at include and require functions in php - I use them to remove bits of php not specific to a certain page away from it.
You can also use output buffering. You can load templates into your classes and return the compiled HTML code.
I would highly recommend the Smarty Templating Engine for PHP. It allows you to separate your presentation (HTML) from your logic. (PHP) Features like caching are built-in, and it really simplifies the process of mixing PHP and HTML.
In it's stable release, (v2) it is already somewhat Object-Oriented. (PHP4+ compatible even) In the current development version (v3 - already in Beta 7) it is much more Object-Oriented (PHP5+ compatible)
Given the nature of PHP, I find templating systems like Smarty overkill. Certainly constantly swapping between php and html code is messy and difficult to read.
One solution is to interpolate variables within strings:
$all_likes=implode('<br />',$user_likes);
print "<span> His likes are:<br /> $all_likes</span>";
However if you consider the scenario of dealing with multiple substitutions into different strings (e.g. for a multi-language website) then a better solution might be to use [s]printf:
$template="<span> %s likes these:<br />$s</span>";
...
printf($template, getUserNameByIndex($index), implode('<br />',$user_likes));
(BTW: None of this is really anything to do with OO specifically)
If you want a generic method of dealing with formatting an arbitary set of values into such a template you could do something like:
print render("<span>$s likes %s</span>",array($username, $user_likes));
function render()
{
$args=func_get_args();
foreach ($args as $key=>$val) {
if ($key && is_array($val)) {
$args[$key]=flatten($val);
}
}
return call_user_func_array('sprintf',$args);
}
function flatten($inp)
{
// there's probably a smarter way of doing this with
// the array fns
$out='';
$join='';
foreach ($inp as $val) {
$out.=$join;
if (is_array($val)) {
$out.=flatten($val);
} else {
$out.=$val;
}
$join="<br />\n";
}
return $out;
}
HTH
C.
精彩评论