File()->uri() produces an error

Hi guys,

I’m trying to get a relative path to a file:

<?php foreach($pages->find('listings')->children() as $entry): ?>
  <img src="<?php echo $entry->files()->findBy('name', 'titleimg')->uri(); ?>">
<?php endif; ?>

However, I get the error:
Fatal error: Call to a member function uri() on a non-object in...

I have already seen posts, where the error is something like
Uncaught Error: Call to a member function url() on null in ...

However, since I know that the file exists and I can get the absolute Path with just $entry->files()->findBy('name', 'titleimg'), I don’t understand, why it won’t give me the relative path.

What am I missing?

Can you try this please :

<?php echo $entry->files()->findBy('name', 'titleimg')->toFile()->uri(); ?>

Unfortunately I get

Fatal error: Call to a member function toFile() on a non-object in ...

As $entry->files()->findBy('name', 'titleimg') only returns a String, I get it, that I can’t run further functions from it, but why…

I often get the same error and bang my head at it until I find a solution.

Here’s a solution I think will work:
image($entry->files()->findBy('name', 'titleimg'))->uri()

By the way, you could also use an image field called titleimg (in this example) in your blueprint to let the user choose the titleimg themselves. You would then simplify your code like so:

image($entry->titleimg())->uri()

Using toFile() here is unnecessary.

$entry->files()->findBy('name', 'titleimg')
```
should usually return either a file object or probably a boolean if the file does not exist.

Yep I realized my mistake afterwards :sob:

Fatal error: Call to undefined function image() in
for
image($entry->files()->findBy('name', 'titleimg'))->uri()

Using toFile() here is unnecessary.
$entry->files()->findBy(‘name’, ‘titleimg’)
should usually return either a file object or probably a boolean if the file does not exist.

That’s what I thought… However, it just returns an absolute Path to my file as a String…

Do all children of listings contain an image called “titleimg.*”? Anyway, you should use an if-statement to make sure that the method is only called if the file exists, otherwise you might run into problems at some point if the file gets deleted.

This does not make sense, there is no field called “titleimg”.

Not all of them, but most of them do. If I just echo the absolute path with findBy it omits the ones, where no image is uploaded. An if-check would be handy, though.

I still don’t get, why I can’t get a Kirbyish object out of the file and instead am only presented with a string…

Well, you are iterating through all the pages here, so if some do not have that file, you will get that error message. You do need an if statement here.

Test what you get with a var_dump():

<?php var_dump($entry->files()->findBy('name', 'titleimg')) ?>

You didn’t read the message above the code :frowning: I was advising him that he could also set up a field called titleimg

Oh yes, sorry :blush:. But anyway, the code should work as is, if the image exists. No need to set up a field.

You’re damn right on that point! So to avoid the error check that the file exists before echoing it!

While the echo gives me the absolute Path the var_dump gives me… a blank page…

<?php var_dump($entry->files()->findBy('name', 'titleimg')); ?>

and the apache error_log reads

[Tue Jul 19 11:30:04.402177 2016] [:error] [pid 783] [client ::1:52819] PHP Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 130809856 bytes) in ...

I tested the if-clause on another subpage (everything is the same, only the names are different)

<?php if( $absolvent->files()->findBy('name', 'frame1')->exists() ): ?>
   <?php echo $absolvent->files()->findBy('name', 'frame1') ?>
<?php endif; ?>

and I got

Fatal error: Call to a member function exists() on a non-object in ...

It looks like the problem at hand is, that the findBy function doesn’t return an object, that has all the functions a file-object would have (uri(), exists() etc.) Maybe I’m missing something completely different…

Try this:

<?php foreach($pages->find('listings')->children() as $entry): ?>
  <?php if($image = $entry->image('titleimg'): ?>
    <img src="<?php echo $image->uri(); ?>">
  <?php endif ?>
<?php endforeach; ?>
```

Oh, BTW, there is another error in your code: You use ` endif`  to end a `foreach` loop, should be `endforeach`.

If i use

<?php if($image = $entry->image('titleimg.jpg')): ?> (mind the .jpg)
   <img src="<?php echo $image; ?>">
<?php endif ?>

I get the absolute path.

With $entry->image('titleimg')): I get nothing. Also <img src="<?php echo $image->uri(); ?>"> gives me nothing. (By ‘nothing’ I mean that only whitespace is rendered, which I find very strange, since at least the HTML-img tags should me rendered…)

Oh, sorry, yes, the image() method needs the complete filename, of course.

<?php if($image = $entry->image('titleimg.jpg')): ?> (mind the .jpg)
   <img src="<?php echo $image->url(); ?>">
<?php endif ?>

or uri() instead of url() although I don’t know why you prefer the uri over the url.