Get path to assets/images

i simply want to add an image.
is there a way to use a helper like the css() or js() for images?
When i use assets/images/a.jpg it works for home and first level of subdomain but not on second level like this:


nevermind… i totally forgot the url() function.

$roots may also help depending on what you’re trying to do.

I have the following snippet in Sublime Text so whenever I need to reference or use something like an image from the assets folder I just type “assets” and press TAB to make it work.

<?php echo \$site->url() ?>/assets/
	<!-- Optional: Set a tabTrigger to define how to trigger the snippet -->
	<!-- Optional: Set a scope to limit where the snippet will trigger -->
	<description>Inserts the root address from a KIRBY CMS installation</description>

Using $kirby->urls()->assets() will work better in conjunction with custom paths and in multi site configurations.

1 Like

How did you solve it?

Either that:

<img src="<?php echo url('assets/images/a.jpg') ?>" alt="">

or that:

<img src="<?php echo kirby()->urls()->assets() . '/images/a.jpg' ?>" alt="">

The latter is more robust but only works for files that are actually in /assets.


On a single-language project I wanted a common method to add the URL root of the assets folder, and also wanted to do some simplistic cache busting, so I wrote a method for the $site object:

 * Complete an asset's URL with base directory and timestamp
 * @param Site $site
 * @param string $url
 * @return string
Site::$methods['asset'] = function(Site $site, $url='') {
   if (!is_string($url) or $url == '') {
      return '';

   // Retrieve timestamp, convert to base36 and only keep the last 5 chars,
   // which cover the last 700 days (more than enough for HTTP caches).
   $file = kirby()->roots()->assets() . DS . $url;
   $time = file_exists($file) ? (string) filemtime($file) : '';
   if ($time) $time = substr(base_convert((string) $time, 10, 36), -5);

   // Another, and theoretically better option is to put the timestamp
   // in the filename, e.g. myfile-6rwtq.css, but that would require changing
   // the .htaccess to rewrite those requests (stripping the timestamp).
   $base = kirby()->urls()->assets() . '/' . $url;
   return $time ? "$base?v=$time" : $base;

So in my templates I can write:

<link rel="stylesheet" href="<?= $site->asset('css/main.css') ?>">

and get:

<link rel="stylesheet" href="http://domain.tld/assets/css/main.css?v=6jjzs">
1 Like

Is there a reason why you don’t just use ($site, $url='') in this case?

A type declaration requires a certain type of parameter, in this case, an object of type Site. If the wrong type is given, an error occurs.

Now I understand about half of this.

This is working fine:

page::$methods['linktag'] = function($page) {
  return '<a href="' . $page->url() . '">' . $page->title()->html() . '</a>';

But I can also do this:

page::$methods['linktag'] = function(Page $page) {
  return '<a href="' . $page->url() . '">' . $page->title()->html() . '</a>';

The first one is shorter, do I need the second one in some cases?

The reason I ask is because I added a new page here:

Site::$methods['test'] = function($site, $arg1 = '', $arg2 = '') {
  return $site->homePage() . ' ' . $arg1 . ' ' . $arg2;

Because it’s shorter without Site, I just used $site without it. Pitfalls?

I’ve read the PHP docs as well as your other comment a few times.

My conclusion is this: In this case, because $site should always be a site object in templates and snippets, Site is redundant, just like when adding page::methods and pages::methods.

I agree that in these specific cases it’s a bit redundant, because these methods will be called by Kirby code and not by user code.

On the other hand, it doesn’t cost much and might even help identify bugs in Kirby’s core (if any).

1 Like