Mediaweeze Posted April 30, 2023 Share Posted April 30, 2023 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> Quote Link to comment https://forums.phpfreaks.com/topic/316220-no-duplicate-logos-in-a-grid-of-9/ Share on other sites More sharing options...
requinix Posted April 30, 2023 Share Posted April 30, 2023 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. Quote Link to comment https://forums.phpfreaks.com/topic/316220-no-duplicate-logos-in-a-grid-of-9/#findComment-1607821 Share on other sites More sharing options...
Mediaweeze Posted May 1, 2023 Author Share Posted May 1, 2023 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? Quote Link to comment https://forums.phpfreaks.com/topic/316220-no-duplicate-logos-in-a-grid-of-9/#findComment-1607847 Share on other sites More sharing options...
kicken Posted May 1, 2023 Share Posted May 1, 2023 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 shuffle the array to randomize the order 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? Quote Link to comment https://forums.phpfreaks.com/topic/316220-no-duplicate-logos-in-a-grid-of-9/#findComment-1607849 Share on other sites More sharing options...
Mediaweeze Posted May 3, 2023 Author Share Posted May 3, 2023 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; ?> Quote Link to comment https://forums.phpfreaks.com/topic/316220-no-duplicate-logos-in-a-grid-of-9/#findComment-1607974 Share on other sites More sharing options...
Phi11W Posted May 3, 2023 Share Posted May 3, 2023 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. Quote Link to comment https://forums.phpfreaks.com/topic/316220-no-duplicate-logos-in-a-grid-of-9/#findComment-1607976 Share on other sites More sharing options...
Mediaweeze Posted May 3, 2023 Author Share Posted May 3, 2023 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. Quote Link to comment https://forums.phpfreaks.com/topic/316220-no-duplicate-logos-in-a-grid-of-9/#findComment-1607977 Share on other sites More sharing options...
kicken Posted May 3, 2023 Share Posted May 3, 2023 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. Quote Link to comment https://forums.phpfreaks.com/topic/316220-no-duplicate-logos-in-a-grid-of-9/#findComment-1607978 Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.