Cal Posted September 23, 2016 Share Posted September 23, 2016 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? Link to comment Share on other sites More sharing options...
pwired Posted September 23, 2016 Share Posted September 23, 2016 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. 1 Link to comment Share on other sites More sharing options...
MuchDev Posted September 24, 2016 Share Posted September 24, 2016 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. 2 Link to comment Share on other sites More sharing options...
Jason Huck Posted September 24, 2016 Share Posted September 24, 2016 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 4 Link to comment Share on other sites More sharing options...
SamC Posted September 24, 2016 Share Posted September 24, 2016 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. Link to comment Share on other sites More sharing options...
3fingers Posted September 24, 2016 Share Posted September 24, 2016 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 Link to comment Share on other sites More sharing options...
SamC Posted September 25, 2016 Share Posted September 25, 2016 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. Link to comment Share on other sites More sharing options...
Macrura Posted September 25, 2016 Share Posted September 25, 2016 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); 2 Link to comment Share on other sites More sharing options...
SamC Posted September 25, 2016 Share Posted September 25, 2016 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. Link to comment Share on other sites More sharing options...
Jason Huck Posted September 26, 2016 Share Posted September 26, 2016 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> 1 Link to comment Share on other sites More sharing options...
SamC Posted September 26, 2016 Share Posted September 26, 2016 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. Link to comment Share on other sites More sharing options...
Robin S Posted September 26, 2016 Share Posted September 26, 2016 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. 1 Link to comment Share on other sites More sharing options...
Jason Huck Posted September 26, 2016 Share Posted September 26, 2016 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." 4 Link to comment Share on other sites More sharing options...
szabesz Posted September 26, 2016 Share Posted September 26, 2016 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! Link to comment Share on other sites More sharing options...
SamC Posted September 26, 2016 Share Posted September 26, 2016 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); ?> Link to comment Share on other sites More sharing options...
Jason Huck Posted September 26, 2016 Share Posted September 26, 2016 @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 4 Link to comment Share on other sites More sharing options...
SamC Posted September 26, 2016 Share Posted September 26, 2016 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. Link to comment Share on other sites More sharing options...
ottogal Posted November 20, 2016 Share Posted November 20, 2016 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)? Link to comment Share on other sites More sharing options...
LostKobrakai Posted November 20, 2016 Share Posted November 20, 2016 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. 1 Link to comment Share on other sites More sharing options...
szabesz Posted November 20, 2016 Share Posted November 20, 2016 (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 November 20, 2016 by szabesz Link to comment Share on other sites More sharing options...
ottogal Posted November 20, 2016 Share Posted November 20, 2016 Thanks to both of you for the clarification. I'll give it a try. 1 Link to comment Share on other sites More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now