In an interview, Nate Abele made some very interesting outlooks towards Cake3.
And although I really appreciate this modern approach, I’m also scared how much work needs to be done to make NoseRub compatible with Cake3.
I should invest a lot more time into UnitTests and tests with Selenium in order to be prepared to find all the nasty side effects that might arise from such a giant move towards Cake3.
Similar to Wordpress Themes, CakePHP offers developers to implement a theme system for their applications.
We used this built in Themes support for NoseRub. Admins of a network should be able to add their own theme, so that the NoseRub installation matches their CI. And users should have the possibility to choose the look of their profile page from a list of given themes.
All templates for websites that Cake renders, are called Views and are organized in the following folder: /app/views/. CSS and Javascript can be found in /app/webroot/.
To enable support for themes in CakePHP, you have to change the View class for that controller. But you can also do this directly in the AppController:
class AppController extends Controller {
public $view = 'Theme';
...
}
Before rendering a page, you now need to tell CakePHP, which theme should be used. We introduce a default theme in NoseRub and set this also directly in the AppController:
class AppController extends Controller {
public $view = 'Theme';
public $theme = 'default';
...
}
This way, you can choose another theme at any place in your controller. If you want to display the profile page of a user with the theme that the user choosed, you can do this like this:
class UsersController extends AppController {
public $uses = array('User');
public function view($username) {
$user = $this->find('first', array(
'conditions' => array(
'User.username' => $username
)
));
$this->set('user', $user);
// todo: check that user exists before proceeding!
// todo: check that value of user theme is valid
$this->theme = $user['User']['theme'];
}
}
CakePHP is now looking for the views in the following folders: /app/views/themed/[theme name]/ and /app/webroot/themed/[theme name]/. If the themes’s name is green CakePHP would look for the default layout (as no other layout is specified here) in /app/views/themed/green/layouts/default.ctp and the to be rendered view in /app/views/themed/green/users/view.ctp.
The really great thing about this is, that CakePHP always looks for the version without themed in the path, if it cannot find the path with themed in it. This way, the themes can be pretty small, because you just need to change the things you really need to. For some cases, you might even only need to include a CSS file into a new theme! (Think CSS ZenGarden…)
This fallback mechanism also works for Javascript and CSS files. In NoseRub, we render the JS tags with the following two lines in an element:
echo $javascript->link('theme.js');
echo $javascript->link('noserub.js');
In /app/webroot/js/theme.js we placed an empty file, but CakePHP will deliver a theme specific JS, if theme.js is included in that theme.
The only real disadvantage of Cake’s Themes is, that you always have to spread the file of your theme in two different folders (/app/views/ and /app/webroot/). This is much simpler in Wordpress.
But you gain a lot of security, because the PHP code in your views are not publicly accessible, because they shouldn’t be included in your webserver document root.
In the case of NoseRub, we will probably have a theme upload in the Admin area, which takes archives with two folders in it: webroot and views
Update: In the comments to the german version of this article, Robert gives some advice on how to use view caching together with themes.
The translation: Themes are not compatible with caching at the moment, as caching takes place in the Dispatcher, even before the controllers are created. If you know, which theme to use before dispatching the controller method, you can create your own Dispatcher class and overwrite cached(). If you need caching on views/elements, you need to create you own View class which extends the Theme class and implement renderElement() and/or element().
Using query() and execute() is very tempting: at some points you are faster doing a query in plain SQL, than building a proper find() statement.
But you really should not do it!
I had a lot of discussions with a colleague of mine and finally he made the argument that hit me:
beforeFind()andafterFind()will not apply to your plain SQL statements.
That’s it. Life can be so simple.
Imagine you add some data in afterFind()
And even if you now argument, that you will not do this, imagine the hassle you will be going through, if you have to use beforeFind() or afterFind()!
So, learn how to write proper find() statements and you will not only learn a lot from it, but you also will have more failproof code.
This is the english version of my older blog CakeBakery and will include recipes, tipps and tricks for your development with CakePHP.
I’m a CakePHP developer since 2006 and am currently using the web framework for NoseRub. NoseRub is an open, distributed social network and is released under the MIT license.
So, if you want to, you can check out the code: noserub.com/code
I hope to be able to add new content on a regular basis now. Often the small tricks are the most important ones, so I will not hesitate write about minor issues, too