Anders Posted February 3, 2019 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
Robin S Posted February 3, 2019 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
Anders Posted February 3, 2019 Author 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!
Anders Posted February 4, 2019 Author 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
Robin S Posted February 4, 2019 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
Anders Posted February 4, 2019 Author Posted February 4, 2019 @Robin S Yeah, that solved it. Thanks a lot - really appreciate it! 1
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