Re: Thoughts on Templates
Posted: Tue Jun 10, 2008 7:08 am
nicely put, +1
A community of PHP developers offering assistance, advice, discussion, and friendship.
http://forums.devnetwork.net/
Code: Select all
class User extends Model{
$this->name = null;
$this->email = null;
function __construct(){
// this auto-populates the friends list
$this->has_and_belongs_to_many('user', 'friends');
}
}Code: Select all
class Profile extends Controller{
// this responds to /profile/username
function view(){
$user = User::first($params['username']);
$this->render();
}
}Code: Select all
Hi there <?=$user->name?>!
<? if ($user->friends){ ?>
You have friends!
<ul>
<? foreach ($user->friends as $friend){ ?>
<li><a href="mailto:<?=$friend->email?>"><?=$friend->name?></a></li>
<?}?>
</ul>
<? } ?>Code: Select all
Hi there = $user->name.'!'
- if ($user->friends)
You have friends!
%ul
- foreach ($user->friends as $friend)
%li
%a{:href=>'mailto:#{$friend->email}'}= $friend->nameI think that all looks good (unless of course you're going for true MVC, and want to separate out the view stuff from the controller. Not necessary though.)Kieran Huggins wrote:So.. thoughts? What logic should be where?
Code: Select all
<?php
class User {
var $name, $email;
var $friends = false;
function User($name = NULL) {
$this->name = isset($name) ? $name : str_shuffle("abcde");
$this->email = "{$this->name}@mailinator.com";
}
};
$me = new User("me");
$me->friends[] = new User();
$me->friends[] = new User();
$me->friends[] = new User();
$loner = new User("loner");
require_once('template.inc.php');
$tpl = CreateTemplate("tpl.html", ""); //don't mind the second parameter
$tpl->AssignObject($me);
echo $tpl->ToString();
$tpl->AssignObject($loner);
echo $tpl->ToString();
?>Code: Select all
My name is [[name]], write me at [[email]], unless you're a spammer; then, please die.<br>
<hr>
[[]]
My friends:<br>
<ul>
<!--[[friends]]-->
<li>Friend [[name]] has email [[email]] </li>
<!--[[/friends]]-->
</ul>
[[]]
Brain the size of a planet, and yet I don't have any friends.
[[/]]Code: Select all
My name is me, write me at me@mailinator.com, unless you're a spammer; then, please die.
My friends:
Friend dbace has email dbace@mailinator.com
Friend cbeda has email cbeda@mailinator.com
Friend daebc has email daebc@mailinator.com
My name is loner, write me at loner@mailinator.com, unless you're a spammer; then, please die.
Brain the size of a planet, and yet I don't have any friends.Code: Select all
[[]]
block 1 (with [[vars]])
[[]]
block 2 (with [[other_vars]])
[[]]
block 3 (with no vars)
[[/]]Code: Select all
<!--[[var]]-->
block (with some variable [[element]])
<!--[[/var]]-->
Or, an alternative would be to help designers learn OUR ways instead of vice versa in order to keep the efficiency that comes with separation of duties.hansford wrote:why don't we all go take a design course, fire all of the designers, and then we can write it any way we see fit.
PHP4?Mordred wrote:Nice, I'm game
Code (PHP4, but should be PHP5 compatible):
Code: Select all
<!--[[page]]-->
My name is [[name]], write me at [[email]], unless you're a spammer; then, please die.<br>
<hr>
My friends:<br>
<ul>
[[friends]]
</ul>
Brain the size of a planet, and yet I don't have any friends.
<!--[[friends]]-->
<li>Friend [[name]] has email [[email]] </li>
Don't ask... and soon I'll have to make a transition with all compatibility fun that ensues.arborint wrote:PHP4?
I don't get how you know where the blocks start and end - maybe the start of one is the ending of the previous one? Ah, I get it, you have consequently defined blocks, and if any of them is mentioned by name, it is substitited? In my system it is done only in-place, which has some downsides (but was easy to implement, that's why I haven't decided whether to change it or not).arborint wrote: A simple library I use has one level of blocks and only has replacement tags. I'd think loops are a good addition. It's templates look something like this:You code would have to insert the friends block as the friends tags.Code: Select all
<!--[[page]]--> My name is [[name]], write me at [[email]], unless you're a spammer; then, please die.<br> <hr> My friends:<br> <ul> [[friends]] </ul> Brain the size of a planet, and yet I don't have any friends. <!--[[friends]]--> <li>Friend [[name]] has email [[email]] </li>
It's used to define a conditional statement. In your version of the template, there is no check whether we have "friends" or not. In my system it's used as a delimiter, defining alternative blocks (the [[/]] marks the end of the last alternative block). So this:arborint wrote:I don't exactly understand what "[[]]" does...
Code: Select all
[[]]
block 1 (with [[vars]])
[[]]
block 2 (with [[other_vars]])
[[]]
block 3 (with no vars)
[[/]]Code: Select all
if (isset($vars)) echo "block 1 (with $vars)";
else if (isset($other_vars)) echo "block 2 (with $other_vars)";
else echo "block 3 (with no vars)";Code: Select all
$MainTemplate = 'My name is @@NAME@@, write me at @@EMAIL@@, unless you\'re a spammer; then, please die.<br>
<hr>
@@FRIENDLIST@@
@@NOFRIENDS@@';Code: Select all
$FriendRowTpl = '<li>Friend @@NAME@ has email @@EMAIL@@</li>';
$FriendListTpl = 'My friends:<br />
<ul>
@@FRIENDROWS@@
</ul>';
$NoFriendsTpl = 'Brain the size of a planet, and yet I don\'t have any friends.';Code: Select all
$friends = '';
if ($user->friends) {
$NoFriendsTpl = ''; // clear out NoFriends
$FriendRows = '';
foreach ($user->friends as $friend){
$FriendRows .= str_replace(array('@@NAME@@', '@@EMAIL@@'), array($friend->name, $friend->email), $FriendRowTpl)."\n";
}
$FriendListTpl = str_replace('@@FRIENDROWS@@', $FriendRows , $FriendListTpl);
} else {
$FriendListTpl = '';
}
echo str_replace(
array('@@NAME@@', '@@EMAIL@@', '@@FRIENDLIST@@', '@@NOFRIENDS@@'),
array($use->name, $user->email, $FriendListTpl, $NoFriendsTpl),
$MainTemplate);
Agreed, maybe a more clear markup is required for this case, I'll think about it. Maybe I should even support named blocks, so they can be nested.arborint wrote:I guess [[]] does not seem very expressive to me because I had to ask!What if you want multiple tags in a block? How does it determine which of the blocks to select?
Code: Select all
[[]]
we have [[var1]] and [[var2]]
[[]]
we have [[var1]] only
[[]]
we have [[var2]] only
[[]]
no vars defined
[[/]]Code: Select all
if (isset($var1) && isset($var2)) echo "we have $var1 and $var2";
//etc...Code: Select all
<?php
/**
* App_Controller here could extend Framework_Controller_Page or something similar
*/
class App_Controller_About extends App_Controller {
public function __construct() {}
public function actionSitemap() {
$this->assign('sitemap', $this->model->getSitemap();
}
}
?>Code: Select all
<?php
class App_Model_About extends App_Model {
public function getSitemap() {
return $this->mysql->call('get_sitemap');
}
}
?>Code: Select all
<div id="sitemap">
<?php if ($sitemap->hasRecords()): ?>
<ul>
<?php for ($sitemap->startRecord(); $sitemap->hasRecord(); $sitemap->nextRecord()): ?>
<li><?php echo $this->anchor($sitemap->fields['url'], $sitemap->fields['name']) ?></li>
<?php endfor; ?>
</ul>
<?php else: ?>
<p>There is no sitemap.</p>
<?php endif; ?>
</div>I'm very interested in what turned you away.Everah wrote: thought, for a while, that a template engine was THE thing to do to separate business logic and presentation logic. I was totally wrong.
I don't buy the idea that a designer will write the templates, I'm not sure how often that happens in the real world, but I don't think non-programmers can handle the full Smarty syntax.Everah wrote: Since the data is available to the views through the controllers, why add the step of taking the data that is held by the controller and substituting that for variables in the view that essentially written in another language (whether it is smarty, @@ syntax, [[]] syntax or even {} syntax, ultimately it becomes a totally new language to manage - if a designer doesn't know PHP and has to learn this new template language... well crap, just have them learn PHP)?
What I'm looking for here is that other way, the shorter way. The way that's faster to write and easier to read. The way that doesn't get it your way. The way I experiment with (by the way) is incidentally very designer-friendly, although I don't see it as a particularly important feature, rather a nice side effect (but let's not forget that whoever ends up writing that template, it's good to make it easy for him ... hey, it could be me!). My, that's way too many "way" in this paragraphmatthijs wrote:Those variables need to be inserted. Those loops (show latest 10 articles) need to be performed. That "display logic" has to be run. One way or the other.
you can indeed look at some of the available template languages. But you can also use PHP, but then just use a limited amount or a specific set of variables/logic.Mordred wrote:Does the job. Short. Easy to read. Easy to maintain. Steals from the rich and gives to the poor.
Code: Select all
<?php if (have_posts()) : while (have_posts()) : the_post(); ?>
<div class="post" id="post-<?php the_ID(); ?>">
<h2 class="posttitle"><a href="<?php echo get_permalink() ?>" ><?php the_title(); ?></a></h2>
<div class="entry">
<?php the_content('<p>Read the rest of this entry</p>'); ?>
</div>
</div>