Filter through multiple tags, sort them and remove duplicates

I am trying to filter some pages (products) based on few tags.

In my blueprint, I have:

Code: 12ax7, ecc83
----
Brand: Amperex, Telefunken
----
Manufacturer: Sylvania, Philips

I first split each tag:

<?php 
$codes = $page->code()->split(',');
$brands = $page->brand()->split(',');
$manufacturers = $page->manufacturer()->split(',');
?>

Then I start looping through each of the tags:

<?php foreach($codes as $item): ?>
	<li>
		<?php snippet('productTile', array('item' => $item)) ?>
	</li>
<?php endforeach ?>

<?php foreach($brands as $item): ?>
	<li>
		<?php snippet('productTile', array('item' => $item)) ?>
	</li>
<?php endforeach ?>

<?php foreach($manufacturers as $item): ?>
	<li>
		<?php snippet('productTile', array('item' => $item)) ?>
	</li>
<?php endforeach ?>

This produces a list of all the products, not in alphabetical order, and with duplicates too.

Is there a way to combine all these filtered products into one object / array (ex: $filtered), sort it alphabetically and remove duplicates, finally loop through it and export the list?

Something like:

<?php foreach($codes as $item): ?>
		add $item to $filtered
<?php endforeach ?>

<?php foreach($brands as $item): ?>
		add $item to $filtered
<?php endforeach ?>

<?php foreach($manufacturers as $item): ?>
		add $item to $filtered
<?php endforeach ?>

<?php $filtered = array_unique($filtered); ?>
<?php asort($filtered) ?>

Then I would finally output all these filtered results.

<?php foreach($filtered as $item): ?>
	<li>
		<?php snippet('productTile', array('item' => $item)) ?>
	</li>
<?php endforeach ?>

I don’t know what your snippet does, it should be fairly straightforward:

<?php $filtered = array();

foreach($codes as $item) {
  $filtered[] = $item;
}

foreach($brands as $item) {
  $filtered[] = $item;
}
foreach($manufacturers as $item) {
  $filtered[] = $item;
}

$filtered = array_unique($filtered);
sort($filtered);
?>

Your system works, but it is creating a $filtered array of my tags.

I would like instead to create a $filtered object containing all the pages, filtered by those tags, sorted alphabetically and with duplicates removed.

I am practically trying to create a “Related Pages” component.

I have the following “spaghetti” code working at the moment. It filter through each of the $tubeNames (Code) tags, then $brands tags or $manufacturers tags, but it break the results into buckets.

I would like instead to get all the results together into a $filtered object, much as $results for the search results, and then clean it of duplicates and organize it alphabetically.

In fact, part of the problem also affect my search page: I don’t know how to sort alphabetically the $results.

<?php 
$tubeNames = $page->tube_name()->split(',');
$brands = $page->brand()->split(',');
$manufacturers = $page->manufacturer()->split(',');


$brandsAndManufacturers = array();

foreach($brands as $item) {
  $brandsAndManufacturers[] = $item;
}

foreach($manufacturers as $item) {
  $brandsAndManufacturers[] = $item;
}

$brandsAndManufacturers = array_unique($brandsAndManufacturers);
sort($brandsAndManufacturers);

$counter = 0;
?>


<?php // Related Tubes ?>

<?php foreach($tubeNames as $tubeName): ?>
	<?php $filtered = $pages->index()->visible()->filterBy('tube_name',$tubeName); ?>		

	<?php echo "<h4>More $tubeName from these brands</h4>" ?>

	<?php foreach($brandsAndManufacturers as $keyword): ?>	

		<?php $filteredByBrandsAndManufacturers = $filtered->filterBy('brand',$keyword); ?>
		<?php $counter = $counter + count($filteredByBrandsAndManufacturers) ?>
		<?php foreach ($filteredByBrandsAndManufacturers as $item): ?>
			<?php if($item->title() != $page->title()): ?>
				<?php echo $item->title() ?><br>
			<?php endif ?>
		<?php endforeach ?>
	
		<?php $filteredByBrandsAndManufacturers = $filtered->filterBy('manufacturer',$keyword); ?>
		<?php $counter = $counter + count($filteredByBrandsAndManufacturers) ?>
		<?php foreach ($filteredByBrandsAndManufacturers as $item): ?>
			<?php if($item->title() != $page->title()): ?>
				<?php echo $item->title() ?><br>
			<?php endif ?>
		<?php endforeach ?>

	<?php endforeach ?>

	
	<?php if($counter < 4): ?>

			<?php echo "<h4>More $tubeName</h4>" ?>

			<?php foreach ($filtered as $item): ?>
					<?php if($item->title() != $page->title()): ?>
						<?php echo $item->title() ?><br>
					<?php endif ?>
			<?php endforeach ?>

		<?php endif ?>

<?php endforeach ?>

Hint:
Do, what @texnixe suggested, in a foreach loop of all pages, you want.

Have a look at custom filters and check out this post

This should leave you without any duplicates; if you then sortBy('title', 'asc'), you should be able to achieve what you want.

1 Like

Thank you @texnixe for pointing me! I’ve managed to have it working :smile: