protro Posted Tuesday at 12:54 AM Share Posted Tuesday at 12:54 AM Hello PW forums, I have an interesting problem I am trying to solve. I am displaying a list of artists, that are children of the parent page Artists. {foreach $pages->get("name=artists")->children() as $item} These children pages act as tags for other pages which have a field 'artist', and are appropriately tagged. I am trying to send the link's href attribute to the latest project page for that artist, rather than the default, which is a sort of artist index page listing all the projects for that artist. <a href="{$pages->get('template=concert-visuals|broadcast|music-videos, artist.name={$item->name}')->first->url}"> {$item->title} </a> I can't seem to fetch anything. What am I missing here ? Link to comment Share on other sites More sharing options...
bernhard Posted Tuesday at 05:59 AM Share Posted Tuesday at 05:59 AM First thing to check is if your $pages->get() call works at all. For example in the tracy console. You are using $pages->get() which will return a single Page object (or NullPage), so your ->first is wrong, i guess. Next, I think you can't use { } brackets inside { } brackets when you are outputting a string. This will NOT work: {var $item = $pages->get(2)} <a href="{$pages->get("name={$item->name}")->url}"> {$item->title} </a> This will work: {var $item = $pages->get(2)} {var $url = $pages->get("name={$item->name}")->url} <a href="{$url}"> {$item->title} </a> And this is what I'd recommend you to do: Create a Site.module.php in /site/modules/Site <?php namespace ProcessWire; // expose the site module as global site() function function site(): Site { return wire()->modules->get('Site'); } // module code class Site extends WireData implements Module { public static function getModuleInfo() { return [ 'title' => 'Site', 'version' => '0.0.1', 'summary' => 'Site Module', 'autoload' => true, 'singular' => true, 'icon' => 'bolt', 'requires' => [ 'RockMigrations>=3.34', ], ]; } } Then add the following method: public function getShowByArtist(Page $item) { return wire()->pages->get('template=concert-visuals|broadcast|music-videos, artist.name={$item->name}'); } Which cleans up your template a lot and will help you to write better (DRY) code, as you have one place to store the logic. If you need the same link url in another place of your website you simple call the same method and not copy paste the selector. If the selector changes over time (for example adding another template to the selector) all your links will still work by only updating one place in your code (and not many). <a href="{site()->getShowByArtist($item)->url}"> {$item->title} </a> Or even better use Custom Page Classes and add the getShowByArtist method directly to your $page object. 3 Link to comment Share on other sites More sharing options...
protro Posted 17 hours ago Author Share Posted 17 hours ago thank you so much @bernhard for showing the method for building a module. I really appreciated this answer. I ended up modifying the code to for a simplified extension of a Custom Page Class, in case anyone else want's to see how that works. in DefaultPage.php <?php namespace ProcessWire; class DefaultPage extends Page { public function getShowByArtist() { return $this->wire()->pages->get("template!=news-item, artist.name='{$this->name}'"); } } and in the template like so: <a href="{$item->getShowByArtist()->url}"> {$item->title} </a> By the way @bernhard, maybe you could elaborate something I encountered that I can't quite piece together. This function `getShowByArtist()` is getting called on the home template, and on the front-end appears on the homepage, but when I tried adding the above function declaration to HomePage.php custom page class, I would get exceptions that the function is unavailable/not call-able. I am using the Rockfrontend method such that in site/templates/layouts/home.php <?= $rockfrontend->renderIf("sections/home.latte", "template=home") ?> And in home.latte is where I am calling the function inside of the a href (as above). However, it only seems to work when I put the getShowByArtist() function declaration inside of the DefaultPage.php custom page class … even though in Tracy Debugger it shows my template as home and the class as \ProcessWire\HomePage on the page in which this function gets invoked (correctly). Why could that be ? Any ideas ? Again, your help has been much appreciated. I might leave the function inside DefaultPage.php for now. Link to comment Share on other sites More sharing options...
bernhard Posted 5 hours ago Share Posted 5 hours ago 12 hours ago, protro said: in DefaultPage.php Nice, looks a lot better no in my opinion 👍 12 hours ago, protro said: Why could that be ? Any ideas ? That sounds strange. I think the only explanation is that ->getShowByArtist() is called on a non-HomePage object. When it throws an Exception you should get a backtrace that you can in spect. Go through the list step by step and inspect which call triggered which next step. This list can be quite long, so I first focus on all files that are under my control and skip those from the core. TracyDebugger is usually really helpful here and you can even click on the line in the stack and land directly in your IDE at the right position. Hope that helps 🙂 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