# CakePHP and htaccess caching funtimes

I wanted to fire up a quick post about my CakePHP and htaccess caching issue — So I was working on a CakePHP project and I was pulling my hair out wondering why a development site was redirecting to a production site, the issue was quickly narrowed down the the .htaccess file which was uploaded to the development area in error — it contained some redirect rules that were kicking in.

So I logged into the development machine and removed the offending htaccess rules, refreshed the page but the issue was still happening.

The reason was that the development server had also had the config file for the production server which has CakePHP caching turned on.

The main take away here is that your .htaccess can potentially get cached by CakePHP, this isn’t something I had thought would happen and until there is a problem you might never consider this as an issue.

The second take away is that the code shouldn’t have needed to be kept separate between development and production, this is something I am going to look at improving on some projects.

In my case the fix was to clear the cache, once Cake had picked up the new .htaccess file everything was grand again.

Going forward I am going to make sure that when I make changes any files on a CakePHP project I will refresh the cache, just to play it safe.

# Copying a CakePHP Project from Linux to Windows

Recently I had to make some changes to a website built on top of the CakePHP framework.

Most of the time I would develop within a Linux environment, making the edits locally and running them on a development server before pushing them onto a production server – the development server being pretty much a clone of the production server.

This time however I opted to do the changes locally (there were a lot of small changes that make pushing to a development server a bit of a pain).

My setup is Windows 7 with XAMPP installed on it, but the stages I had to follow should be similar for most setups.

I already had the website code downloaded onto my machine as that is where I make the edits – once I set up my hosts file in Windows and the virtual host directives in Apache I figured I would be 90% of the way there. I wish!

Warning: include(cake\bootstrap.php) [function.include]: failed to open stream: No such file or directory in C:\path\to\my\site\webroot\index.php on line 78

Warning: include() [function.include]: Failed opening 'cake\bootstrap.php' for inclusion (include_path='/path/to/cake') in C:\path\to\my\site\webroot\index.php on line 78

Fatal error: CakePHP core could not be found. Check the value of CAKE_CORE_INCLUDE_PATH in APP/webroot/index.php. It should point to the directory containing your \cake core directory and your \vendors root directory. in C:\path\to\my\site\webroot\index.php on line 79

Obviously you go where the errors take you, sure enough if I open webroot/index.php I can see that it is linking to a folder structure that I don’t have locally.

I jump onto the development machine and grab the files that it was linking to, pull them into a folder and put the correct path in, like so:

if (!defined('CAKE_CORE_INCLUDE_PATH')) {
//define('CAKE_CORE_INCLUDE_PATH', "/old/linux/path/cake" );
define('CAKE_CORE_INCLUDE_PATH', "C:\new\windows\path\cake" );
}

Now when I go to my site I get this error:

An Internal Error Has Occurred

Useful! But before that displays I do get some of my layout displaying on screen, so there is a bit of progress.

In order to squeeze some more information out of cake I go into config/core.php and change the debug level.

//Configure::write('debug', 0);
Configure::write('debug', 2);

Now when I refresh the page I get plenty of useful information! In my case it was because I was an idiot and forgot to hook up my database – I won’t go through the steps to do that but basically export the development database, import it into your local and make sure you set up the same users with the same privileges.

I tend to try and keep my local setup the same as development so I am not messing about with config files too much.

My next issue that is immediately apparent after a refresh is that CSS is not getting loaded (and I am going to guess that JavaScript isn’t getting loaded either).

I have found that the best way to begin to track down this sort of issue is to view the source of the page, first of all is the code in place to try and load in CSS? In my case it was.

Next question, does the path to the CSS file look right? Again in my case it does.

Final question, when you click on the link to the CSS file, does it load? In my case it does not.

This immediately feels like an issue with either Apache or .htaccess redirects.

First let me check Apache to make sure that mod_rewrite is turned on, I check my httpd.conf file and sure enough it is enabled. Which means there is probably something wrong with how my site is locally trying to rewrite things. Onto .htaccess!

Annoyingly in my case htaccess was fine – in my case it turns out that I stupidly didn’t have my path in my virtual host set to the webroot, once I added this into my virtual host directive and restarted Apache I started to get my CSS again.

That is almost us finished – everything seems to be working but there was one edit made earlier that needs to be tidied up – the location of the Cake folder is something you want to worry about long term, having to remember to change that whenever you move code about is just a pain.

You don’t want to exclude webroot/index.php from any deployment solution because at some stage you might change something that you want to deploy, so I suggest doing something like this:

	if (!defined('CAKE_CORE_INCLUDE_PATH')) {
$currenturi =$_SERVER['DOCUMENT_ROOT'];
$mypos = strpos($currenturi, 'C:');

 var $validate = array( 'name' => array( 'rule' => 'alphaNumeric', 'required' => true, 'allowEmpty' => false, 'message' => 'Please enter your name' ), 'email' => array( 'rule' => 'email', 'required' => true, 'allowEmpty' => false, 'message' => 'Please enter your email address' ) );  Obviously replace the fields and rules with your own, but that is the basic idea. ## Controller In the controller I perform a test to see if the data is valid before saving, if it is then you save as normal, if it isn’t then I append the error messages into the inbuilt flash function. $this->Contact->set($this->data); if ($this->Contact->validates()) { //Normal Saving Stuff } else { $this->Session->setFlash(__(implode('<br />',$this->Contact->invalidFields()), true)); } 

The three important things here are;

• Setting the data to the model
• Doing the validates() check
• Imploding the error array to make it a string for the setFlash function

Hopefully this helps someone stuck with CakePHP validation.

This is something that caught me out several times when I was new to CakePHP, so I thought I would post it here in case you are in a similar situation.

Basically I was hitting issues that when I was viewing the variables available to a view (using the CakePHP Debug Toolbar) were I was noticing that I was bringing back far more information than I needed (and occasionally, not enough)

Bringing back too much information is never a good thing, it is inefficient and a possible security leak.

The reason for this is that in CakePHP the Read, Find or FindAll takes in a value called Recursive.

To set the level of recursion you do something similar to the following;

$this->Model->recursive = 1 There are 4 settings, which can be read about in detail in the CakePHP Book, but basically you can use this to make Read, Find or FindAll not perform JOINS (or perform more of them!). Be sure that your selections only ever return the data they need to and no more. Share this on # Get rid of var$name in CakePHP

A lot of people new to CakePHP struggle with remembering what to call and when, a common thing I see people doing inside their controller is something like;

$this->Sections->recursive = 0; When actually they mean something like; $this->Section->recursive = 0;

I think the reason the Model is sometimes pluralised is because when you look at most examples of how to write controllers the very first thing inside the class is;

var $name = 'Sections'; The reason this is included in both the Model and the Controller is to punch PHP4 into playing nice. If you require PHP4 then fair enough, but the vast majority of us use PHP5 and as such have no need for$name. So I would implore you to remove it from samples and code that doesn’t require it as some people seem to trip up over it.