Kirby CLI and absolute file paths

Hi y’all,

I’ve got a question regarding absolute file paths inside a Kirby cli command.

I’ve got a field with a type of files within my site.yml named csv and a kirby command named import located here site/commands/import.php. Within the command callback I read the files field via site()->csv()->toFile()->url().

Now when I run kirby import from the command line, I see that the file path is printed as /media/site/0da821a872-1682877986/file.csv. However this is not the folder where the file is located in.

Looking at the filesystem I see that the selected file inside the panel is actually in /media/site/32eaf44bc4-1682877986/file.csv. How can that be that it’s printing a complete different file path? Am I doing something obvious wrong? Below is a shorter version of my command import

<?php

use Bnomei\Janitor;
use Kirby\CLI\CLI;

return [
    'description' => 'Import csv file',
    'args' => [] + Janitor::ARGS,
    'command' => static function (CLI $cli): void {

      $csv = site()->csv()->toFile()->url();

      try {
        if (($file = fopen($csv, 'r')) !== FALSE) {
          while (!feof($file) && ($row = fgetcsv($file, 1024)) !== FALSE) {
              if(!$header)
                $header = $row;
              else
                $results[] = array_combine($header, $row);
          }
          fclose($file);
        }
      } catch (Exception $e) {
        $alert = ['Error: ' . $e->getMessage()];
      }

      if(empty($alert)) {
        $cli->error($alert);
      } else {
        $cli->success('Success');
      }
    }
];

Thanks in advance!
Flo

why not use ->toFile()->root() instead of ->url()

1 Like

That’s a good point. This does return the correct file path.
But shouldn’t url() still return at least the correct relative path?

No, well yes. It depends on what you call “correct”.

By default, with the advised server settings, the content folder is not accessible to site visitors. Using the url function therefore generates a path to the media folder together with a hash that identifies the current version of a file (the first part of 0da821a872-1682877986 is a CRC32 hash of the file path, the second part is the “last modified” date of the file).
The file in the media folder isn’t however created immediately just by calling url. It’s copied there only when a visitor actually requests it.

So if the you don’t have a file there, it’s because it has not yet been generated, because nobody has requested it via the web server.
If you have a file.csv in another folder, it means that the path “has changed” (or it’s a new file, but in your case the path changed).

The “path” is defined as “path of the file relative to the web root”. The file you actually have in the media folder was generated from a web request, it’s very much possible that the “path” differs between actual web requests and CLI scripts:
Example: let’s say you were testing the site locally on “http://localhost/mywebsite”, the “path” would be “mywebsite/content/file.csv”
CLI scripts however don’t have a “webroot” (because no webserver is involved there). The path is therefore relative to the kirby installation (AFAIK): so only “content/file.csv”.

root() on the other hand gives you the absolute actual file location in the content folder.

TLDR; use url() only when you actually intend to serve something via the webserver. Otherwise use root().

1 Like

@rasteiner Thanks a lot for your detailed explanation. That makes totally sense now why I wasn’t able to get to the file in first place as I did not “request” the file via the webserver but from the cli.

Much appreciated!