Jump to content

Display related pages


Edward Ver
 Share

Recommended Posts

Hi Guys,

I want to display pages with the same tag. But nothing is showing. I'm new to this and I'm no PHP DEV. Any help to guide me to the right approach will be a great help.

Project details page (work_details.php template)
    - work_hero_repeater (repeater)
        - tags (text field)
        - client_name (Text field)
        - hero_image (Image Field)

<?php $items = $pages->find("template=work_details, tags=$page") ?>
<ul>
    <?php foreach($items as $item): ?>
        <?php foreach($item->work_hero_repeater as $work_hero_repeaters) ?>
            <li><?= $work_hero_repeaters->work_hero_image->getCrop('hero')->url ?>
            <a href="<?= $work_hero_repeaters->pager_link->url ?>"></a>
            </li>
    <?php endforeach; ?>
</ul>

 

Link to comment
Share on other sites

$items = $pages->find("template=work_details, tags=$page->tags");

'tags' is a textfield, but you're passing the entire page object (tags=$page"). 
You need to pass the tags textfield value instead.

I'm assuming that your textfield contains only one tag, e.g: new and not multiple tags like: new, cool, favorites 

If you want to learn more about selectors, try this: https://processwire.com/docs/selectors/#api-variables-in-selectors

 

Also, you are missing some things in the repeater foreach

<?php $items = $pages->find("template=work_details, tags='{$page->tags}'"); ?>
<ul>
    <?php foreach($items as $item): ?>	
        <?php foreach($item->work_hero_repeater as $work_hero_repeaters): //here! ?>
            <li>
                <?= $work_hero_repeaters->work_hero_image->getCrop('hero')->url ?>
                <a href="<?= $work_hero_repeaters->pager_link->url ?>"></a>
            </li>
        <?php endforeach; //and here! ?>
    <?php endforeach; ?>
</ul>

 

  • Like 2
Link to comment
Share on other sites

10 hours ago, Sanyaissues said:
$items = $pages->find("template=work_details, tags=$page->tags");

'tags' is a textfield, but you're passing the entire page object (tags=$page"). 
You need to pass the tags textfield value instead.

I'm assuming that your textfield contains only one tag, e.g: new and not multiple tags like: new, cool, favorites 

If you want to learn more about selectors, try this: https://processwire.com/docs/selectors/#api-variables-in-selectors

 

Also, you are missing some things in the repeater foreach

<?php $items = $pages->find("template=work_details, tags='{$page->tags}'"); ?>
<ul>
    <?php foreach($items as $item): ?>	
        <?php foreach($item->work_hero_repeater as $work_hero_repeaters): //here! ?>
            <li>
                <?= $work_hero_repeaters->work_hero_image->getCrop('hero')->url ?>
                <a href="<?= $work_hero_repeaters->pager_link->url ?>"></a>
            </li>
        <?php endforeach; //and here! ?>
    <?php endforeach; ?>
</ul>

 

Thank you very much Sanyaissues
That works like a charm. Still learning PW, and lovin it so far.

Link to comment
Share on other sites

Just one more issue, Yes, each tag field only has one tag.

Even though each page has e.g:

Page1

 image.png.a1969f1cbe788cfc049f2aa62e881c27.png

 

Page2 

image.png.2808c259195f25aa0aff452aafe92bbc.png

They  all  show on a page. I only want pages with the same tag visible on a page.

Any ideas? or I'm doing something wrong.

Thanks in advance

Edited by Edward Ver
Link to comment
Share on other sites

To get the things done you need to play around with the logic until you hit the pot (usually the logic we write and the logic we think we write are different).

To find the issue, let's poke your logic a little:

// Find all pages with the template work_details and where the field tags is exactly the same as this page tags field
$items = $pages->find("template=work_details, tags=$page->tags");

When viewing Page1 that will be translated to:

//Pages with template work_details and field tags equal to branding/identity
$items = $pages->find("template=work_details, tags=branding/identity");

To discover why you aren't getting the results you are expecting, try something simple first:

// You can copy and paste each of these examples into your code

// First, let's verify if all the pages with a specific tag are being fetched.
// Print the title of all pages with a tags field containing "branding/identity"
$items = $pages->find("tags=branding/identity");
echo $items->each('{title}');

// Now, let's do the same dynamically and also print the value of the tags to understand what $page->tags contains.
// Print the title of all pages with a tags field equal to this page's tags field and print the value of tags
$items = $pages->find("tags=$page->tags");
echo $items->each('{title} <br>');
echo "Tags value: " . $page->tags;

// Also, note we can search for tags fields that contain a string using %= instead of =
// Print the title of all pages containing the string from the page's tags field
$items = $pages->find("tags%=$page->tags");
echo $items->each('{title} <br>');
echo "Tags value: " . $page->tags;

As as side note, debugging will be way easier if you install TracyDebugger.  

  • Like 1
Link to comment
Share on other sites

2 hours ago, Sanyaissues said:

To get the things done you need to play around with the logic until you hit the pot (usually the logic we write and the logic we think we write are different).

To find the issue, let's poke your logic a little:

// Find all pages with the template work_details and where the field tags is exactly the same as this page tags field
$items = $pages->find("template=work_details, tags=$page->tags");

When viewing Page1 that will be translated to:

//Pages with template work_details and field tags equal to branding/identity
$items = $pages->find("template=work_details, tags=branding/identity");

To discover why you aren't getting the results you are expecting, try something simple first:

// You can copy and paste each of these examples into your code

// First, let's verify if all the pages with a specific tag are being fetched.
// Print the title of all pages with a tags field containing "branding/identity"
$items = $pages->find("tags=branding/identity");
echo $items->each('{title}');

// Now, let's do the same dynamically and also print the value of the tags to understand what $page->tags contains.
// Print the title of all pages with a tags field equal to this page's tags field and print the value of tags
$items = $pages->find("tags=$page->tags");
echo $items->each('{title} <br>');
echo "Tags value: " . $page->tags;

// Also, note we can search for tags fields that contain a string using %= instead of =
// Print the title of all pages containing the string from the page's tags field
$items = $pages->find("tags%=$page->tags");
echo $items->each('{title} <br>');
echo "Tags value: " . $page->tags;

As as side note, debugging will be way easier if you install TracyDebugger.  

Well, it was silly of me.

The Field "tags" was inside a repeater of the page template. I move it to out of the repeater, and it works now. Hey, don't judge me, I'm still learning :P. 

Thank you for your precious time Sanyaissues

 

Edited by Edward Ver
  • Like 1
Link to comment
Share on other sites

This is the one that works for me:

<?php if ($page->tags): ?>
<?php $items = $pages->find("template=work_details,id!=$page,tags='{$page->tags}'"); ?>
<?php foreach($items as $item): ?>	
<div class="w-full py-16 bg-slate-50">
    <div class="max-w-[89.5rem] md:mx-auto">
    <h3 class="w-full !mt-0 mb-6 text-2xl text-center ">Related Projects</h3>
        <div class="flex flex-row flex-wrap items-center justify-center gap-4 lg:flex-col ">
            <?php foreach($item->work_hero_repeater as $work_hero_repeaters):  ?>
                    <div class="relative group">
                        <div class="overflow-hidden">
                            <img class="lozad w-full rounded-sm mt-0 lozad group-hover:scale-105 transform-gpu  group-hover:saturate-150 transition-all duration-[600ms] " data-src="<?= $work_hero_repeaters->work_hero_image->getCrop('gridsquare')->url ?>"   alt="<?= $work_hero_repeaters->work_hero_image->description ?>" >
                        </div>
                        <h5 class="pt-5 text-xl font-gloock"><?= $work_hero_repeaters->work_client ?></h5>
                        <p class="flex-1 px-5 text-left font-raleway md:px-0"><?= $work_hero_repeaters->work_hero_subheading ?></p>
                        <p class="top-0 left-0 hidden w-full h-full"><?= $work_hero_repeaters->tags ?></p>
                        <a class="absolute top-0 left-0 w-full h-full group" href="<?= $work_hero_repeaters->pager_link->url ?>"></a>
                    </div>
            <?php endforeach; ?>

        </div> 
    </div>         
</div>
<?php endforeach; ?>   
<?php else: ?>
<?php endif; ?>

I hope someone will find it useful. 

BTW Sanyaissues , How do you change it to accept more than 1 tag. If  I use 2 tags e.g: Illustration , Logo, it does not work.

Link to comment
Share on other sites

@Edward Ver you can use the contains operator for that.

1. First, set your field to use Pipe as delimiter (edit field > input > tag delimeter). With that, if our Page1 has 3 tags: logo vector illustration, they will be stored like this: logo|vector|illustration

image.png.8d3ba6c8ccfb3b551263d107b0b26f4a.png

The pipe separator will be very useful because of this https://processwire.com/docs/selectors/#or-selectors1

Quote

OR selectors: matching one value or another
In instances where you need to match values in a single field with an either-or expression, the values should be split with the "or" operator, which is the pipe character "|". The following examples demonstrates its usage:

firstname=Mike|Steve
id=123|124|125
title*=Red|Blue|Green

 


2. Now lets find pages containing any of the tags of the page:

//This will find pages containing any of this tags logo|vector|illustration (including the current page)
$p =  $pages->find("tags*={$page->tags}");
echo $p->each('{title} <br>');

3. Let's remove the current page from the results:
 

// Option 1: find all the pages and remove the current page.
$p =  $pages->find("tags*={$page->tags}")->remove($page);
echo $p->each('{title} <br>');

//Option 2: find pages where the page ID isn't the same as the current page
$p =  $pages->find("id!={$page->id}, tags*={$page->tags}");
echo $p->each('{title} <br>');


 

 

  • Like 1
Link to comment
Share on other sites

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
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...