Anders Posted February 3, 2019 Share Posted February 3, 2019 Consider this example, where I want to print a list of teasers (linked title + summary) for news articles: $content = ""; foreach ($pages->find("template=article") as $article) { $content .= wireRenderFile('teaser', array("item" => $article)); } It works, but I find the code quite ugly. I would much prefer to be able to switch the call to wireRenderFile to something more like this: $article->renderWith("teaster"); Or even better, replace the whole thing with something like this: $pages->find("template=article")->renderAllWith("teaser"); Are there any functions like that? I searched the API, but couldn't find anything. Or is there any other way to make my code look better? Or is my quest completely misquided here? I just started out with PW today, so I have no clue what I am doing yet. I already love it though! 1 Link to comment Share on other sites More sharing options...
Robin S Posted February 3, 2019 Share Posted February 3, 2019 Welcome to the PW forums @Anders! 32 minutes ago, Anders said: Consider this example, where I want to print a list of teasers (linked title + summary) for news articles: There are many different ways you could do this and at the end of the day it comes down to personal preference. Myself, if this was a one-off listing of teasers that wasn't to be used on other templates I would tend to build the markup directly in the template file and not render any other files. And if it was a listing that was to be used in several template files I would tend to render a file that looped over multiple pages and I would pass those pages to the rendered file. I prefer to output markup directly and make use of the Markup Regions feature, but to keep with your case of populating a $content variable it would be something like this: $content .= $files->render('teasers', ['items' => $pages->find("template=article")]); BTW, the wireRenderFile() function is sort of obsolete as far as I can see because it is just an alias for $files->render(). But if you wanted to render a page with something similar to your example... 37 minutes ago, Anders said: $article->renderWith("teaster"); ...then you could look at the (largely undocumented) $page->render() method. The best resource that I know of for this method is Ryan's post here: Also you can read the comments for PageRender::renderPage() in /wire/modules/PageRender.module (which is what $page->render() calls behind the scenes). So you could do something like: foreach ($pages->find("template=article") as $article) { $content .= $article->render('teaser.php'); } 2 1 Link to comment Share on other sites More sharing options...
Anders Posted February 3, 2019 Author Share Posted February 3, 2019 Your last code block (with $article->render) seems to render not only the teaser, but the full page of the article after that! But it doesn't matter, because I think I like your $file->render suggestion the best anyway. I'll go with that. Thanks a lot for the help! Link to comment Share on other sites More sharing options...
Anders Posted February 4, 2019 Author Share Posted February 4, 2019 On second thought.. Turns out module development is so simple due to the elegant API, so I went ahead and wrote myself a module: <?php namespace ProcessWire; class RenderWith extends WireData implements Module { public static function getModuleInfo() { return [ 'title' => 'RenderWith', 'summary' => 'API extention for rendering pages with different templates.', 'version' => 1, 'autoload' => true ]; } public function ready() { $this->addHook('Page::renderWith', $this, 'renderWith'); $this->addHook('PageArray::renderWith', $this, 'renderManyWith'); } public function renderWith($event) { $page = $event->object; $template = $event->arguments(0); $event->return = wireRenderFile($template, ["item" => $page]); } public function renderManyWith($event) { $pages = $event->object; $template = $event->arguments(0); $content = ""; foreach ($pages as $page) { $content .= wireRenderFile($template, ["item" => $page]); } $event->return = $content; } } No idea if I am breaking any design principles or anything here, so viewer discretion is adviced. 3 Link to comment Share on other sites More sharing options...
Robin S Posted February 4, 2019 Share Posted February 4, 2019 26 minutes ago, Anders said: Your last code block (with $article->render) seems to render not only the teaser, but the full page of the article after that! Perhaps you have auto-prepended and/or auto-appended template files in your /site/config.php, in which case you would want to use the $options array to override those when rendering the page, e.g. foreach ($pages->find("template=article") as $article) { $content .= $article->render('teaser.php', ['appendFile' => null]); } 5 Link to comment Share on other sites More sharing options...
Anders Posted February 4, 2019 Author Share Posted February 4, 2019 @Robin S Yeah, that solved it. Thanks a lot - really appreciate it! 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