Jump to content

images->first API


fruid
 Share

Recommended Posts

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

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.

  • Like 2
Link to comment
Share on other sites

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

  • Like 2
Link to comment
Share on other sites

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

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...