Jump to content

Recommended Posts

Posted

is this possible? To keep things organised I'd like to have a separate directory for each set of related templates. They would all still be in the main templates directory, just in various subdirectories.

 

Surely I'm not restricted to having every template file in the same directory?

Posted

Do you have so many templates that you need them in separated sub dirs ? Its all about organizing the site folder tree with your page tree ! Through time I also restructured things in the site folder but I keep my templates in the root of the templates folder. Instead I keep html format for different web site pages on the front in separate folders (page views) and any navigation (topnav, subnav) in separated folders. I also create separated associated css files for them in the styles folder. This speeded up my editing and maintenance time.

  • Like 1
Posted

I am a total offender of using a ridiculous amount of templates, but there are many ways around this. Most of the time you can standardize your templates so that every different type of page doesn't need to use a different template, and just includes the functions that are applicable for that part of your site. Over the years there have been several discussions on this subject, and what I have seen everything come down to is just a matter of implementation. If you find that you are getting too many templates then possibly look into how you can make your code a bit more reusable and aware of its context. Here is a good starter, but I recommend googling our forum and focus on posts in relation to page structure.
 

 

  • Like 2
Posted

I set all my templates up initially as "no-file" templates, using the Create a new template without a file... option, then go to the Files tab and enter "main" as the Alternate Template Filename. This points all my "logical" templates to a single "physical" template at /site/templates/main.php. From there, you can include the actual template any number of ways, the simplest being something like this:

echo wireRenderFile('./views/'.$page->template->name.'/'.$page->template->name.'.inc');

The main reason I do it this way is that I also use AllInOneMinify for asset management, and I have it set up to automatically include an associated javascript and/or LESS file for each template if present, so for the "home" template, instead of having home.php loose in the templates directory, I have:

/site/templates/views/home/

...which contains:

home.inc
home.js
home.less


 

 

  • Like 4
Posted
1 hour ago, Jason Huck said:

I set all my templates up initially as "no-file" templates, using the Create a new template without a file... option, then go to the Files tab and enter "main" as the Alternate Template Filename. This points all my "logical" templates to a single "physical" template at /site/templates/main.php. From there, you can include the actual template any number of ways, the simplest being something like this:


echo wireRenderFile('./views/'.$page->template->name.'/'.$page->template->name.'.inc');

 

I like the sound of this!  Gonna give it a try, thanks for sharing.

Posted
5 hours ago, Jason Huck said:

The main reason I do it this way is that I also use AllInOneMinify for asset management, and I have it set up to automatically include an associated javascript and/or LESS file for each template if present

Could you please elaborate a bit more on how to achieve this with AIOM? @Jason Huck

Posted
On 9/24/2016 at 11:15 AM, Jason Huck said:

echo wireRenderFile('./views/'.$page->template->name.'/'.$page->template->name.'.inc');

I tried this method but found my defaults set in '_init.php' would be undefined when the page loaded. LIke this:

// _init.php - prepended to current page template, i.e. main.php
$content = $page->body;
$summary = $page->summary;

// main.php
<?php
    //include($page->template->name.'.inc'); //works fine
    echo wireRenderFile($page->template->name .'.inc'); // 'Notice: Undefined variable: 'summary'
?>

// basic-page.inc (template in admin alternate name = "main.php")
<?php if ($summary) {
    echo $summary;
}
    echo $content;

Still not 100% sure why this happens.

Posted

the wireRenderFile() function won't have access to your custom variables, you would need to do this:

$viewBag = array(
  'content' => $content,
  'summary => '$summary,
);

then

echo wireRenderFile($page->template->name .'.inc', $viewBag);

 

  • Like 2
Posted
56 minutes ago, Macrura said:

the wireRenderFile() function won't have access to your custom variables, you would need to do this:


$viewBag = array(
  'content' => $content,
  'summary => '$summary,
);

then


echo wireRenderFile($page->template->name .'.inc', $viewBag);

 

Thanks for the info.

Posted
On 9/24/2016 at 11:31 AM, 3fingers said:

Could you please elaborate a bit more on how to achieve this with AIOM? @Jason Huck

It's pretty simple. AIOM accepts an array of files to include, and fails gracefully when one is missing. I keep the arrays in $page for portability. I load third party libraries and site wide stuff first, then layer on the view-specific assets if available, something like this:

<?php
    $page->styles = array(
        // third party libraries first...
        'lib/normalize-css/normalize.css',
        // ...etc...
        // site-wide/global assets next. this file imports many separate stub files...
        'styles/main.less',
        // now add the view file. you can check for its existence first,
        // but a missing file won't prevent the rest from working
        'views/'.$page->template->name.'/'.$page->template->name.'.less'
    );

    // do the same thing for scripts
    // $page->scripts = array(...
?>

...then in your template:

<link rel="stylesheet" href="<?= AIOM::CSS($page->styles); ?>">

...and:

<script src="<?= AIOM::JS($page->scripts); ?>"></script>

 

  • Like 1
Posted
14 hours ago, Macrura said:

the wireRenderFile() function won't have access to your custom variables, you would need to do this:


$viewBag = array(
  'content' => $content,
  'summary => '$summary,
);

then


echo wireRenderFile($page->template->name .'.inc', $viewBag);

 

Apologies for quoting this again but there's something that's been bugging me. What's the point of using this method? I see structures like this when looking at MVC patterns for processwire:

/templates/
-main.php (master template)
-home.php
-basic-page.php
--/views/
---home-view.php
---basic-page-view.php

But why use the wireRenderFile() function at all? What's the advantage of having a '$viewBag' array in '_init.php' and then having to pass this around to various templates. From what I read, the idea is that the main logic would go in home.php and the HTML and basic logic would be more for home-view.php. However, what I've found that I'm struggling to see how to separate these things out. For example I have the following which outputs a basic page rendering the title/body/summary and a section underneath rendering the child pages title/summary:

// _func.php
function showChildPagesSummary() {
    $str = '';

    foreach(wire('page')->children as $item) {

        if($item->summary) {
            $str .= "<div class=\"section\">";
            $str .= "<h3><a href=\"$item->url\">$item->title</a></h3>";
            $str .= $item->summary;
            $str .= "</div>";
        }
    }
    return $str;
}

// basic-page.inc
<?php if ($summary) {
    echo $summary;
}

    echo $content;

    if (showChildPagesSummary()) {
        echo "<h2>In this section</h2>";
        echo showChildPagesSummary();
    }

//main.php
        <!-- main content -->
        <div id="content">
            <h1><?php echo $title; ?></h1>
            <?php include($page->template->name.'.inc'); ?>
        </div>

Why not just use include() like above which has access to the custom variables in the first place (in '_init.php')?

So I read over https://medium.com/@clsource/the-wire-render-pattern-806bf6d6097a#.3rpw6z6sq a few times and it looks to be abstracting away from functionality that's baked in already. I guess I just can't see a real world example where using views makes more sense (and wireRenderFile() along with custom variables passed as an array) rather than plain old include().

Any ideas would be appreciated. Thanks.

Posted
34 minutes ago, SamC said:

Why not just use include() like above which has access to the custom variables in the first place (in '_init.php')?

I tend to agree, and use include() over wireRenderFile() myself. I suppose one reason some prefer wireRenderFile() is the scope of variables is limited so you don't run the risk of overwriting a variable of the same name in your template file.

As for using a view file separate to the the template file, it depends how strictly necessary you consider "separation of concerns" to be. Definitely good if you are part of a team and want to hand the view file on to a front-end person who shouldn't be dealing with business logic. Or if you have a lot of logic that you don't like cluttering up the view. As a solo designer-developer, I like to have my business logic in my template so I can see what is going into variables, but I guess a lot of people would frown on that.

  • Like 1
Posted

FWIW, I don't do it to enforce MVC at all, which IMO is often overkill for typical web projects. I also don't have the kind of duplication you've illustrated for each template, with e.g. both home.php AND home.inc files. I route everything through a single main.php file. That file is just a series of includes for various global functions and configuration, and at the bottom I use output buffering to include the page-specific view and wrap it with a global base template. I prefer doing it that way so that all of the global markup is in a single file rather than split across separate "head.inc" and "foot.inc" includes (which then have to live in every template file). I also like having view-specific js and css assets together in the same folder as the view. That makes more sense to me than organizing assets by file type.

I could just as easily have used wireRenderFile() instead of output buffering. I provided that as the example simply because it's available in PW and this is a PW forum. I also tend to store additional properties in $page rather than creating global variables (e.g., $page->foo = 'bar' instead of $foo = 'bar'), which makes it a lot easier to use wireRenderFile(). As long as you pass in $page, you know you've got everything you need, and you can add more properties later without worrying about updating your "view bag."

  • Like 4
Posted
3 hours ago, Jason Huck said:

I also tend to store additional properties in $page rather than creating global variables (e.g., $page->foo = 'bar' instead of $foo = 'bar'), which makes it a lot easier to use wireRenderFile(). As long as you pass in $page, you know you've got everything you need, and you can add more properties later without worrying about updating your "view bag."

I especially like this idea!

Posted

Thanks for all the replies, it's really helpful to a beginner.

8 hours ago, Robin S said:

I tend to agree, and use include() over wireRenderFile() myself. I suppose one reason some prefer wireRenderFile() is the scope of variables is limited so you don't run the risk of overwriting a variable of the same name in your template file.

As for using a view file separate to the the template file, it depends how strictly necessary you consider "separation of concerns" to be. Definitely good if you are part of a team and want to hand the view file on to a front-end person who shouldn't be dealing with business logic. Or if you have a lot of logic that you don't like cluttering up the view. As a solo designer-developer, I like to have my business logic in my template so I can see what is going into variables, but I guess a lot of people would frown on that.

I think each to their own. If there's no team involved, I don't think it matters. Personally, this is what I am enjoying most about PW. Coming mainly from Drupal 7, the ability to just add fields, create a template, and use an API to manually spit the data out onto a webpage anywhere I want, with the markup I want is rather liberating. I don't have separate 'header.inc' and 'footer.inc' files, they never usually change so I keep the whole lot in main.php, just change the middle content section.

6 hours ago, Jason Huck said:

I also tend to store additional properties in $page rather than creating global variables (e.g., $page->foo = 'bar' instead of $foo = 'bar'), which makes it a lot easier to use wireRenderFile(). As long as you pass in $page, you know you've got everything you need, and you can add more properties later without worrying about updating your "view bag."

This sounds quite interesting to me also but I'm not sure I understand what you mean by pass in $page to wireRenderFile e.g., $page->foo = 'bar'? Say I have this:

// _init.php
$home = $pages->get('/');
$title = $page->get('headline|title');
$content = $page->body;
$summary = $page->summary;

$viewBag = array(
    'home' => $home,
    'title' => $title,
    'content' => $content,
    'summary' => $summary
);

$page->foo = 'bar' // where would this fit in?


// main.php
<?php
    echo wireRenderFile($page->template->name .'.inc', $viewBag);
?>

 

Posted

@SamC in your example, all of your variables are things that you can access directly from $page, so you could, if you wanted, just pass in $page instead of all of those individual variables. If you have anything extra you want to add, you can just add it. Just be careful not to accidentally override the built-in properties & methods.
 

$page->any_key => 'any value';
$page->another_key => 'another value';
echo wireRenderFile($page->template->name.'.inc', array('page' => $page)); // everything in $page will now be available within this template

 

  • Like 4
Posted
11 minutes ago, Jason Huck said:

@SamC in your example, all of your variables are things that you can access directly from $page, so you could, if you wanted, just pass in $page instead of all of those individual variables. If you have anything extra you want to add, you can just add it. Just be careful not to accidentally override the built-in properties & methods.
 


$page->any_key => 'any value';
$page->another_key => 'another value';
echo wireRenderFile($page->template->name.'.inc', array('page' => $page)); // everything in $page will now be available within this template

 

Thanks. This might come in handy.

  • 1 month later...
Posted
On 26.9.2016 at 9:18 PM, Jason Huck said:

@SamC in your example, all of your variables are things that you can access directly from $page, so you could, if you wanted, just pass in $page instead of all of those individual variables. If you have anything extra you want to add, you can just add it. Just be careful not to accidentally override the built-in properties & methods.
 


$page->any_key => 'any value';
$page->another_key => 'another value';
echo wireRenderFile($page->template->name.'.inc', array('page' => $page)); // everything in $page will now be available within this template

 

Great idea. Just a thought: Couldn't it be overkill to pass the whole $page object to the function (in case it has a lot of properties&methods, and the file to render needs just a few of them)?

Posted
1 hour ago, ottogal said:

Great idea. Just a thought: Couldn't it be overkill to pass the whole $page object to the function (in case it has a lot of properties&methods, and the file to render needs just a few of them)?

Everything is in memory already anyways. You could even use $this->page in the included file even if you don't explicitly give it the object as $page. So there's not really overhead.

  • Like 1
Posted (edited)

Since the Page object is already in the memory, I can't see any performance related issues with it, but I'm not a PHP resources optimizer wizard, so someone might chime in to shed more light on it.

Edit: @LostKobrakai was faster than me :) 

Edited by szabesz

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.
×
×
  • Create New...