Plugin-specific styles, images, and javascript files

Published on and tagged with cakephp  feature  plugin

One missing piece for using plugins as mini-applications was the ability to have plugin-specific styles, images and javascript files. You had to put them to the respective folders in your application, or you had to use some hacks.

In the meantime this ability has been introduced (I don’t know when it was added). To make use of it, you have to add a “vendors” folder with the subfolders “css”, “img”, and “js” to your plugin:

app
  plugins
    myplugin
      vendors
         css
         img
         js

Files in those folders can then be accessed like http://example.com/myplugin/img/my_image.jpg.

Unfortunately, HtmlHelper and JavascriptHelper are not (yet?) aware of this new feature. For example, the following code used in a view of your plugin:

<?php echo $html->image('my_image.jpg'); ?>

will create this HTML code:

<img src="/img/my_image.jpg" alt="" />

As you see, the path points to the “img” folder of your application, and not to the “img” folder of your plugin. To avoid this, we have to specify the full path to the image:

<?php echo $html->image('/'.$this->plugin.'/img/my_image.jpg'); ?>
// creates: <img src="/myplugin/img/my_image.jpg" alt="" />

The same also applies when including CSS styles and Javascript files.

Happy plugin baking :)

PS1: A new “notEmpty” validation rule has recently been added (“teknoid” was faster with an article, so here just a link to his article).

PS2: A CakePHP presentation (in German) by Timo Derstappen.

8 comments baked

  • David Persson

    Problem is that it’s superslow to output images and friends by php. On each request to a plugin image or css a part of the framework is invoked, objects are being built, …

    I prefer to use the django approach of separating media from the framework and letting apache itself handle all the static files. That what it’s for.

    I’m preparing a plugin in the attm cakeforge repo to be used with cake introducing an enhanced/conventionalized media directory schema plus a helper to handle the urls.

  • cakebaker

    @David: Thanks for your comment!

    Yes, there is some overhead involved when serving files in that way. On the other hand it is convenient to have all plugin-related files in the plugin folder. In the end it depends on your project whether the overhead is acceptable or you have to look for a different solution.

    Anyway, I have to have a look at your attm project.

  • Matt Huggins

    Ahh, thanks for the heads up. Previously, this could be done by saving the images under the vendors/css folder of the plugin, and referencing the image as img/name.jpg from a CSS file. My images stopped showing up, and I couldn’t figure out how to resolve it.

    I like the fact that I can use the vendors/img folder now, but I hate the fact that I have to directly reference the plugin name.

  • cakebaker

    @Matt: Thanks for your comment! And yes, it would be nice, if the helpers would automatically look in the correct plugin folders for the referenced resources.

    Oh, just saw you started a new site, good luck with it ;-)

  • David Thalmann

    Thank you for this post, was looking for a solution like that for a long time.
    Any idea how to define in-plugin routes? because for example an user-auth plugin just _wont_ work without routes.
    and other hard-coded stuff like i18n/l10n? or should i ‘fix’ this with some kind of helper-modules?

    (I’m on a plugin-based cms with cakephp, but the plugin-part of the documentation isn’t very helpfully for newbies like me ;) )

  • cakebaker

    @David: Hm, what do you mean with “in-plugin routes”? Can you provide an example of what you try to accomplish?

  • David Thalmann

    @cakebaker: The idea of a plugin is to serve a fully working mini-app, which you can drop in your plugin folder and it should work as-is (may have some dependencies to other plugins, but nothing else!). This includes localization files, plugin specific routes, styles (<- thank you for your blogpost ;) ).

    As an example, my blog plugin:

    Router::connect(
        '/blog/:id-:slug/*',
        array(
            'plugin' => 'blog',
            'controller' => 'blog',
            'action' => 'view')
        ),
        array(
            'pass' => array('id'),
            'id' => '[0-9]+'
        );

    This code fragment belongs not to the application, it belongs to the plugin, so it should be in the plugin.
    (where should I place it? And how should cake realize anyway, that I’ve defined a route somewhere outside of routes.php?)

    Same problem with localization.

    I mean, it’s not a big deal to do it for each plugin, but a cake-plugin would be way more a plugin in my understanding of what a plugin should be.

    I’ve just found a interesting post:
    http://groups.google.com/group/cake-php/browse_thread/thread/74484afe7da5c1f0#msg_f8adaf31f5980fd1
    Thats may what i’ve been looking for :)

  • cakebaker

    @David: Yes, in theory plugins are mini-apps, in practice it is not (yet?) the case, at least not completely. There are no plugin-specific configuration files.

    For the time being you have to use a workaround as shown in the link you posted, but you might consider to open an enhancement ticket for it (if there is not one already), maybe the devs will add such functionality to the core in a future version…

  • My Homepage

    … [Trackback]

    […] There you will find 44184 more Infos: cakebaker.42dh.com/2008/08/04/plugin-specific-styles-images-and-javascript-files/ […]

Bake a comment




(for code please use <code>...</code> [no escaping necessary])

© daniel hofstetter. Licensed under a Creative Commons License