Violet

Is this template file structure an OK practice in terms of variable-passing?

Recommended Posts

I originally created my template files thinking I'd only ever need 3 and not worrying about if I repeated bunches of common code there (yes, bad practice, I know). I figured I'd just manually/copy-paste to change any common code in all 3 as needed. So of course, fast-forward awhile, and I'm now up to 6 template files with possibly a few more to come, and decided it was high time I made the switch to keep the common parts in their own unique files for ease of editing. So I therefore went back and read Ryan Cramer's tutorial "How to Structure Your Template Files".

OK. I tried out the "includes" command mentioned in the tutorial on a test template. The resultant web page physically functions as expected, but my question here is, "Is the practice I'm showing below OK in terms of variable usage?" If not, what approach should I be using? 

I've tested it out and the variables do populate as expected in the final result, but is it OK for me to do it like this or is there the chance that some of the variables won't be passed properly?

Here is what I  mean (only the relevant portions of code shown to illustrate):

...
<aside> 
  <h3>Three Random Posts</h3>
<!-- get the list, then display it -->
<?php
$itempages = $pages->find("template=my-post");
$shortlist = $itempages->getRandom(3);
$shortlist->shuffle();
$itempagezero = $shortlist->eq(0);
$itempage1 = $shortlist->eq(1);
$itempage2 = $shortlist->eq(2);
?>
<?php include("./INC_displaylist.php"); ?>
</aside>
<?php include("./INC_footer.php"); ?>
</body>
</html>


The possible issue here is that the INC_displaylist.php file outputs field data from $itempagezero, $itempage1, and $itempage2. Is that OK? I wanted to split the variable assignments and the output separately. This is because, based on the exact template I'm using, I will sometimes choose to populate $itempages via different selectors in the $pages->find command in different template files, although all templates will display an identically-formatted list of 3.

By contrast, I wouldn't expect any variable issues with including the INC_footer.php file as shown above, since I'm not using any variables in the footer that aren't first referenced in that same footer.

So am I doing it OK here or should I be populating these variables somewhere else to ensure they're recognized properly by INC_displaylist.php? If I need to do it somewhere else, where should I populate these?

Share this post


Link to post
Share on other sites

Hi @Violet

This should work fine. What I'd do is make the path:

/site/templates/includes/displaylist.php

and link to it with:

<?php include(".includes/displaylist.php"); ?>

Do you need an include file though? I mean, is it that big or complex? If the list is just the linked titles, you could (not tested):

<aside> 
  <h3>Three Random Posts</h3>
<!-- get the list, then display it -->

<?php
  // can chain the methods, first part returns an array with all pages
  // created with 'my-post'. Second part, gets random x 3 from first array
  // and returns a new array, which is then shuffled and saved to $itempages
  $itempages = $pages->find("template=my-post")->getRandom(3)->shuffle();
  
  // if items are actually returned
  if (count($itempages)):
  ?>

  <ul>

  <?php
  // loop over them
  foreach ($itempages as $itempage): ?>

  <h4><?= $itempage->title; ?></h4>
  
  <?php endforeach; ?>
  
  </ul>

  <?php else: ?>

    <p>No posts found :(</p>

  <?php endif; ?>
</aside>

...or you could do it with an include:

<aside> 
  <h3>Three Random Posts</h3>
<!-- get the list, then display it -->

<?php
  // can chain the methods, first part returns an array with all pages
  // created with 'my-post'. Second part, gets random x 3 from first array
  // and returns a new array, which is then shuffled and saved to $itempages
  $itempages = $pages->find("template=my-post")->getRandom(3)->shuffle();
  
  // if items are actually returned
  if (count($itempages)):
  ?>

  <ul>

  <?php
  // loop over them
  foreach ($itempages as $itempage): ?>

   <?php include("./includes/displaylist") ;?>
  
  <?php endforeach; ?>
  
  </ul>

  <?php else: ?>

    <p>No posts found :(</p>

  <?php endif; ?>
</aside>

and displaylist.php like:

<?php namespace ProcessWire;
// caveat being that the variable MUST be called '$itempage' here
?>

<h4><?= $itempage->title; ?></h4>

<?= $itempage->summary; ?>

<?= $itempage->whatever; ?>

It's up to you really :)

==EDIT==

I am unsure by your example if you need different fields from each page $itempagezero, $itempage1 and $itempage2. Would need to see the contents of INC_displaylist.php. You did mention 'all templates will display an identically-formatted list of 3.'.

==EDIT 2==

Can I just clarify something. You can also use wireIncludeFile() function which is awesomer (is that a word?) than the standard include because you can pass variables INTO the template. The standard include above is simply used 'as if it were typed directly into the containing template'. This is just another approach.

<aside> 
  <h3>Three Random Posts</h3>

  <?php
    $itempages = $pages->find("template=my-post")->getRandom(3)->shuffle();

    if (count($itempages)) {
      // include the file and pass the pages into it
      wireIncludeFile("./includes/displayist.php", array('mypages' => $itempages));
    }
  ?>

  <h3>Newest 5 Posts</h3>

  <?php
    $itempages = $pages->find("template=my-post, limit=5, sort=created");

    if (count($itempages)) {
      // include the file and pass the pages into it
      wireIncludeFile("./includes/displayist.php", array('mypages' => $itempages));
    }
  ?>

</aside>

and displaylist.php

<?php namespace ProcessWire; ?>

<ul>

  <?php
  // loop over the value/s of the 'mypages' array key
  foreach ($mypages as $itempage): ?>

   <li><a href="<?= $itempage->url; ?>"><?= $itempage->title; ?></a></li>
  
  <?php endforeach; ?>
  
</ul>

There's just so many ways. I haven't tested this one either but you get the idea.

You can see why people here (and myself) love the flexibility processwire provides! :) you can arrange your templates any way you want, whatever makes sense to you.

  • Thanks 1

Share this post


Link to post
Share on other sites

Hi @SamC thanks so much for your very helpful and thorough reply. I went through your code for your two different examples. Thanks, I think I see what you're saying here. Upon reflection, I think I have something more like your second method in mind, mainly because I have a fair amount of fields to output from the post list and a fair amount of styling going on in there. Therefore if I decide I want to later add in and display an extra field for each item in the list of 3 in the <aside> section (this is in fact exactly what happened yesterday), I just want to edit ONE file (the one called by "include") and not every single one of my template files.

Also, sorry if I inadvertently made my wording confusing in the original post. Oops :blush:. When I said "all templates will display an identically-formatted list of 3", I did not mean that all 3 items will be displayed identically to EACH OTHER. This is why I did not loop. I just meant that the layout of the 3 will not change between templates. So, for example the first post title might be displayed with full-width photo, publication date, and with an excerpt. Posts 2 and 3 might be displayed below that but next to each other (one on left other on right), with title and just thumbnail pic, no excerpt. Still tinkering with my design layout, but ultimately I want the final layout and final fields of the <aside> section to be the same on all my different templates (e.g. post 1 details always shown full-width; posts 2 and 3 always displayed below next to each other). So that's why I was wanting to use include.

My displaylist.php basically looks a lot like your example, but with lots of styling and with separate display of each of the 3 post fields.

IMPORTANT QUESTION: Your example showed I was supposed to begin the file displaylist.php with: 

<?php namespace ProcessWire;
?>

 

The file calling it i.e. the code from my template file I gave at the start (currently called _temptest.php ) ALSO starts with that:

<?php namespace ProcessWire; ?>
<!DOCTYPE html>
<html lang="en">
<head>
  ....

So to clarify, do I still need to specify "namespace ProcessWire" in file displaylist.php even though file _temptest.php (which calls displaylist.php) starts with the same thing? And thanks again for all the help you've given me above. I really appreciate it.

Share this post


Link to post
Share on other sites

Haven't thoroughly read everything written above. Quick suggestions:

$config is your friend

For paths, (and other stuff), $config is your friend. Rather than entering paths yourself, let it to the donkey work. For instance, if you have an includes folder in /site/templates/includes/  you can get to that easily using:

$path = $config->paths->templates . 'includes/';

Delayed Output

If you are not already, I recommend you use this approach. Makes it easy to pass and change variables if needed. See the Automatic Inclusions section (the $config->prependTemplateFile). Your files do not have to be named .inc. They could be .php or even .tpl.

 

  • Like 2

Share this post


Link to post
Share on other sites
Just now, Violet said:

So to clarify, do I still need to specify "namespace ProcessWire" in file displaylist.php even though file _temptest.php (which calls displaylist.php) starts with the same thing?

Not 100% sure, let me test... when I remove the namespace from one of my includes I get...

Fatal error: Uncaught Error: Call to undefined function renderTags()

What I do (maybe unnecessarily) is just paste that line at the top of every template. it fixes my errors anyway.

I believe it's to do with the compiling of the files Admin > Setup > Templates > Files (tab) and using 3rd party PHP libraries so variables don't collide. I'm no PHP expert so don't quote me on this!

Just now, kongondo said:

Delayed Output

If you are not already, I recommend you use this approach.

I'm thinking of going this way myself, or at least the new template strategy. Things are getting a little weird with includes, especially my header which changes depending on what template is loaded. Got some funky logic in an include file right now that just doesn't feel right.

What puts me off is all the HTML in strings in terms of syntax autocomplete/highlighting in ST3.

  • Like 1

Share this post


Link to post
Share on other sites

Thanks to both of you for the updates. 

@kongondo , the $config is a good idea,I will replace my paths on the "include" with that. Valuable info.

You also mentioned I should consider delayed output. When reading up about it, I came to the conclusion that I'd have to sit around and do a lot of concatenating of strings every time I create a new template file. I'm new to ProcessWire, so maybe I've gotten it wrong, but I just don't like the general idea that I have to pre-define every output I want to make as a string first, instead of just using variables here there and everywhere on the fly as I update/change my templates (the latter is what I love about ProcessWire).

I will think about all this. In the meantime, will change my paths to $config ones.

@SamC , thank you SO MUCH for going to all the trouble to actually test out the namespace on the "include" files. While my setup was working fine without the namespace, I'm DEFINITELY heeding your warning that depending what you have going on in your files, omitting the namespace may lead to errors. As you say, it can't hurt to put it in. I'll change my files around to add those in. Thanks so much!

14 hours ago, SamC said:

Things are getting a little weird with includes, especially my header which changes depending on what template is loaded.

What you said above about the limitations of the "includes" method was very valuable too. Hmm.

Thanks also for the link to the new template strategy; this was extremely helpful as it was not mentioned in the tutorial that I had read in my first post (why??). I'm not certain if the new template strategy is ultimately what I'm looking for; I'll have to think about that carefully. The reason is my template is heavily CSS-based, and I'm not a big fan of using classes like pw-append and pw-prepend. I can see how on the one hand the new system would allow flexibility when using different templates on a site; on the other I don't like the notion of using classes that aren't defined in my stylesheet. I realize ProcessWire handles those tags itself; I just don't like it from an ideological point of view more so than a practical point of view. Plus, I don't want the pw classes to be at war with either my classes or my screen reader strategy. Perhaps it wouldn't clash, but it still doesn't seem like the most readable templating method to me.

I read your second edit, and I was beyond thrilled!

16 hours ago, SamC said:

You can also use wireIncludeFile() function which is awesomer (is that a word?) than the standard include because you can pass variables INTO the template.

I think this is what I might go with! It sounds like exactly what I need. I will try it out. This is hugely valuable info thanks.

 

Share this post


Link to post
Share on other sites
21 minutes ago, Violet said:

When reading up about it, I came to the conclusion that I'd have to sit around and do a lot of concatenating of strings every time I create a new template file.

I think you must have misunderstood the tutorial.

 

22 minutes ago, Violet said:

I don't want the pw classes to be at war with either my classes or my screen reader strategy.

The pw-* classes are just placeholder tags that ProcessWire parses at render. They are removed in the final markup. There's a very tiny note about it on that page (I'm not sure why it had to be a note and not just in the text proper :)) just above Benefits and drawbacks section.

Quote

Note: after being processed, the “pw-” classes above are removed from the HTML tags automatically by ProcessWire.

 

  • Like 2

Share this post


Link to post
Share on other sites
21 minutes ago, Violet said:

You also mentioned I should consider delayed output. When reading up about it, I came to the conclusion that I'd have to sit around and do a lot of concatenating of strings every time I create a new template file. I'm new to ProcessWire, so maybe I've gotten it wrong, but I just don't like the general idea that I have to pre-define every output I want to make as a string first, instead of just using variables here there and everywhere on the fly as I update/change my templates (the latter is what I love about ProcessWire).

Hi,

I have not read the whole thread but I think Ryan's delayed output with all those concatenating stuff is not for everyone, normally I do not use it either. I have a hybrid approach of using all sorts of possibilities which is rather long to explain but maybe one day I have the time to do a write up on it in my own blog.

The most important thing is that most of the time I use <?php include __DIR__ . '/../path/to/file.php'; ?> but there is something to keep in mind: http://yagudaev.com/posts/resolving-php-relative-path-problem/

Using PHP's own include() and its variants has the advantage of being able to access all the variables you need during the rendering process without doing much extra "work". It works well for not too "convoluted" frontends. Yet, more sophisticated approaches might be required in other cases but for just starting with ProcessWire you will probably not need more than this for quite a while.

Note that PHP is a native template engine, at least Rasmus Lerdorf says so:

I do something similar. Early in the rendering process I implement the "business logic" and store stuff in variables which can be outputted and/or tested later in the native Rasmus's style code part generating the actual output. This way most code editors can auto format, syntax highlight, intellisense, etc... your HTML code.

Concatenated code is hard to read to say the least. Some IDEs deal with it well – e.g. PHPStorm (which is not free) – but still...

  • Like 1

Share this post


Link to post
Share on other sites

The following topic is old and some of the stuff is probably out of date but well worth reading.

 

  • Like 3

Share this post


Link to post
Share on other sites

Thanks for all of the additional info, @kongondo. And the delegate approach sounds interesting. It could be a good way to do it when there are some similar-ish templates, which is the case for 2 of my current 6 templates. So it could be a strategy to incorporate into those. However I'm not sure that I would want to do it for everything I'm using, because (correct me if I'm wrong), in that case I'd wind up using 1 template file with a bunch of conditional statements referring to 6 different templates. This, while elegant coding-wise, would surely have a little drawback in readability, at least to me. I might have misunderstood as I am still a newbie, sorry. I'm still very much trying to get to grips with everything and get my head around everything. In any case, I might incorporate this delegate approach for the more similar of my templates where there wouldn't be too many conditional statements. I'm glad that everyone has given me so many different templating strategies to choose from here. 

@szabesz - thanks, so glad for the warning and for the link to the info about relative paths! Actually I had wondered about that, which was one of the reasons I'd kept my inc files in the same directory as my template files. My own naming convention for my inc files is INC_filenamehere.php , since my editor handles the .php files well, but won't recognize a .inc the same way, and I don't like editing plain text. I like the markup and things to be in different colors like they are on .php files. (Yes I know I can probably change the editor settings to recognize .inc files but I'd prefer to instead go for a filename convention that works for me personally). Plus having inc files start with INC_ means they are all grouped together alphabetically in my template directory anyway. I will update my paths using $config, just as kongondo recommended, so that this way I can ensure that the path is specified explicitly to sidestep the whole problem altogether. Thanks, I read the other 2 articles you linked to also, very helpful info when thinking about templating strategies.

2 hours ago, szabesz said:

Early in the rendering process I implement the "business logic" and store stuff in variables which can be outputted and/or tested later in the native Rasmus's style code part generating the actual output.

Thanks, it's helpful to get ideas of how people are doing it for their own sites.

All of this discussion has forced me to think about what's most important to me when templating. It's probably readability and layout.  In other words, I need to be able to come back to my templates 6 months from now, and if there's a change I want to make on the page (whether it's displaying a new field or changing some of the styling), I want to be able to do it as quickly as possible without needing to track stuff down much. Parts of my templates can be busy, especially when I have a bunch of nested divs etc with different classes, but it seems to be the main way that makes sense to me while still functioning responsively. Anyway this has given me lots to think about and it's helped highlight to me that there are lots of different possible templating approaches due to the flexibility of ProcessWire. It's not even restricted to only the methods mentioned in the tutorial I had first read. I really appreciate all the help I've received here from everyone.

  • Like 3

Share this post


Link to post
Share on other sites
2 hours ago, kongondo said:

The following topic is old and some of the stuff is probably out of date but well worth reading.

 

I have used this approach for the past 4 sites.

Now I'm considering other options though. Things like this though...

<?php
$headline = $page->get("headline|title");

// bodycopy is body text plus comments
$bodycopy = $page->body . $page->comments->render();
$sidebar = $page->sidebar;

// check if this page has any children
if(count($page->children)) {
  // render sub-navigation in sidebar
  $sidebar .= "<ul class='nav'>";
  foreach($page->children as $child) {
    $sidebar .= "<li><a href='$child->url'>$child->title</a></li>";
  }
  $sidebar .= "</ul>";
}

include("./main.inc"); 

...makes me think a few things:

1) Having to make strings out of all my HTML is a royal pita.

2) No autocomplete for HTML tags in ST3 when pretty much everything is chucked into strings.

3) However, this is easier to read than some of the the alternate syntax I'm using i.e. when there's a bunch of if/else, inside a loop, maybe a second loop, then the alternate syntax I also find a pita.

4) I like the idea of being able to pre-populate things, then just render them out later depending on which template is loaded. Makes a fair bit of sense.

So, it seems I'm unpleasable :P good news is, whatever approach you take @Violet you've got a forum full of incredible help here.

  • Like 1

Share this post


Link to post
Share on other sites

wow, did'nt read all the answers, but it seems nobody mentioned markup regions anywhere? soma's post is a must-read of course, but it's also from 2011 and we now have the same functionality a lot easier and cleaner imho: https://processwire.com/blog/posts/processwire-3.0.62-and-more-on-markup-regions/

a simple setup could be:

_main.php

<html>
  <head>
    <!-- scripts&co -->
  </head>
  <body>
    <section id="header">your header, menu or the like...</section>
    
    <region id="main"></region>
    
    <section id="footer">your footer</section>
  </body>
</html>

home.php (really no other markup than this in this file!)

<section id="main">
  <h1>Welcome to my website!</h1>
  <p>This is the awesome text of my awesome website</p>
</section>

blogitem.php (for example)

<section id="main">
  <h1>Blog Item <?= $page->title ?></h1>
  
  <?= $page->body ?>
  
  <ul>
  <?php
  $page->siblings("id!=$page")->each(function($p) {
	echo "<li><a href='{$p->url}'>{$p->title}</a></li>";
  }
  ?>
  </ul>
</section>

This will render your website with header and footer, inject scripts on all sites and just change the content of the main section on your pages.

  • Like 3
  • Thanks 1

Share this post


Link to post
Share on other sites

I just made a copy of my templates folder, renamed the copy 'templates.delegate' and now in the process of trying out the new markup regions to see how it suits me. Thanks for the newer link @bernhard

Having:

<region id="main"></region>

replaced by:

<section id="main">
  <h1>Welcome to my website!</h1>
  <p>This is the awesome text of my awesome website</p>
</section>

(EDIT - the section tags are not printed)

reminds me a bit of extending in twig, where you could:

// master template
<div id="content">{% block content %}{% endblock %}</div>

and then in the child template:

{% extends "base.html" %}

{% block content %}
    <h1>Index</h1>
    <p class="important">
        Welcome on my awesome homepage.
    </p>
{% endblock %}

Not paid a great deal of attention to this approach but I like the look of it.

  • Like 2

Share this post


Link to post
Share on other sites

i haven't used markup regions on larger projects. ryan said its a little more overhead. but for smaller projects imho it is the cleanest and easiest solution. i think its much easier to understand for newcomers than the regular delayed output. it was also great to work together with my designer :) 

  • Like 2

Share this post


Link to post
Share on other sites

I wonder how much overhead? What is considered 'large amounts of markup' as quoted from your link?

Your second point is interesting. If this approach is easy for web designers (or developers) to understand, this may help in the convincing of clients that anyone would be able to take over the site in the future because the template structure is so intuitive/straight forward.

 

  • Like 1

Share this post


Link to post
Share on other sites

@bernhard - Thank you for your awesome example! Yes, Sam had posted a link to the 3.0.49 post, but it was good to also see the updated 3.0.62 version of markup regions. The thing that made a huge difference to me was your code example. Your sample code here was MUCH easier for me to understand as a newcomer than the examples given in both of the official markup regions posts. If there are any other newcomers who are thinking of using markup regions, I strongly recommend bernhard's earlier reply above. It allowed me to see more easily how this would indeed help solve the general problem of having common bits of code.

The advantage over the "includes" method is that the main layout code is in one place. In other words, I could therefore edit header and footer for all pages from the same file ( _main.php in your example), and I can see layout at a glance. High readability and ease of editing. I see I could add to _main.php all possible region ID's used in all templates; only the ones used by the specific template in use will get populated. So, it's pretty tidy, and you can get a feel straight away for what sorts of things all of your templates are likely to be doing, just by looking at _main.php. The main disadvantage I see is that I'm not sure what I would do if I ever created a page template that (for example) I did not want to include a footer on. Sure, that's unlikely to happen, but I'm not sure how I'd handle that using markup regions if it occurred. I expect there must be a way to do that, it's just not obvious to me.

@SamC thanks for updating and also for mentioning the methods you are using. It is really great for me to have all of this info here from everyone all in one place. 

Share this post


Link to post
Share on other sites
26 minutes ago, Violet said:

The main disadvantage I see is that I'm not sure what I would do if I ever created a page template that (for example) I did not want to include a footer on.

You're in luck because I just tried this.

// _main.php
<region id="header">HEADER</region>

<region id="main"></region>

<region id="footer">THIS IS MY FOOTER</region>

...and a template:

// basic-page.php (used to make the /about/ page)
<?php namespace ProcessWire; ?>

<region id="header"></region>

<region id="main">
  <div class="container py-5">
  <div class="row justify-content-center">
    <div class="col-md-8">
      <?= $page->body; ?>
    </div>
  </div>
</div>
</region>

<region id="footer"></region>

Then on a page made with the basic-page template. The header and footer are hidden completely (from view and source).

  • Thanks 1

Share this post


Link to post
Share on other sites

Oooh awesome!! I can see how that would work but I would never have thought of it myself. Thanks @SamC! I really appreciate you trying that out. I'm leaning toward using markup regions now.

One question, if anyone is willing to comment: using "markup regions" vs using "includes" - which of those two would you expect to be faster to render? And are there any conditions / caveats which favor one better than the other as far as speed alone is concerned? 

I know it said that markup regions can take a bit longer if you're outputting a lot of markup, but how do I know if I have a lot of markup? Also, wouldn't "includes" be considered an extra step just like "markup regions", so how do we know which one of these two would be faster for PW to render? I know there's most likely no hard-and-fast rule here, but I'm seeking some general thoughts about which conditions might favor one vs the other speed-wise. 

Share this post


Link to post
Share on other sites

I think includes() would be faster because it is a function built into php. It's like whatever's in the include file is simply written right into the page. The markup regions have to be processed by PW first to see what goes where, then put it all together for final output.

I'm not convinced on markup regions tbh. I'm just not getting how you dynamically change just parts of the regions instead of having to define what goes in the entire region in every template. Maybe just tired! I'll carry on tomorrow.

  • Like 1

Share this post


Link to post
Share on other sites

@SamC what are you trying to do exactly? 

Like always in PW it's up to you. Just wanted to mention markup regions because I didn't see anybody mentioned them. If others are happier with using includes that's totally fine :)

Ps: if performance is a factor for you the best you can do is to invest some euros and 3 minutes to download and install procache. No matter what technique you are using for generating the output, procache will make it lightning fast even on slow servers ;)

  • Like 1

Share this post


Link to post
Share on other sites
1 hour ago, bernhard said:

@SamC what are you trying to do exactly? 

At present, all templates are rendered via '_main.php' but each template that needs to be a rendered page (basic-page, blog-index, blog-entry etc.) uses the alternate template filename instead of '_main.php' being appended. Hence:

// _main.php
<?php include("./includes/header" . ".php"); ?>
<?php include("./views/{$page->template->name}" . ".php"); ?>
<?php include("./includes/footer" . ".php"); ?>

and the header which is included on every page:

<?php namespace ProcessWire; ?>

<header>
  <div class="container">
   LOGO, MENU ETC...
  </div>

<?php
  if ($page->template == "tag-entry") {
    $title = "Processwire " . strtolower($page->title) . " tutorials";
  }
  elseif ($page->parent->template == "blog-entry") {
    $title = $page->parent->title;
  }
  else {
    $title = $page->get("altTitle|title");
  }
?>

  <div class="container pt-5 pb-6">
      
      <h1 class="display-3"><?= $title; ?></h1>

      <?php if ($page->subtitle): ?>
        <p class="subtitle"><?= $page->subtitle; ?><p>
      <?php endif; ?>

      <?php if ($page->template == "blog-entry" && $page->parent->template == "blog-entry"): ?>

        <p class="date-and-cat"><span>Posted on</span> <strong><?= renderPostDate($page->parent) ;?></strong> <strong><?= renderTags($page->parent); ?></strong></p>

      <?php elseif ($page->template == "blog-entry" && $page->parent->template == "blog-index"): ?>

        <p class="date-and-cat"><span>Posted on</span> <strong><?= renderPostDate($page) ;?></strong> <strong><?= renderTags($page); ?></strong></p>

      <?php endif; ?>

  </div>

</header>

So, using another method such as markup regions, not sure how to render this. Maybe something like:

// _main.php
  <?php
    if ($page->template == "tag-entry") {
      $title = "Processwire " . strtolower($page->title) . " tutorials";
    }
    elseif ($page->parent->template == "blog-entry") {
      $title = $page->parent->title;
    }
    else {
      $title = $page->get("altTitle|title");
    }
  ?>

  <region id="header">
    <div class="container pt-5 pb-6">

    <h1 class="display-3"><?= $title; ?></h1>

    <?php if ($page->subtitle): ?>
      <p class="subtitle"><?= $page->subtitle; ?><p>
    <?php endif; ?>

    <region id="date-and-cat"></region>

    </div>

  </region>

and a blog page for example:

// blog-entry.php
<region id="date-and-cat">
  <?php if ($page->parent->template == "blog-entry"): ?>

    <p class="date-and-cat"><span>Posted on</span> <strong><?= renderPostDate($page->parent) ;?></strong> <strong><?= renderTags($page->parent); ?></strong></p>

  <?php elseif ($page->parent->template == "blog-index"): ?>

    <p class="date-and-cat"><span>Posted on</span> <strong><?= renderPostDate($page) ;?></strong> <strong><?= renderTags($page); ?></strong></p>

  <?php endif; ?>
</region>

Not really sure here. I also have include files inside loops and stuff like that. I think my best bet is to start with empty templates and build it up rather than modifying my existing ones which is just confusing me no end.

Don't really want to divert this thread too much though.

  • Like 1

Share this post


Link to post
Share on other sites
12 hours ago, SamC said:

Not really sure here. I also have include files inside loops and stuff like that. I think my best bet is to start with empty templates and build it up rather than modifying my existing ones which is just confusing me no end.

agree ;) but of course you can combine markup regions and includes...

12 hours ago, SamC said:

Don't really want to divert this thread too much though.

agree :)

  • Like 1

Share this post


Link to post
Share on other sites
47 minutes ago, bernhard said:

agree ;) but of course you can combine markup regions and includes...

Starting to see the point of regions now after playing around with it this morning. Need to keep reminding myself that '_main.php' is the LAST file that is output.

This does seem to have (at least) one advantage over my last approach. Namely, I don't have to set '_main' as the alternate template filename anymore for each template.

=EDIT=

Another thing I've noticed, if you include a file from '_main.php' (which is not a known system template), the include must have...

<?php namespace ProcessWire; ?>

...at the top or it doesn't output.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Recently Browsing   0 members

    No registered users viewing this page.

  • Similar Content

    • By dweeda
      How do I migrate a template with all its fields and values to a new site? Is their an export/import process?
    • By Sephiroth
      Hi, So today I will writing a small tutorial on developing templates in Processwire using Twig Template, Processwire is a highly flexible CMS which gives developers/designers/users options and allows easy extension of the platform. So here goes the tutorial 
      What is Twig Template ?
      Simply put in my own words, Twig is a modern templating engine that compiles down to PHP code, unlike PHP, Twig is clean on the eyes , flexible and also quite *easy* to have dynamic layout site with ease ,without pulling your hair out. Twig is trusted by various platforms. It was created by the guys behind Symfony.
      Take this code as an example
      {% for user in users %} <h1>* {{ user }}</h1> {% endfor %} This will simply be the equivalent in PHP World
      <?php $userArray = ["Nigeria","Russia"]; foreach($userArray as $user): ?> <h1><?= $user ?></h1> <?php endforeach; The PHP code though looks simple enough however, you start to notice that you have to be concerned about the PHP tags by ensuring they are closed  properly , most times projects gets bigger and comes complex and harder to read/grasp, and also in PHP you can explicitly create variables in the template making it very hard to read as it grows and prone to getting messy WordPress is a major culprit when it comes to that regard.
      Have you ever wanted to created separate layouts for different pages and  break your sites into different parts e.g Sidebar, Comment Section, Header Section ? the regular approach would be to create individual pages for each section and simply add them as templates for the pages and with time, you can end up having tons of templates, however Twig allows you to easily inherit templates and also override the templates where you can inject content into the block easily. Don't worry if you don't understand the concept, the following parts will explain with an example of how to easily inherit layouts and templates.
      Layout
      <!DOCTYPE html> <html lang="en"> <head> {{include("layout/elements/header.twig")}} </head> <body> <div class="container-fluid" id="minimal"> <header id="pageIntro"> <div class="bio_panel"> <div class="bio_section col-md-6"> <h1>Okeowo Aderemi</h1> <h2>{{ page.body }}</h2> </div> </div> <div class="clearfix"></div> </header> <section id="page-body"> <div class="container"> <div id="intro" class="col-md-7 col-lg-7"> <h1>About me</h1> <h2> {{ page.summary }} </h2> </div> {block name="content"}{/block} <a style="font-size:1.799783em; font-style:italic;color:#d29c23" href="{{pages.get('/notes').url }}">Read more articles</a> </div> <div class="clearfix"></div> </div> </section> </div> <footer> <div class="header-container headroom headroom--not-top headroom--pinned" id="header-container"> {{include("layout/elements/footer.twig")}} </div> </footer> </body> </html> This is basically a layout where we specify blocks and include other templates for the page, don't panic if you don't understand what is going on, I will simply break down the weird part as follows:
      Include
      This basically is similar to native PHP 'include', as it's name suggests it simply includes the templates and injects the content into the layout , nothing out of the ordinary here if you are already familiar with php's include function.
      {{ output }}
      This simply evaluates the expression and prints the value, this  evaluate expressions, functions that return contents , in my own short words it's basically the same as <?= output ?> except for the fact that it's cleaner to read.
      {% expression %}
      unlike the previous this executes statements such as for loops and other Twig statements.
      {% for characters in attack_on_titans %} <h1> {{characters}} </h1> {% endfor %} This  executes a for loop and within the for loop, it creates a context to which variables in that context can be referenced and evaluated, unlike dealing with the opening and closing PHP tags, Twig simply blends in with markup and makes it really quick to read. 
      I will simply post the contents of both the header and footer so you can see the content of what is included in the layout
      header.php
      <meta charset="utf-8"/> <meta content="IE=edge" http-equiv="X-UA-Compatible"/> <meta content="width=device-width, initial-scale=1" name="viewport"/> <title> {{ page.title }} </title> <link href=" {{config.urls.templates }}assets/css/bootstrap.min.css" rel="stylesheet"/> <link href="{{config.urls.templates }}assets/css/main.min.css" rel="stylesheet"/> <link rel='stylesheet' type='text/css' href='{{config.urls.FieldtypeComments}}comments.css' /> <link rel="stylesheet" href="{{config.urls.siteModules}}InputfieldCKEditor/plugins/codesnippet/lib/highlight/styles/vs.css"> <script type="text/javascript" src="{{config.urls.siteModules}}InputfieldCKEditor/plugins/codesnippet/lib/highlight/highlight.pack.js"></script> <script src="{{config.urls.templates }}assets/js/vendors/jquery-1.11.3.min.js"> </script> <script src="{{config.urls.templates }}assets/js/vendors/bootstrap.min.js"> </script> <script src="{{config.urls.FieldtypeComments}}comments.js"></script> <link rel="stylesheet" type='text/css' href="{{config.urls.templates}}js/jquery.fancybox.min.css"> <script src="{{config.urls.templates}}js/jquery.fancybox.min.js"></script> {block name="javascriptcodes"}{/block} footer.php
      <nav class="site-nav pull-right"> <div class="trigger"> <a class="page-link" href="{{pages.get('/about').url}}"> <span>{</span> About <span>}</span> </a> <a class="page-link" href="{{pages.get('/notes').url}}"> <span>{</span> Journals <span>}</span> </a> <a class="page-link" target="_blank" href="https://ng.linkedin.com/in/okeowo-aderemi-82b75730"> <span>{</span> Linkedin <span>}</span> </a> <a class="twitter page-link" target="_blank" href="https://twitter.com/qtguru"> <span>{</span> Twitter <span>}</span> </a> </div> </nav> There's nothing special here, other than twig simply injecting these fragments into the main layout , the next part is the most interesting and important concept and benefit that Twig has to offer
      {% block content %}{% endblock %}
      This tag simply creates a placeholder in which the content would be provided by the template inheriting this layout, in lay terms it simply means child templates will provide content for that block, the 'content' simply uses the name 'content' to refer to that specific block, so assuming we were to inherit this template it would simply look like this.
      Inheriting Template Layout
      {% extends 'layout/blog.twig' %} {% block content %} <div class="container blog-container"> <section class="blog"> <header class="blog-header"> <h1> {{page.title}} </h1> <h5 class="blog_date"> {{page.published|date("F d, Y")}} </h5> <br> </br> </header> <div class="blog_content"> <hr class="small" /> {{page.body}} <hr class="small" /> </div> </section> </div> {% endblock %} {% block nav %} <div class="col-md-4 col-xs-4 col-sm-4 prev-nav"> <a href="{{page.prev.url}}"> ← Prev </a> </div> <div class="col-md-4 col-xs-4 col-sm-4 home-nav"> <a href="{{homepage.url}}"> Home </a> </div> <div class="col-md-4 col-xs-4 col-sm-4 next-nav"> <a href="{{page.next.url}}"> Next → </a> </div> {% endblock %} In this snippet you can easily notice how each blocks previously created in the header and layout are simply referenced by their names, by now you will notice that twig doesn't care how you arrange the order of each block, all Twig does is to get the contents for each blocks in the child templates and inject them in the layout theme, this allows flexible templating and also extending other layouts with ease.
      Twig in Processwire
      Thanks to @Wanze we have a Twig Module for Processwire and it's currently what i use to build PW solutions to clients
      https://modules.processwire.com/modules/template-engine-twig/
      The Modules makes it easy to not only use Twig in PW but also specify folders to which it reads the twig templates, and also injects Processwire objects into it, which is why i can easily make reference to the Pages object, another useful feature in this module is that you can use your existing template files to serve as the data provider which will supply the data to be used for twig template.
      take for example, assuming I wanted the homepage to display the top six blog posts on it, TemplateEngineTwig will simply load the home.php ( Depending on what you set as the template), it is also important that your twig file bears the same name as your template name e.g home.php will render into home.twig here is an example to further explain my point.
      home.php
      <?php //Get the Top 6 Blog Posts $found=$pages->find("limit=6,include=hidden,template=blog-post,sort=-blog_date"); $view->set("posts",$found);  
      The $view variable is the TemplateEngine which in this case would be Twig, the set method simply creates a variables posts which holds the data of the blog posts, the method allows our template 'blog.twig' to simply reference the 'posts' variable in Twig Context. Here is the content of the 'blog.twig' template
      blog.tpl
      {% extends 'layout/blog.twig' %} {% block content %} <div class="block_articles col-md-5 col-lg-5"> {% for post in posts %} <div class="article_listing"> <span class="article_date"> {{post.published}}</span> <h2 class="article_title"> <a href="{{post.url}}">{{post.title}}</a> </h2> </div> {% endfor %} {% endblock %} So home.php sets the data to be used in home.tpl once Twig processes the templates and generates the output, twig takes the output from the block and injects it in the appriopriate block in the layout, this makes Processwire templating more flexible and fun to work with. 
      The major advantage this has; is that you can easily inherit layouts and provide contents for them with ease, without the need of running into confusions when handling complex layout issues,an example could be providing an administrator dashboard for users on the template side without allowing users into the Processwire back-end. You can also come up with several layouts and reusable templates.
       
      Feel free to ask questions and any concerns  in this approach or any errors I might have made or overlooked.
      Thanks
       
       
       
    • By matsn0w
      Hey everyone, hope you're all doing well!
      I'm building my first ProcessWire website at the moment, which is of course a very good way to understand all of the possibilities ProcessWire has to offer. But that also means that I'm facing some troubles now and then, and so is the case right now.
      I made a template for a couple of pages, like the homepage, the contact page, etc. I am using Bootstrap 4.0 for the layout. 
      So here's the deal: I want to show an alert box on top of every page, warning the user that the website is still under construction. Of course, I can just include the code and add the fields I made for the alert into the template, but that means I have to do that for every page, which I obviously don't want. So I made a template with the code and fields for the alert. When I did this, I realised that I can create multiple alerts this way, so I made two pages, containing different alerts. (And converted the code into a foreach-loop in the template).
      But now my question; how can I include these pages in a different template? Can I make a field or something to insert a page or is this simply not possible? Or do I have to approach this in a different way?
      I hope I explained my problem clear!
      Thank you in advance,
      matsn0w
    • By pycode
      Hello PW, 
      discovered few days ago this awesome cms and now want to start a project on it, but need some help. I'm coming from the drupal side, which I kinda like, but it is not usable for smaller projects like I need now. I like it's way to build to content from the ground up, but it feels heavy, don't know why. PW feels really light and want to give it a try.
      Long story short, development it is a hobby for me, so everything I do is self-learned throw try & error, no programming skills yet. I want to learn JS now, and for that, want to translate a website to my native Romanian language so I can learn myself and others in the future. The site I'm talking about is www.learn.javascript.ru
      I want to build a similar structured site (please see the attached image):

      Home / Projects / About will be basic page template based, no problem with them.
      mysite.com/javascript/
      Starting Learn JavaScript will be a basic page template as well, I can make it statit, as it will contain some info and links to the Sections of the JS theory pages.
      mysite.com/javascript/section-name/
      By accessing a section page, I want to see again some description text and links of the attached unit pages to this section, so when I open any section it shows me all the attached unit pages to it. On the sidebar, I need to render links to all the sections, just that.
      Next is unit pages like mysite.com/javascript/section-name/unit-name/
      Here goes the units text, main content in other words, like a blog post. The key point is to have a dropdown and select the section page for it. For sidebar, I want to render the list with links for every headline from the unit page. Will do it by using Jumplinks Hanna Code, I believe it will do the job perfectly.
      Who can give me a hand with the templates?
      first /javascript/ page I can do as a basic page.
      next /javascript/section-name/ don't know. what fields should it contain for linking units?
      and last /javascript/section-name/unit-name/ again, what field needs to be used for linking? Page refference I believe?
      How I write it to templates?
      Would be gratefull for your help guys,
      Thank you
       
    • By rareyush
      I am trying too create a custom field where when user select to create a category 2 text area shows where one title of the category goes & another for some content.
      Like in a picture I want 2 text areas when I click on create new