Some ideas to organize your CSS files and autoload them in CakePHP

By Tulio Faria aka "tulio"
In this article, I will show some ideas in how to organize your CSS files and how to autoload them in your CakePHP project. Some of them are elegant , and others are not so elegant as they could be ...

First Idea: CSS files named whitout any link with controller names


In this method, the files names are completely different from controller names. This is not recommended, because you could lose much time searching a CSS file which is related to a specific controller.

To use this method, we will do the controller choose what CSS file will be used, so will be used a variable $CSS to store the CSS file name. For example, an Articles controller:

Controller Class:

Download code <?php 
class ArticlesController extends AppController
{
      var 
$name 'Articles';
function 
index(){

      
$this->set("CSS""articleshome");
      }
function 
read($id){
      
$this->set("CSS""readarticle");
 }
}
?>


Note that we set a variable $CSS for each method (action), and each CSS file name doesn't have any link with the method or controller name.

Now, in our default layout, inside the head tag:

View Template:

Download code
<head>
.
.
<?
if(isset($CSS)){
   echo 
$html->css($CSS);
}
?>
.
.
</head>


In the layout, we did a validation to know if $CSS has been set, so we only include it if this occurs.

This way is not very elegant, right?

Second Idea: CSS with the same controller name



In this method, the CSS files will have the same name of their controllers, that is, an Articles controller will have an article.css. So we will have a project a little more organized, and we will find the CSS files easier then before, because both have the same name.

Now, we don't need to do anything in controller, only in the layout.

View Template:

Download code
.
.
<head>
<?
echo $html->css($this->params["controller"]);
?>
</head>
.
.


We used $this->param to know what is the name of the controller. This array contains many useful information, like controller name, method name, and others. If you want to know more, and don't want to read api/manual, just: print_r($this->params), and see what happens.

print_r($this->params);

Third Idea: CSS file with the same name of controller, but only if CSS file exists



This method is an update from Second Idea, we will just validate if CSS file is present in server, if it is, we link it to HTML. The code for the validation is the following:

View Template:

Download code
<head>
.
.
<?
if (is_file(APP.WEBROOT_DIR.DS."css".DS.$this->params["controller"].".css")){
echo 
$html->css($this->params["controller"]);
}
?>
.
.
</head>

Note that to show the complete file path, we used many constants. Here is their meanings:
* APP : stores the complete path to current application. For example: c:testCakeapp
* WEBROOT_DIR : the webroot directory name.
* DS : or Directory Separator, stores which slash we will use, depending on the OS. Backslash for windows and slash for *nix.

This method is more organized. Besides, it performs needed validations. This method is recommend when you have all style for each controller in a single CSS file.

Fourth Idea: one CSS file for each method of controller



This idea, I think it is more accurate and organized. Why? Because we will separate each CSS for one method.

Again, we will modify only the layout:

View Template:

Download code
<head>
.
.
<?
if (is_file(APP.WEBROOT_DIR.DS."css".DS.$this->params["controller"]."_".$this-params["action"].".css")){
      echo 
$html->css($this->params["controller"]."_".$this->params["action"]);
 }
?>
.
.
</head>


In this example, we are using the following filename ruler for CSS files: controllersname_method.css and we already are validating if the CSS file exists.

Fifth Idea: one CSS file for each method of controller, a little bit more organized



This idea is almost equal to the previous, but we won't put all CSS files in the same directory, we will separate them in foldes with the same names of controllers.
For each controller, we will have a folder like webroot/css/controllername and in this folder, we will have all CSS for each method.

View Template:

Download code
<head>
.
.
<?
if (is_file(APP.WEBROOT_DIR.DS."css".DS.$this->params["controller"].DS.$this->params["action"].".css")){
       echo 
$html->css($this->params["controller"]."/".$this->params["action"]);
}
?>
.
.
</head>


Note that we only change "_" for slash.
So if we have a controller called Articles and a method (action) called read, it will be linked in html, if the file /css/articles/read.css exists.

This last idea, I think it is the best.

Tulio Faria
http://www.tuliofaria.net
http://www.iwtech.com.br

Comments 215

CakePHP team comments Author comments

Comment

1 Global CSS

You might also want to think about global CSS if you use Cake for multiple apps. 1.2 makes it soooo easy: http://joelmoss.info/switchboard/blog/2142:Whats_new_in_CakePHP_Asset_Sharing
posted Tue, Jan 16th 2007, 04:03 by Joel Moss

Comment

2 Not Just for CSS

A very useful technique, and one not just limited to CSS. I can see this getting used to include controller/action specific javascript too.
posted Tue, Jan 16th 2007, 10:23 by RichardAtHome

Comment

3 I like it

Very handy, i've implmented this myself and added a few little bits, as Richard said, its handy for javascript too, here is my code :

View Template:


<?
    
//include controller specific js automatically
    
if (is_file(APP.WEBROOT_DIR.DS.'js'.DS.'inc'.DS.$this->params['controller'].DS.$this->params['controller'].'.js')){
           echo 
"\t".'<script type="text/javascript" src="'.$this->webroot.'js/inc/'.$this->params['controller'].DS.$this->params['controller'].'.js"></script>';
    }
    
//admin js
    
if (is_file(APP.WEBROOT_DIR.DS.'js'.DS.'inc'.DS.$this->params['controller'].DS.$this->params['controller'].'_admin.js') AND
                
strpos($this->params['action'], 'admin_') == ){
           echo 
"\t".'<script type="text/javascript" src="'.$this->webroot.'js/inc/'.$this->params['controller'].DS.$this->params['controller'].'_admin.js"></script>';
    }
    
    
    
//include action specific js automatically
    
if (is_file(APP.WEBROOT_DIR.DS.'js'.DS.'inc'.DS.$this->params['controller'].DS.$this->params['action'].'.js')){
           echo 
"\t".'<script type="text/javascript" src="'.$this->webroot.'js'.DS.'inc'.DS.$this->params['controller'].DS.$this->params['action'].'.js"></script>';
    }    
    
?>     
    
    <?php echo $html->css('cake.generic');?>
    
    <?
    
//include controller specific css automatically
    
if(is_file(APP.WEBROOT_DIR.DS.'css'.DS.'inc'.DS.$this->params['controller'].DS.$this->params['controller'].'.css')){
        echo 
"\t".$html->css('inc/'.$this->params['controller'].DS.$this->params['controller']);
    }
    
//admin css
    
if (is_file(APP.WEBROOT_DIR.DS.'css'.DS.'inc'.DS.$this->params['controller'].DS.$this->params['controller'].'_admin.css') AND 
            
strpos($this->params['action'], 'admin_') == ){
           echo 
"\t".$html->css('inc/'.$this->params['controller'].DS.$this->params['controller'].'_admin');
    }
    
    
//include action specific css automatically
    
if (is_file(APP.WEBROOT_DIR.DS.'css'.DS.'inc'.DS.$this->params['controller'].DS.$this->params['action'].'.css')){
           echo 
"\t".$html->css('inc/'.$this->params['controller'].'/'.$this->params['action']);
    }
    
?> 


I add a new directory to the /js and /css folders (/inc) to keep everything tidy. Hope you find it useful.
posted Wed, Jun 27th 2007, 07:17 by Alex McFadyen

Comment

4 Helper

posted Tue, Sep 25th 2007, 13:34 by Danny Ferguson

Comment

5 Another Idea...

If your page titles are named simply like mine, you can throw this in your default.thtml <head/> tag:

echo $html->css($this->pageTitle);
posted Mon, Oct 15th 2007, 22:38 by ted stevens

Comment

6 Cool

That is really great! :-D Very simple, very organized. great work! Thanks!
posted Sat, Feb 2nd 2008, 14:05 by Zach Smith

Comment

7 A more comfortable solution

I found all these proposed solutions very interesting, but they all have an annoying thing: you MUST put in EVERY view template some code, and if you have many actions for a controller you have to edit each view.
The solution i'proposing is this:
chose your preferred method for organinzing the style sheets from the ones listed above, but
instead of putting inside the view the code for loading,
edit the AppController class, and inside the beforeRender() method put this code:

function beforeRender(){
....
if( file_exists(CSS.$this->params['controller'].'.css') ){
$this->set('controllercss_for_layout',$this->params['controller']);
}
....
}

then into your LAYOUT insert inside the <head> section something like this:

<?
if(isset($controllercss_for_layout))
echo $html->css($controllercss_for_layout);
?>



In this way you don't have to care about the css loading inside the views, you can do the same thing for javascripts, and extending the concept to an action specific css/js is very simple.

CakePHP is to develop FAST ..and this is avery fast way
to do it :-)
posted Fri, May 9th 2008, 08:30 by Andrea Cappalunga

Login to Submit a Comment