Updating files field programmatically

Hi, I’ve been trying to figure out how to update a files field programmatically.

I couldn’t find “the correct way” anywhere, so here’s what I’m trying to do after the files is moved into the page content folder:

    'modelfile' => $page->files()->sortBy('modified', 'desc')->limit(1),

This code works, however it ONLY works when there’s already a file in the content folder. So first time uploading a file it does not save a file to the field, but the next time it does.

How should I go about solving this?

You can use a file.create:after hook.

What does your above code store in the content file? Plus, the files field–like the page field–expects the content to be yaml encoded.

Would the file.create:after hook run even when I’m uploading the file from the frontend?

As for how it’s stored: The first time it stores nothin, just Modelfile:, and the second time it stored YAML encoded, like:


- NY8sVeship.scn

Note that if I dump $page->files()->sortBy('modified', 'desc')->limit(1), it always dumps a collection of Files with 1 entry.

I’ll try encoding it to YAML before updating and see if that changes anything. Thank you.

Depends how you upload the file, the hook should be triggered not only in the Panel but also if you upload using Kirby’s methods.

The result looks ok, so probably no yaml encoding needed.

Looks like I made it work.

From controller.php:

F::write($source = $page->mediaRoot() . '/' . $fileName, file_get_contents($_FILES['modelfile']['tmp_name']));
        $result = File::create([
          'filename' => Str::random(6) . $_FILES['modelfile']['name'],
          'source'   => $source,
          'parent'   => $page

From config.php:

'hooks' => [
    'file.create:after' => function ($file) {
        'modelfile' => [$file->contentFileName()],

Thank you for your help.

1 Like