Cannot get video URL

Hi there!

I think I’m slowly getting used to Kirby (and I really like it so far!) but I always run into problems since I know almost nothing about PHP and I don’t really get some about Kirby’s logic.

So I want to show a video that I uploaded via the panel before. But I just can’t access the URL of the video! Of course I’ve searched the forum, but nothing I tried worked.

This is a part of my blueprint:

sections:
      video:
        label: Video
        type: files
        layout: cards
        template: video
        info: "{{ file.dimensions }}"
        image:
          ratio: 1/1
        min: 1
        max: 1
        size: small

And I want to show the video this way:

<?php foreach($page->video() as $video): ?>
    <?php if($video = $page->video()): ?>
      <video src="<?= $video->url() ?>" alt="<?= $page->description()->h() ?>"></video>
    <?php endif ?>
  <?php endforeach ?>

I’m getting this right now:
<video src="" alt="Das ist ein Testvideo!"></video>

That’s better than the countless PHP errors from before, but I’m getting really frustrated slowly. I really hope someone can explain to me what I’m doing wrong (and how to correct it)?

You need to convert it to a file object with toFile(), and check it exists first before trying to use it. Also, you only have one video, so the loop doesnt make sense. You can remove min: 1 from the blueprint.

Assuming you have two fields called video and poster to hold the video and the poster image, something like this will do it. Using ->isNotEmpty() isnt the best way to check for the file, since it just checks the field has a value, not wether the file selected in the field actually exists or not… but the below is generally what you want.

<?php

// Video
$poster = $page->poster()->isNotEmpty() ? $page->poster()->toFile() : ' ';
$video  = $page->videofield()->isNotEmpty() ? $page->videofield()->toFile() : ' ';

?>

<video playsinline autoplay poster="<?= $poster->url() ?>">
<source src="<?= $video->url() ?>" type="video/mp4">
<a href="<?= $video->url() ?>"><img src="<?= $poster->url() ?>" alt="<?= $poster->alt() ?>"></a>
</video>

A safer way would be to put the video tag in a snippet and render it if the files field can be converted to a file object…

<?php 
if ($page->videofield()->tofile()) {
  echo snippet('yourvideosnippet');
}
?>

Since video is a section here, not a field, you cannot access it as $page->video()->toFile(). You will have to access it via the blueprint assigned to it:

<?php if ($video = $page->videos()->findBy('template')->video()) : ?>
<video playsinline autoplay poster="">
<source src="<?= $video->url() ?>" type="<?= $video->mime() ?>">
</video>
<?php endif ?>

oops… tired eyes :frowning: :zzz:

I would suggest using a files field, rather than a section, since you only want one video. The files field still allows you to upload a file.

Thanks to both of you!

I tried to use a files field before (and just tried it again), but it wouldn’t let me upload anything, I can only choose already existing files… That’s why I chose a section.

I’m also a bit confused about the way to access it – in my other blueprints I used files sections for images and it worked perfectly fine?

For example

sections:
  images:
    label: Bilder
    type: files
    layout: cards
    template: image

and

<img src="<?= $image->url() ?>" alt="<?= $image->alt()->or($page->title()) ?>">

work perfectly fine together. I would have expected that (more or less of course) replacing “image” with “video” should work the same?

The files section will accept any kind of file that Kirby allows to be uploaded. It dosnt care what it is. It could be a PDF, Word Doc, Spreadsheet, Image, Videos… pretty much anything (apart from a few that are unsafe). You can limit by mime type if you only want specific kinds of files to be uploaded. I dont know where your setting $image but most of the file methods fall back to the first file on the page if it cant find the one you asked for. Thats possibly why it worked out for you.

To upload files via a files field, you can set the uploads option:

fields:
  video:
    type: files
    uploads: video # sets the template

then you can access the file stored via this field

<?php if ($video = $page->video()->toFile() : ?>
<!-- your code -->
<?php endif ?>

That is only by coincidence, because $page->images() is a native Kirby method that fetches all images from the page, not from your section. As I said, it is not possible to access a section via its section name. The way to separate files from different sections is via their assigned file template.

Example 1: To get all files uploaded via this section with the image template:

sections:
  images:
    label: Bilder
    type: files
    layout: cards
    template: image
$images = $page->images()->template('image'); // fetch all images from page and filter by template

Example 2:

sections:
  videos:
    label: Videos
    type: files
    layout: cards
    template: video
$videos = $page->videos()->template('video'); // fetch all videos from page and filter by template

Fields store something in the content file, sections don’t.

I tried both methods right now (section and field) and they either printed out PHP errors or (unknown) as source… It might be too late, I’ll give it another try tomorrow.

Thanks for your help so far, @jimbobrjames and @texnixe!

What PHP errors?

I think it’s best if you first decide if you rather want to go with a field or a section. Then create the blueprint accordingly, select the file(s) you need and create the template. Then if it doesn’t work as expected, post both the complete blueprint and corresponding template code here.