froot Posted August 26, 2022 Share Posted August 26, 2022 always struggling with this. How to get the only or first image what ever the images field type (array or single or automatic)? // check if there is one if(count($item->images)){ echo $item->images->first->width(200)->url; } Doesn't work in all scenarios though… what if the field is NOT an array and only has one image? what if the field is NOT an array and empty? what if the field IS an array but only has one image? what if the field IS an array but empty? what if the field IS an array and there are multiple images? (probably the only scenario where the above works). Can someone who's been there before provide a code that covers all and never throws an error, just stays empty if there is no image? Link to comment Share on other sites More sharing options...
pwired Posted August 26, 2022 Share Posted August 26, 2022 Maybe this can be helpful ========================================================================================= $page->images->first(); // first image $page->images->last(); // last image $page->images->eq(0); // first image $page->images->eq(1); // second image ========================================================================================= Find the total number of pictures // Get the page that holds the the pictures $p = $pages->get('/path_to_page/'); $numberofimages = $p->images->count(); echo $numberofimages; ========================================================================================= images is an array ... see all the array elements inside the array images 1) Get a Page who has images $p = $pages->get('/path_to_page/'); 2) this gets all the elements $array = $p->images->getKeys(); 3) and this outputs to see them echo implode($array); ========================================================================================= Because an array starts with item number 0 and not 1 ... the last item number in the array is one less than total counted // echo $n; show the total counted number // echo $n--; show the total counted number minus 1 ... this is the last item in the array Note that when you upload an image in the backend by default it will be the LAST one added If you want to output the images in a gallery on the front and want the latest uploaded image to be the first in the gallery, you have to reverse the backend image order: Example: $var_page = $pages->get('/path_to_your_page/'); foreach($var_page->images->reverse() as $image) { echo "<a href='$image->link'><img src='$image->url' alt='description' width='' height=''></a>"; } ========================================================================================= F. 2 Link to comment Share on other sites More sharing options...
bernhard Posted August 26, 2022 Share Posted August 26, 2022 8 hours ago, fruid said: always struggling with this. How to get the only or first image what ever the images field type (array or single or automatic)? Yeah, that's one of very rare examples where PW might add a little too much magic ? The different return values of an image field can definitely lead to confusion or even worse to problems. Until April this year I thought I would be save just using $page->getUnformatted('images') as this always returns the array version. https://processwire.com/talk/topic/26952-get-image-in-the-context-of-a-hook/?do=findComment&comment=222914 But thankfully @Robin S has pointed out that this array might include temporary items and therefore might lead to unexpected results again... See https://processwire.com/talk/topic/26952-get-image-in-the-context-of-a-hook/?do=findComment&comment=222917 There are several not so obvious solutions to the problem: https://processwire.com/talk/topic/26952-get-image-in-the-context-of-a-hook/?do=findComment&comment=222942 --- For my taste this shows that the different output formatting return types introduce more complexity and risk than necessary, but that decision was made a long time ago so we'll have to deal with it. Instead of using ->getUnformatted() I have switched to using ->getFormatted() instead and making sure to set the correct value via RockMigrations. <?php class Example extends Page { public function myImage() { // return image as single pageimage return $this->getFormatted('myimage'); } public function migrate() { [...] $rm->createField('myimage', 'FieldtypeImage', [ 'label' => 'My demo image field', // make sure that the image field returns a single image 'outputFormat' => FieldtypeFile::outputFormatSingle, [...] ]); } } I just realized though, that this can be a problem, because I'm defining an important piece of the method "myImage()" in another method! So on a more complex pageclass I might change the outputFormat of the field to outputFormatArray and I'll introduce a bug in myImage() ! That's not good... I think we should have something like this: $page->getImage('myimagefield'); // returns PageImage (or null) $page->getImages('myimagefield'); // returns PageImages Array That would make a bulletproof code look like this (which would then be a simple answer to your simple question): $image = $page->getImage('myimagefield'); if($image) echo "<img src='{$image->maxSize(400,300)->url}' alt='...'>"; // or $images = $page->getImages('myimagefield'); if($images->count()) echo "<img src='{$images->first()->maxSize(400,300)->url}' alt='...'>"; That would look a lot more like PW imho ? I've created a request for that, so if you like the idea give it a thumbs up: https://github.com/processwire/processwire-requests/issues/453 2 Link to comment Share on other sites More sharing options...
bernhard Posted September 3, 2022 Share Posted September 3, 2022 Ryan was quick with this one ? It's now easy and bullet proof: <?php $img = $page->get('images.first'); if($img) echo "<img src={$img->size(200,200)->url} alt=...>"; https://processwire.com/talk/topic/27528-weekly-update-– 2-september-2022/#comment-226391 2 Link to comment Share on other sites More sharing options...
froot Posted September 5, 2022 Author Share Posted September 5, 2022 is that on the dev branch 3.0.204? or master 3.0.200? Link to comment Share on other sites More sharing options...
bernhard Posted September 5, 2022 Share Posted September 5, 2022 Latest DEV 1 Link to comment Share on other sites More sharing options...
froot Posted September 5, 2022 Author Share Posted September 5, 2022 will wait till it's master then I guess, but good to know Link to comment Share on other sites More sharing options...
froot Posted September 5, 2022 Author Share Posted September 5, 2022 Thanks for looking into this Bernhard. I'd love to make it more backwards compatible though, so I'm still trying to solve it old-school. Here I'm getting the first field of the template that is an image field, not really relevant but what ever. foreach($item->fields as $field) : if($field->type != 'FieldtypeImage'){continue;} else {$imagefield = $field; break;} endforeach; $imageHttpUrl = $item->$imagefield->first->httpUrl; This seems to always work when the field is set to array or automatic and whether the field is populated with just one or more images. That's good enough for me. However, now I'm wondering, if the field is not populated at all, how I can make it work for the fall-back value that you can set for an image field, you know? The one you specify in the "Details" or "Advanced" tab of the field settings. 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