Jump to content

No duplicate logos in a grid of 9


Mediaweeze

Recommended Posts

Hi, I have literally been working on this for days, I'm a complete novice so just kind of trying everything to get this to work so forgive me if there are lots of unnecessary bits in my code.

I'm grabbing a client logo from a WordPress custom field group called clients, there are currently 72 in the list but this will change as some get added and others get deleted. I want the logos to display in a grid of 9 tiles <li>'s

But not showing the same logo twice in the grid (ever). So what I have tried is to divide he logos into chunks to show in each <li> but I'm still seeing duplicates, in a var_dump I can see that all the logos displayed withing each <li> are unique so I can only guess when it shuffles it's changing the chunks? I'm not sure but if anyone could improve on what I have done it would help me a ton.

 

<?php
    $clients = $_w->page->get_field('clients');

    // Get the total number of clients
    $num_clients = count($clients);

    // Set the number of logos to display in the grid
    $num_logos = 9;

    // Get a list of unique random indices within the range of the clients array
    $indices = UniqueRandomNumbersWithinRange(0, $num_clients - 1, $num_logos);

    // Sort the indices in row-major order
    sort($indices);

    // Create an array to store the unique images
    $images = array();
			foreach ($clients as $c) {
    $images[] = $c->image->url;
}

    // Loop through the indices and get the corresponding image URLs
    foreach ($indices as $i) {
        $image_id = $clients[$i]->image->id;
        $image = wp_get_attachment_image_src($image_id, 'full');
        $images[] = $image[0];
    }
?>

<?php
// Get an array of all image URLs
$images = array_map(function ($c) {
    return $c->image->url;
}, $clients);

// Remove duplicates from the images array
$images = array_unique($images);
?>

<?php
// Loop through the indices and get the corresponding image URLs
foreach ($indices as $i) {
    $image_id = $clients[$i]->image->id;
    $image = wp_get_attachment_image_src($image_id, 'full');
    $images[] = $image[0];
}

if ($images): 
    // divide the array of logos into 9 smaller arrays
    $chunks = array_chunk($images, ceil(count($images) / 9));
    
    // shuffle the chunks to get a random distribution of logos
    shuffle($chunks);
?>
    <section class="image-grid-container">
        <script id="hd_client_gallery" type="text/json">
            [<?php 
                $total = count($clients);    
                $count = 0;
                foreach ($clients as $c): 
                    echo "{";
                        echo '"url": "' . $c->image->url . '",';
                        echo '"href": "' . $c->link. '"';
                    echo "}";
                    if(++$count !== $total) {
                        echo ", ";
                    }
                endforeach;
            ?>]          
        </script>
        <ul class="object image-grid gallery">
            <?php for ($i = 0; $i < 9; $i++): ?>
                <?php if (isset($chunks[$i])): ?>
                    <li>
                        <?php foreach ($chunks[$i] as $image_url): ?>
                            <?php 
                                // get the client with this image URL
                                $client = null;
                                foreach ($clients as $c) {
                                    if ($c->image->url == $image_url) {
                                        $client = $c;
                                        break;
                                    }
                                }
                            ?>
                            <?php if ($client): ?>
                                <a <?= ($client->link ? 'href="'.$client->link.'"' : '' ); ?>>					
                                    <img class="img-fluid" src="<?= $image_url ?>" />
									
                                    <img style="display:none;" class="img-fluid" src="" />
                                </a>
                            <?php endif; ?>
                        <?php endforeach; ?>
						
                    </li>
                <?php endif; ?>
            <?php endfor; ?>
        </ul>
    </section>
			
<?php endif; ?>



<?php
function UniqueRandomNumbersWithinRange($min, $max, $quantity) {
    $numbers = range($min, $max);
    shuffle($numbers);
    return array_slice($numbers, 0, $quantity);
}
?>

		</div>
</section>
			

 

Link to comment
Share on other sites

Is this all code from a single file? You aren't posting bits from one place and bits from another? Because there's a lot of confusing work going on with the $images variable - and honestly, I didn't look a whole lot further than that.

Programming is like cooking, or mixing paint colors, or sticking your foot in your mouth: if something is going wrong, adding more on top of it isn't going to help. You need to stop, reset, and try again.

So my advice is to take all the code you've written so far, move it to a scratch pad somewhere that you can look at for reference, and then start over from the beginning.
Figure out what it is that you need to do with your code. Plan ahead. Experiment even, if that helps. I figure that you should end up with maybe 3-5 total lines of code in order to build your $images array.

And let me be clear here: you're damn close to it. In fact I'm pretty sure that the correct answer is in that code you currently have. But the problem is there's a whole bunch of not-correct code mixed in as you were trying it out.

Link to comment
Share on other sites

Hi @requinix,

Thanks for your response, I thought that would be the case! I have worked on it again this morning and got it down to this.

<?php
$clients = $_w->page->get_field('clients');
$clients_images = array();
$clients_count = count($clients);

foreach ($clients as $c) {
    $image = wp_get_attachment_image_src($c->image->ID, 'full');
    if ($image) {
        $clients_images[] = array(
            'url' => $image[0],
            'href' => $c->link
        );
    }
}

$chunk_size = ceil($clients_count / 9);
$chunks = array_chunk($clients_images, $chunk_size);

?>

<?php if ($clients_images): ?>
    <section class="image-grid-container">
        <script id="hd_client_gallery" type="text/json">
            <?= json_encode($clients_images); ?>          
        </script>
        <ul class="object image-grid gallery">
            <?php foreach ($chunks as $chunk): ?>
                <li>
                    <a <?= ($chunk[0]['href'] ? 'href="'.$chunk[0]['href'].'"' : '' ); ?>>					
                        <img class="img-fluid" src="<?= $chunk[0]['url']; ?>" />
                        <img style="display:none;" class="img-fluid" src="" />
                                             
                    </a>
                </li>
            <?php endforeach; ?>
        </ul>
    </section>
<?php endif; ?>

But still seeing duplicated image in the grid, what I think should happen is that each <li> should have it's own list of client logos that it loops through that never changes, that way there should never be any duplicates, I'm just not sure how to achieve this?

Link to comment
Share on other sites

If you're getting duplicates with that code, it sounds to me like your $client_images array simply contains duplicates, not that you're selecting the same image twice somehow.  If that's the case, filter out those duplicates before you take your random selection.

 

Your code is a little overly complicated for the task. Your original code had the components of a right solution, just too much extra junk along with it.  To get X unique random elements from an array (assuming the array itself is unique) then all you need to do is

  1. shuffle the array to randomize the order
  2. slice off the first X elements.

 

Side question, why do you have two images takes, with one of them being display none and without a src?

Link to comment
Share on other sites

Hi @kicken

Thanks for your reply, the two image with a bit of css make the images fade out between one and another. 

I have worked on my code further but still stuck, I thought that by using array_chunk was a better solution as I could split all 72 clients into chunks and distribute theme between the list elements. ensuring that each <li> had it's own chunk of client logos to fade through. I'm nearly there but I think I'm just missing the mark or have something in the wrong place?

 

<?php
    $clients = $_w->page->get_field('clients');
    $chunks = array_chunk($clients, 8);
    shuffle($chunks);
?>

<?php if ($clients): ?>
    <section class="image-grid-container">
        <script id="hd_client_gallery" type="text/json">
            [<?php 
                $total = count($clients);    
                $count = 0;
                foreach ($clients as $c): 
                    echo "{";
                        echo '"url": "' . $c->image->url . '",';
                        echo '"href": "' . $c->link. '"';
                    echo "}";
                    if(++$count !== $total) {
                        echo ", ";
                    }
                endforeach;
            ?>]          
        </script>
        <ul class="object image-grid gallery">
            <?php $imageCounter = 0; ?>
            <?php foreach ($chunks as $chunk):
                shuffle($chunk);
            ?>
                <?php foreach ($chunk as $c):
                    if (!$c) continue; // skip empty elements
                    if ($imageCounter > 8) break;
                    $imageCounter++;
                ?>
                <li>
                    <a <?= ($c->link ? 'href="'.$c->link.'"' : '' ); ?>>					
                        <img class="img-fluid" src="<?= $c->image->url; ?>" />
                        <img style="display:none;" class="img-fluid" src="" />
                    </a>
                </li>
                <?php endforeach; ?>
                <?php if ($imageCounter > 8) break; ?>
            <?php endforeach; ?>
        </ul>
    </section>
<?php endif; ?>

 

Link to comment
Share on other sites

On 4/30/2023 at 9:19 AM, Mediaweeze said:

I'm grabbing a client logo from a WordPress custom field group called clients, there are currently 72 in the list but this will change as some get added and others get deleted. I want the logos to display in a grid of 9 tiles <li>'s

But not showing the same logo twice in the grid (ever).

Taking a step back and looking not at how to do this but, rather, why you want to do it in the first place ...

What do the icons represent?  Are they the icons chosen by clients to represent themselves on your site or are they just a list of possible icons that someone could choose from? 

If you're going to have a grid of links to each client then it doesn't matter if they're duplicated - that's why they chose. 

If it's something (an avatar?) to pick from, then use a Reducing Set - create one array with the icons in it and another, initially of the same size with the index of each one.  Then, as you [randomly] pick each icon, remove it's index from the second array so you can't choose that one again. 

Regards, 
   Phill  W.

 

Link to comment
Share on other sites

HI @phil

I want to show many and unknown number of client logos in a grid of nine squares, they fade in and out so that all logos show eventually but not all at once, and never duplicated in the grid, currently there are 72 clients so 72 client logos. these may increase or decrease depending on if new clients or added or taken away. You can see a video of how it works and why it's not working correctly here Video of the problem. I hope that helps explain what I'm attempting to do.

Link to comment
Share on other sites

41 minutes ago, Mediaweeze said:

I thought that by using array_chunk was a better solution as I could split all 72 clients into chunks and distribute theme between the list elements

That seems to me like maybe a misunderstanding of what is happening. You're not outputting a group of images in each LI element that get cycled through, you're just generating 9 LI elements with one image each.  The code to do that can be much simpler than what you have.  Randomize your array with shuffle, then dump out the first 9 elements.

<?php
$clients = array_filter($clients); //Remove empty elements
shuffle($clients); //Randomize the array.
?>
<ul class="object image-grid gallery">
    <?php foreach (array_slice($clients, 0, 9) as $c): ?>
        <li>
            <a <?= ($c->link ? 'href="'.$c->link.'"' : '' ); ?>>
                <img class="img-fluid" src="<?= $c->image->url; ?>" />
                <img style="display:none;" class="img-fluid" src="" />
            </a>
        </li>
    <?php endforeach; ?>
</ul>

Your code to output the JSON structure of all your clients could also be improved.  You should be using json_encode rather than trying to build the json manually.  This way, the json data will be properly encoded and escaped if necessary.

<script id="hd_client_gallery" type="text/json">
<?php
    echo json_encode(array_map(function($c){
        return [
            'url' => $c->image->url,
            'href' => $c->link
        ];
    }, $clients));
?>
</script>

array_map takes in an array and for every element in that array calls a function. The return value of that function is then put into a new array.  So the above maps whatever your client objects are into a simple array with just url and href elements.  That simple array then gets transformed into json and output.

16 minutes ago, Mediaweeze said:

You can see a video of how it works and why it's not working correctly here Video of the problem.

From the video, it seems like your duplication problem is a result of your JavaScript code that does the fade effect.  When it choose a new image to fade in, it does so without regard to which images are already displayed.  If you want to fix this, you'll have to do so by fixing the JavaScript code, there's nothing to do about that from within your PHP code.

 

Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.