Jump to content


Photo

A different way of using templates / delegate approach


  • Please log in to reply
43 replies to this topic

#21 adamkiss

adamkiss

    Master of the universe

  • Moderators
  • 1,078 posts
  • 289

Posted 06 March 2012 - 11:21 AM

Also, I am probably retarded, I totally missed Diogos response. Sorry

#22 diogo

diogo

    Hero Member

  • Moderators
  • 2,011 posts
  • 1089

  • LocationPorto, Portugal

Posted 06 March 2012 - 11:30 AM

Adam, I think we just answered at the same time... don't be so harsh on yourself :)

#23 thomas

thomas

    Distinguished Member

  • Members
  • PipPipPipPip
  • 115 posts
  • 33

  • LocationKöln, Germany

Posted 03 August 2012 - 04:19 AM

Thanks for the interesting thread. If you (like me) don't like to put markup into variables, you can use the output buffer to use cleaner include files:

ob_start();
include('./teaser.php');
include('./pager.php');
$page->body = ob_get_clean();
include('./main.php');

That way your include files can be html with php elements and not $page->body="<p>something</p>"

I have one question to the main.php approach, though: I have a bunch of functions that are used by several templates. With the head/foot method I would simply put them into head.inc and make them available to every page. Where do you put this when using a main.php? Would that be a module?

Thanks,
thomas

#24 Soma

Soma

    Hero Member

  • Moderators
  • 3,217 posts
  • 1762

  • LocationSH, Switzerland

Posted 03 August 2012 - 05:34 AM

I have one question to the main.php approach, though: I have a bunch of functions that are used by several templates. With the head/foot method I would simply put them into head.inc and make them available to every page. Where do you put this when using a main.php? Would that be a module?


I'm not sure I understand right, but I would put them in main.php or include them like you would when using a head.inc.

@somartist | modules created | support me, flattr my work flattr.com


#25 thomas

thomas

    Distinguished Member

  • Members
  • PipPipPipPip
  • 115 posts
  • 33

  • LocationKöln, Germany

Posted 03 August 2012 - 05:39 AM

I'm not sure I understand right, but I would put them in main.php or include them like you would when using a head.inc.

My question is how you deal with functions that are potentially needed in every single page on the site. Putting them into main.php doesn't work in this example, because those functions are needed in teaser.php, which is called before main.php. One way would of course be to put include('./functions.php') into every template but I was wondering if there's a way to specify a file that is automatically included into every template.

#26 Soma

Soma

    Hero Member

  • Moderators
  • 3,217 posts
  • 1762

  • LocationSH, Switzerland

Posted 03 August 2012 - 05:54 AM

Of which method here are you talking about. With my approach the main.php always get's loaded and then the template of the page is included, so this will work well.

@somartist | modules created | support me, flattr my work flattr.com


#27 thomas

thomas

    Distinguished Member

  • Members
  • PipPipPipPip
  • 115 posts
  • 33

  • LocationKöln, Germany

Posted 03 August 2012 - 06:03 AM

Of which method here are you talking about.

Ryan's, where the dynamic content is definded in the page's template before callling the page structure (main.php).

#28 Soma

Soma

    Hero Member

  • Moderators
  • 3,217 posts
  • 1762

  • LocationSH, Switzerland

Posted 03 August 2012 - 06:06 AM

Ah, yes then you would have to include the function to each template file. That's one reason I don't like Ryan's approach. :) Though no issue at all, just personal preference.

Edit: Yes a module would help here, that provides function for all templates.

@somartist | modules created | support me, flattr my work flattr.com


#29 thomas

thomas

    Distinguished Member

  • Members
  • PipPipPipPip
  • 115 posts
  • 33

  • LocationKöln, Germany

Posted 03 August 2012 - 06:37 AM

Cheers, I'll take another look at your approach then :)

#30 apeisa

apeisa

    Hero Member

  • Moderators
  • 2,530 posts
  • 856

  • LocationVihti, Finland

Posted 03 August 2012 - 05:02 PM

After Ryan's latest incarnation of Blog Profile I wanted to see if I could learn something from there to my own workflow. It turned out very nicely and this seems like a perfect template approach for me. Wanted to share it with you guys.

Folder structure under templates folder:

templates/markup/
templates/markup/helpers/
templates/markup/layouts/
templates/scripts/
templates/styles/


And it all begins from here:

templates/markup/index.php
-this is the "complete" html file, it has doctype, head and starting and ending body. There is very little "logic" here, it's more like a container. There is one very important code snippet there though:

<?php
if ($page->layout) {
  include("./markup/layouts/{$page->layout}.php");
} else {
  include("./markup/layouts/default.php");
}
?>

Code above goes between header and footer of your site, that will be the main content. I call it layout, but the better name would be "content layout" or "inner layout" or something like that.

Then the templates/markup/layouts/ folder will keep at least default.php file, but probably few others, like "threeColumns.php", "frontpage.php", "gallery.php" etc.. you got the idea.

Each of the actual pw template files are then purely "controllers" - no actual markup generated there. All markup are done in files inside templates/markup/ folder and it's subfolders. This is how template file templates/home.php on one site I am building right now looks like:

<?php

// Carousel items
$t = new TemplateFile(wire('config')->paths->templates . 'markup/helpers/carousel.php');
$t->set('carouselPages', $page->carousel);
$page->masthead = $t->render();


// Tour themes
$t = new TemplateFile(wire('config')->paths->templates . 'markup/helpers/items.php');
$t->set('title', "Get inspired from our <strong>tour themes</strong>");
$t->set('items', $page->featured_themes);
$t->set('description', $page->themes_description);
$t->set('url', $config->urls->root . "themes/");
$t->set('linkTitle', "All themes");
$page->main .= $t->render();


// National parks
$t = new TemplateFile(wire('config')->paths->templates . 'markup/helpers/items.php');
$t->set('title', "Seven beautiful <strong>national parks</strong>");
$t->set('items', $page->featured_parks);
$t->set('description', $page->parks_description);
$t->set('url', $config->urls->root . "national-parks/");
$t->set('linkTitle', "All national parks");
$page->main .= $t->render();


$page->layout = "frontpage";
include("./markup/index.php");

This uses few "helper" markup files from templates/markup/helpers/ folder (namely carousel.php and items.php). Here is the carousel.php for your reference:
<?php
/* Generates the markup for the frontpage carousel */
if (count($carouselPages) < 1) return;
$styles = '';
echo "<div id='carousel'><ul class='rslides'>";
foreach($carouselPages as $key => $p) {
  echo "<li class='c-item c-item-$key'>";
  echo "<img src='".$p->image->getThumb('carousel') ."' alt='' />";
  echo "<p>$p->summary</p>";
  echo "<a class='button' href='{$p->link->url}'>$p->headline</a>";
  echo "</li>";
}
echo "</ul></div>";

Then populates the $page->masthead and $page->main properties and then set's the inner layout to "frontpage". That templates/markup/layouts/frontpage.php file is very simple on this site, but could be much more complicated if needed:

<div id="masthead">
  <?= $page->masthead; ?>
</div>

<div id="main" class="wrap">
  <?= $page->main; ?>
</div>

Frontpage is rather unique and I could have done all the markup on the frontpage.php file also. But I do want to re-use those "carousel" and "items" components on other places as well. But if I do have totally unique stuff, where I do want to get "quick and dirty" this approach allows it. Then my template file would be something like this:

$page->layout = "campaign2012";
include("./markup/index.php");

And then all the markup would be in that templates/markup/layouts/campaign2012.php

Blog profile really gave me a good ideas (cleaner folder structure etc) and using TemplateFile class adds nice possibilities. This is of course just a one way to manage your templates, but hopefully someone of you finds this helpful when thinking about how you like to structure this stuff.

PS: If you are just getting started with PW, then I recommend using the head and foot includes method from demo install. There is nothing wrong with that method and only more complicated sites starts to benefit from these methods introduces in this topic.

#31 arjen

arjen

    Sr. Member

  • Members
  • PipPipPipPip
  • 340 posts
  • 125

  • LocationHoogeveen, The Netherlands

Posted 04 August 2012 - 12:43 PM

Thanks for your detailed post! I'm studying the blog profile as well and I can't seem to wrap my head around the TemplateFile class. What does it do exactly? Do you create a temporary template? Or a template as a variable? Why and when do you use it?
work will always be the curse of the drinking classes...

#32 apeisa

apeisa

    Hero Member

  • Moderators
  • 2,530 posts
  • 856

  • LocationVihti, Finland

Posted 04 August 2012 - 02:23 PM

It is pretty simple and straightforward. It loads the file and then you can set variables for it. Then you can render the output (directly echo or save to a variable which get's echoed later on). It doesn't differ that much from having functions that return the output, but I think having them as separate files is much cleaner. And no need to passing variables as function parameters is nice also.

It is pretty close to plain simple includes, but it allows to save the output to a variable instead of directly outputting it. That is pretty much all it does (same as this: http://php.net/manua...php#example-140). This difference allows you to keep your actual template file purely as a controller if you want to (like in my example there is always last line include("./markup/index.php"); which starts the output).

#33 arjen

arjen

    Sr. Member

  • Members
  • PipPipPipPip
  • 340 posts
  • 125

  • LocationHoogeveen, The Netherlands

Posted 05 August 2012 - 06:07 AM

Thanks for the answer. It seems like a really clean and neat way to create templates. Would you be so kind to post the contents of items.php or carousel.php? So I can relate those as well?
work will always be the curse of the drinking classes...

#34 apeisa

apeisa

    Hero Member

  • Moderators
  • 2,530 posts
  • 856

  • LocationVihti, Finland

Posted 05 August 2012 - 06:46 AM

Sure, actually will add one of these into first example. But here are both:

Carousel.php
<?php
/* Generates the markup for the frontpage carousel */
if (count($carouselPages) < 1) return;
echo "<div id='carousel'><ul class='rslides'>";
foreach($carouselPages as $key => $p) {
  echo "<li class='c-item c-item-$key'>";
  echo "<img src='".$p->image->getThumb('carousel') ."' alt='' />";
  echo "<p>$p->summary</p>";
  echo "<a class='button' href='{$p->link->url}'>$p->headline</a>";
  echo "</li>";
}
echo "</ul></div>";

items.php
<?php
if (isset($title)) echo "<h2 class='items-title'>$title</h2>";

echo "<div class='items'>";
foreach($items as $key => $p) {
  $key++;
  if ($key > 3) {
	$key = 1;
	echo "<hr class='padding' />";
  }
  echo "<div class='col{$key}of3 item'>";
  echo "<img src='". $p->featured_image->getThumb('thumbnail') ."' alt='' />";
  echo "<h2 class='title'><a href='$p->url'>$p->title</a></h2>";
  echo "</div>";
}
echo "</div>";

And as additional bonus, items-with-description.php (it includes the items.php from above):
<?php
if (count($items) < 1) return;
$items = $items->slice(0,3);
include('./items.php');
echo "<div class='col1-2of3'><p>$description</p></div>";
echo "<div class='col3of3'><a class='button block' href='$url'>$linkTitle</a></div>";

Uh, just realized that my site has evolved a little. Those in my example actually use "items-with-description.php" instead of just "items.php".

There is also my "default-masthead.php":
<?php
$img = $image->width(304);
?>
<div class='col1-2of3'>
  <h1><?= $title ?></h1>
  <p class='summary'><?= $summary ?></p>
</div>
<div class='col3of3'>
  <img src='<?= $img->url ?>' alt='' />
</div>


#35 adamkiss

adamkiss

    Master of the universe

  • Moderators
  • 1,078 posts
  • 289

Posted 05 August 2012 - 11:06 AM

If you are interested, I am trying about similar approach in my module Render::, which is currently in the 'proof of concept' phase.

#36 arjen

arjen

    Sr. Member

  • Members
  • PipPipPipPip
  • 340 posts
  • 125

  • LocationHoogeveen, The Netherlands

Posted 05 August 2012 - 12:00 PM

Thanks apeisa! It seems I understand this somewhat better now with the examples. Will try this on a couple of sites I'm going to convert from Textpattern to ProcessWire.
work will always be the curse of the drinking classes...

#37 Robert Zelník

Robert Zelník

    Full Member

  • Members
  • PipPipPip
  • 69 posts
  • 5

Posted 05 August 2012 - 10:36 PM

Back to the Soma's template approach: I just realized that we would not need to use dirty hacks to force PW to render alternate template file, if PW would allow us to set template files for both layout and particular view.

Example:
We have a post template.
In post template we set
  • main.php for layout (default setting for the whole site) - renders the whole HTML page
  • post.php for view (default setting for this particular template - derived from the template name) - renders the content specific to the post template, nested inside the main.php layout
This approach is common in many web application frameworks.

#38 apeisa

apeisa

    Hero Member

  • Moderators
  • 2,530 posts
  • 856

  • LocationVihti, Finland

Posted 06 August 2012 - 12:28 AM

Robert, if I understood you correctly, that is exactly what my method does also. It doesn't do it automatically, since I want most of my templates to use same view (default.php), but it is possible to set any view just by saying:

$page->layout = "post";

I am pretty sure that similar thing is possible on Soma's approach also. No dirty hacks needed to get such an output.

#39 Robert Zelník

Robert Zelník

    Full Member

  • Members
  • PipPipPip
  • 69 posts
  • 5

Posted 06 August 2012 - 12:48 AM

Yes, exactly. It's a similar approach done differently. I just think that it would be great if PW would allow to set both layout and view files in the template settings. Currently we can just set the layout file (in Advanced > Alternate Template Filename).

#40 Soma

Soma

    Hero Member

  • Moderators
  • 3,217 posts
  • 1762

  • LocationSH, Switzerland

Posted 06 August 2012 - 02:42 AM

Back to the Soma's template approach: I just realized that we would not need to use dirty hacks to force PW to render alternate template file, if PW would allow us to set template files for both layout and particular view.

Example:
We have a post template.
In post template we set

  • main.php for layout (default setting for the whole site) - renders the whole HTML page
  • post.php for view (default setting for this particular template - derived from the template name) - renders the content specific to the post template, nested inside the main.php layout
This approach is common in many web application frameworks.


I'm not sure I understand correctly. "My" approach already does exactly this. The template in PW uses all "main" as alternative, but the template name still exists when main.php is called, so depending on the name of the template the right templatename.inc view include will be loaded.

@somartist | modules created | support me, flattr my work flattr.com





0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users