Filter to exclude files that contain specific string in their name

I can fetch an image that contains e.g. the string “cover” in its filename like so:

$page->images()->filterBy('filename','*=','cover')->first()

Is there a way to turn this method around, so I get a collection of all the images in a folder, except the one that contains the string “cover” in its name? I know you can define your own filter methods, but how exactly would I go about that? I’d be grateful for any hints.

A lil messy, but maybe this could work (if it’s always only one ‘cover’)?

$page->images()->filterBy('filename', '!=', $page->images()->filterBy('filename','*=','cover')->first()->filename());

Ha! I knew I was thinking overly complicated :smile: That worked perfectly fine, thanks for the tip!

I’d rather create my own filter here:

$page->images()->filter(function($image) {
  return !str::contains($image->filename(), 'cover');
});
6 Likes

Solid! I’ll implement that. Thanks a lot you guys!

Hello Guys,

I was searching for this Solution to exclude images on Page.

Because every uploaded image is shown in the Slider.

My Snippet for the files is

<?php foreach($page->images() as $image): ?>
 <img class="rsImg" src="<?php echo $image->url() ?>" alt="">
<?php endforeach ?>

Where do I have to put that snippet above to get this Filter on one page to work :frowning: I’ve tried several possibilities.

Hope you can help me.

Have a nice day :slight_smile:

What kind of images are you trying to filter?

In your example it’d be

<?php
$images = $page->images()->filter(function($image) {
  return !str::contains($image->filename(), 'cover'); // whatever you want to remove
});
?>
<?php foreach($images as $image): ?>
 <img class="rsImg" src="<?php echo $image->url() ?>" alt="">
<?php endforeach ?>
1 Like

Wow, thank you for the fast response. It worked like a charm :slight_smile:

Thank you very much.

I made a custom filter out of @distantnative’s code, that can be used with \filterBy, like this

$page->images()->filterBy('filename', '!*=', '-big')

where !*= means “doesn’t contain”. To install this filter create a file filterStringContainsNot.php (or whatever you like) at plugins/ and save this code:

<?php

collection::$filters['!*='] = function($collection, $field, $value, $split = false) {

  foreach($collection->data as $key => $item) {
    if(!str::contains((string)collection::extractValue($item, $field), $value)) continue;
    unset($collection->$key);
  }

  return $collection;

};
4 Likes

Thanks for your filter!
It is just what I was looking for :slightly_smiling:

Hey guys. I’m looking to filter Kirby users based on a custom field named “position”. The following will allow me to filter based on a single value.

$members = $site->users()->filterBy('role', 'member')->filter(function($member){
    return str::contains($member->position(), 'Officer');
});

This is great. It allows me to build a collection of members that have “Officer” in the position field, but can this be tweaked to allow me to filter multiple position values. For example what if I wanted to get a collection of members that have either “Officer” or “Executive Board” as a value in the position field?

Any insight would be awesome.

You can either use and or condition or check if the value is in an array:

$positions = ['officer', 'whatever'];
    return in_array($member->position(), $positions);

I am trying to achieve the same result, i.e show all images except for images with the word ‘cover’ in the name. For some reason this code is still showing me all the images, including those with ‘cover’ in the file name.

<div class="photo-grid">
  <?php foreach($page->images()->filterBy('filename', '!=', 'cover') as $image): ?>
      <img src="<?php echo $image->url() ?>" alt="">
  <?php endforeach ?>
</div>

Any ideas?

@elaltito Do you want to exclude all files that contain the string cover or only the one with the filename cover. For the first option, use the code provided by @bastianallgeier

$images = $page->images()->filter(function($image) {
  return !str::contains($image->filename(), 'cover');
});

foreach ($images as $image) {
  echo $image->url();
}

Are you on Kirby 2 or 3? On Kirby 3, there is a shorter way to achieve this.

Thanks for your help @texnixe ! :slight_smile: I have just finished upgrading to Kirby 3, what would be the shorter way to achieve this then? And yes I would like to exclude all files that include the string ‘cover’, for example “photo_cover.jpg”

@thewebprojects: https://getkirby.com/docs/reference/objects/files/filter-by#available-filter-methods

Great, worked perfectly! Thanks again for your amazingly quick response! :slight_smile: