This short post is for everyone using CakePHP plugins and getting 404 errors when they try to access a Controller in their plugin. I spend 1 hour puzzling to find out what could possible be wrong with my plugin. Especially considering that the plugin was already running perfectly on several production servers. It turned out it had something to do with my Apache settings.
What was happening? I created a plugin, for the sake of this post let's call it 'MyPlugin' and I wanted to access the controller 'MyController'. Normally, you would point your browser to http://localhost/myapp/myplugin/my_controller, but instead of getting the expected page, I got a 404 error. Interestingly, the CakePHP logs did not show anything, meaning that the framework was not even being accessed. Eventually, I read the Apache logs and found this particular message:
[Mon Jun 09 09:19:06 2014] [error] [client 127.0.0.1] Negotiation: discovered file(s) matching request: /var/www/myapp (None could be negotiated)., referer: http://localhost/myapp/
After some Googling I found out that it hat something to do with the MultiView module of Apache. Let me quote the effect of this module:
If the server receives a request for /some/dir/foo, if /some/dir has MultiViews enabled, and /some/dir/foo does not exist, then the server reads the directory looking for files named foo.*, and effectively fakes up a type map which names all those files, assigning them the same media types and content-encodings it would have if the client had asked for one of them by name. It then chooses the best match to the client's requirements.
Apache was thus finding some physical file on a per-directory basis and then using Content Negotiation to try and figure out which file it should serve up based on the request headers. And, since I didn't have any file types configured for content negotiation, Apache didn't know how to respond and just returned a 404.
In the end, I just disabled the MultiViews module in the Apache settings:
Options Indexes FollowSymLinks -MultiViews
and everything worked accordingly.
This clearly shows that using the default settings of Apache without really knowing what they do it a very bad thing.