Sun 17 Feb 2008
Way back when CakePHP had a wiki there were a series of articles on “Advanced Validation.” One aspect of these articles was using the Model rules in JavaScript to validate on the client side. The code (I believe this is it) was originally for CakePHP version .10 (iirc). I had been using a heavily modified version of this code even in my 1.2 projects, but it was due for a ground up re-write.
I wrote an article for PHPArch not too long ago with a generic PHP approach for JavaScript validation. Using that JavaScript as a base, I created a helper to convert the model rules into JavaScript.
Here are the links:
Download
Instructions
Demo
This is all very beta, so please let me know if you find an issue. The helper should work with the three formats for defining validation in your model (output from bake, one rule per field, multiple rules per field).
If you are worried about security, there is an option to only include certain rules. See the tips section at the end of the instructions. Thanks to Marc for suggesting this.
Sun 17 Feb 2008
I just posted a bug fix for my CakePHP Asset Packer. The previous version didn’t handle $javascript->codeBlock, when the inline option was set to false. The JavaScript would just disappear…ooops. Updated code is available in the Bakery article or you can download here.
Tue 12 Feb 2008
I just stumbled on this smokin’ article on PHP Architect’s new C7Y site. It’s really some of the best PHP writing I’ve ever seen - even non-programmers will probably enjoy it…uh…alright I wrote. So please check it out.
I’m about 75% done rolling this into a CakePHP helper. And since Cake is going re-focus on jQuery as it’s primary JavaScript library there will be no excuse for not using it.
Sun 10 Feb 2008
Here’s a list of various CakePHP turorials, organized by subject. I’m trying to stick to mostly 1.2 stuff, but included some 1.1 tutorials that we’re still helpful. Leave a comment if I missed one and I’ll add it to the list.
General
manual.cakephp.org - The 1.1/Old Manual
tempdocs.cakephp.org - The 1.2/New Manual
www.amazon.com - Beginning CakePHP: From Novice to Professional (not yet released)
api.cakephp.org - The API
Getting Started
www.ibm.com - IBM’s 5-part “Cook up Web sites fast with CakePHP”
manual.cakephp.org - CakePHP Blog Tutorial
cakephp.bytenoise.co.uk - In the Kitchen with CakePHP
Version 1.2 Info
cakebaker.42dh.com - Deprecated stuff in CakePHP 1.2
Bake Console
cakebaker.42dh.com - Faster baking with bake
www.littlehart.net - Screencast: Interactive Console for CakePHP
Debugging
www.cakephp.org - Using Debug Messages
Test Suite
bakery.cakephp.org - Testing Models with CakePHP 1.2 test suite
cakebaker.42dh.com - How to use the official CakePHP test suite
Auth Component
www.littlehart.net - Simple User Registration in CakePHP 1.2
www.webdevelopment2.com - CakePHP Auth Component For Dummies Tutorial
www.webdevelopment2.com - CakePHP Auth Component - Tutorial Two
ACL
lemoncake.wordpress.com - Using AclBehavior in CakePHP 1.2
lemoncake.wordpress.com - Using AuthComponent and ACL in CakePHP 1.2
bakery.cakephp.org - How to use ACL with Cake PHP 1.2.x?
www.realm3.com - Setting Up User Groups With ACL and Auth in CakePHP 1.2
Ajax
bakery.cakephp.org - Getting started quickly with Scriptaculous effects
Advanced Ajax
blogs.bigfish.tv - Drag and drop using Ext JS with the CakePHP Tree Behavior
mentalramblings.info - CakePHP Ajax Comments
HABTM
tempdocs.cakephp.org - hasAndBelongsToMany (HABTM)
Admin Routing
www.cakephp.org - Admin Routing
Validation
bakery.cakephp.org - Multiple rules of validation per field in CakePHP 1.2
cakebaker.42dh.com - Validation with CakePHP 1.2
tempdocs.cakephp.org - Data Validation
Pagination
tempdocs.cakephp.org - Pagination
www.littlehart.net - CakePHP Pagination With A HABTM Relationship
cakebaker.42dh.com - Pagination of data from a HABTM relationship
RSS
cake.insertdesignhere.com - Cake 1.2’s new RSS helper
Theming
www.sanisoft.com - Theming your CakePHP apps (V1.2)
www.pseudocoder.com - Theming With CakePHP
Counter Cache
cakebaker.42dh.com - Counting associated records
www.cakephp.nu - CounterCache in CakePHP 1.2 beta
Builds
ertw.com - Pushing a CakePHP app from dev to prod
The Set Lib
www.thinkingphp.org - Cake 1.2’s Set class eats nested arrays for breakfast!
cakebaker.42dh.com - An alternative way to create arrays
Thu 24 Jan 2008
I’ve been using the built in pagination in CakePHP 1.2-beta a lot lately and I must say it’s freaking awesome. My one oh so minor grievance is that it doesn’t “remember” where you were if you navigate off the page. For example many times I’ll be paging through a sorted list of records and want to edit a particular one. After I edit and save I’m dropped back to the index with the default sorting on page 1.
I Googled around a bit and skimmed through the pagination code, but didn’t see a quick way to turn this type of functionality on. So I wrote a quick component that keeps the sort/page in the session and re-applies it. This is all done automatically by just including the component in your controller.
You can download the component here.
I’ll probably submit it to the CakePHP Bakery soon, but was hoping to get some feedback first.
Wed 23 Jan 2008
Posted by Matt under
Javascript ,
PHP
No Comments
I almost never post links to other blogs posts, but I thought this was cool.
Leon Chevalier from AcidDrop.com (is this the worst name for a blog designed to showcase one’s professional skills or just in the top 5?) has created a PHP class (latest version) that will automatically package and minify all your CSS and JS.
I was playing around with it to see if there was anything extra Leon was doing that my CakePHP Asset Packer wasn’t. One thing I found interesting is that the actual cached CSS and JS are stored as PHP files. This is done so that PHP can set the expires headers and gzip the contents. Granted this should/could be done with the actual web server, but many shared hosts don’t allow this. Even so I’m not really sure doing this is a great idea, since you’re essentially trading process time for network time.
From the comments it seems like people are having success using this with their WordPress sites. It would make sense to roll the whole thing into a plugin.
Sun 20 Jan 2008
R. Rajesh Jeba Anbiah left a comment concerned about the performance hit when using the CakePHP Asset Packer Helper.
The major reason for choosing the Asset Helper is to speed up the site. But, the hit on the helper call is heavy–at least for me. [snip] …for the real benefit, one seems need to manually minify/pack.
I decided to put this to the test. I grabbed a fresh download of the latest CakePHP 1.2-beta and made a basic TestsController with one action with a view. It didn’t use a model. I took the default layout and moved it to my /app/views/layouts. In the layout I added 2 Stylesheets and 2 JavaScripts. In the view I included one of each using the $scripts_for_layout method. I used ab, with the parameters “-c 10 -t 60″, to do the testing. Since this was all on my local machine network speed isn’t really a factor. Essentially I would be getting the times to render the page.
The first test I ran was without the Asset Packer Helper - what you would get with the base CakePHP install.
Here’s the baseline results:
Complete requests: 622
Requests per second: 10.36 [#/sec] (mean)
The hope is that including the helper won’t hurt these numbers too much. The speed increase gained by using the helper is seen in the download of merged js and css files and since ab is only testing the html file (not the images, css, jss linked within), the benefit of the helper won’t be evident in this test.
First I included the helper and commented out the filecaching. This is essentially what happens when the helper is being used for the first time on a particular group of css/js files. Either because one of the files has changed or because the cache hasn’t been created yet. Consider this to be the worst case scenario and probably would only really happen a tiny percentage of the time, like right after you do an update. I expected the numbers to take a hit, but not to be this bad:
Complete requests: 32
Requests per second: 0.52 [#/sec] (mean)
Did I emphasize that this scenario doesn’t happen very often? I could try to improve this, but I’m not sure it’s worth it. This doesn’t happen too ofter, plus most of the time is probably in the css and js minifying/packing, which are vendor classes.
Let’s take a look at a more common use case. The cached files already exist, so the helper checks to see if there are any changes, finds none and doesn’t have to do any extra processing.
Complete requests: 583
Requests per second: 9.69 [#/sec] (mean)
Much better. Still a hit from the baseline numbers, but not too bad.
Here’s one more test. In the AssetHelper class there is a var $checkTS. Setting this to false will disable the functionality described above, where the helper will see if any of the original css/js have changed and the cached version needs to be rebuilt. You can safely set this to false if you clean out your packed directories with new builds.
Complete requests: 602
Requests per second: 10.03 [#/sec] (mean)
That’s an improvement over the default settings for the helper and are pretty close to the baseline results. The difference is 3.15700 milliseconds/request or .003157 in seconds.
I may look into trying to get that last scenario closer to the baseline, but the difference isn’t so significant that I would really worry about it.
So what does the extra .003157 seconds of processing time get you? This isn’t a perfect test, but I ran Yslow on the baseline setup and again with the helper. The baseline scored a D(61). With the helper that jumped to a B(81).
Thu 17 Jan 2008
Posted by Matt under
CakePHP ,
My Apps
No Comments
I’ll get back to posting some more CakePHP tips soon. I promise I have a bunch of ideas queued up.
In the meantime I wanted to announce my latest CakePHP site, InStalker.com. InStalker is a site to help people get hard to find products like the Nintendo Wii and DS Lite. I know there are tons of other sites that already do this. Two things I didn’t see very often on the other guys is Twitter support and Ajax. There is no need to sign up for anything. You just leave the site open in your browser and it will automatically alert you when $latest_trendy_product is in stock.
It’s using the latest beta 1.2 release (which rocks). A lot of the code and design came from RSStalker.com, so it really didn’t take me that long to put together.
So if you’re looking for a Wii (still not in stock very often and when it is you usually need to buy as part of bundle) or DS Lite (comes in stock often, but you have to be fast) check it out.
Mon 7 Jan 2008
This post is part 2 of a series focusing on CakePHP 1.2.
There have been a couple posts lately on the CakePHP Google Groups asking how themes work. I responded to one with the some quick basic steps. There is also a post by Tarique Sani that give a pretty good starting point.
This is basically a rehash of my response with a bonus tip to simplify theme management.
The Basics
In your AppController you turn on CakePHP theming by adding the following variables:
var $view = 'Theme';
var $theme = 'default';
I like to set the theme right off the bat to some default theme, then in the beforeRender callback reset the correct theme. How you store the current active them is up to you. It could be a config value, session value or a record in the database. Once you have this you can set it with:
$this->theme = $themeName;
Where do all the files go?
If you left all the CakePHP defaults alone you would put your layouts and views in /app/views/themed/themeName. For example the directory structure would look like this:
/app/views/themed/themeName
/app/views/themed/themeName/layouts/
/app/views/themed/themeName/layouts/default.ctp
/app/views/themed/themeName/views/
/app/views/themed/themeName/views/action/
/app/views/themed/themeName/views/action/index.ctp
Then for your css, js and images your would make similar directories under /app/webroot/themed:
/app/webroot/themed/themeName/js/
/app/webroot/themed/themeName/js/jquery.js
/app/webroot/themed/themeName/css/
/app/webroot/themed/themeName/css/style.css
/app/webroot/themed/themeName/img/
/app/webroot/themed/themeName/img/logo.jpg
I wasn’t particularly fond of this approach since it meant maintaining a theme in two locations. I couldn’t just “drop it in”.
Instead I chose to merge the two locations and have the views and layout located in /app/webroot/themed with the js, css and images. I’ll get to the security issues with this in a moment, but first how do I tell Cake to look in webroot for views? In your /app/config/bootstrap.php simply add:
$viewPaths = array(WWW_ROOT);
Now cake will look in both /app/views and /app/webroot/ for any views and themes.
The issue now is that all my views and layout are directly readable. If someone were to type in the path to one of these files in their browser they see all the raw PHP code. To stop this simply create a .htaccess file in /app/webroot/themed with:
DENY FROM ALL
Wait! My App Is Now Super Slow!
See the first comment for clarification on this issue.
Here’s what’s happening. The controller renderer has to load theme.php for outputting a themed view. It does this using the new App::import functinality, part of which is a recursive directory search through all the view paths, which after our change above looks like this:
/app/views
/app/webroot/
/cake/libs/view/
The theme.php files lives in the last location, but to find it, Cake has to search through the first two locations. Now if you have a ton of folders in your webroot, a bunch of folders for product images or something like FCKeditor (467 folders!), the search is going to take awhile.
To fix this I re-ordered the viewPath list in my AppController->beforeRender.
$viewPaths = Configure::read('viewPaths');
array_unshift($viewPaths, array_pop($viewPaths));
Configure::write('viewPaths', $viewPaths);
The list now looks like this:
/cake/libs/view/
/app/views
/app/webroot/
This probably isn’t the best solution, so if you find something better, please let me know.
Some Final Tips
The great thing about CakePHP theming is that if any of the views/css/js/whatever files don’t exist in the theme, Cake will automatically fall back to the default locations. This is nice since it allows you to only create the files you need and use the defaults for the rest of the site. In many cases you really only need theme files for the layout, css and images. I like to include two css files in each layout. A default.css which is in /app/webroot/css/ and has all the base styles for the site. Then a second style.css in /app/webroot/themed/themeName/css/ which has theme specific styles.
Elements work as normal with themed layout, so if you make the html code in them really generic (for example: a ul/li menu) it’s super easy to share the element, but make it look completely different with the theme’s css.
Tue 1 Jan 2008
This post is part 1 of a series focusing on CakePHP 1.2.
CakePHP’s Interactive Bake Shell is one it’s most powerful features. It is a simplified command line interface for code generation. Most commonly it is used to generated code for models, views or controllers. I often use it to create a base of code, then tweak that code to fit into the application. An obvious issue is the baked code has actions and views for both add and edit functionality. Very often these two operations are virtually identical so, it doesn’t really make sense maintaining separate code that does the same thing, commonly know as DRY.
Merging the add and edit actions
This is actually quite simple and only take a minute to do. The steps are the same for both the regular add/edit and the admin routed add/edits.
The Add Action
Open the generated controller PHP file. In it you’ll see a function for add() and another for edit(). Replace the entire add function with a call to render the edit view. It should look like this:
function add() {
$this->render('edit');
}
You could also completely remove this action and fix any link that point to /controller/add to /controller/edit, but I prefer this way, since code generated for other models may have links to this model if the tables are related. You can delete the /views/controller/add.ctp file.
The Edit Action
There are a few more changes required in the edit action. Find the edit function, right below the add function. Delete the first if statement:
if (!$id && empty($this->data)) {
$this->Session->setFlash('Invalid Model');
$this->redirect(array('action'=>'index'), null, true);
}
Further down these is:
if (empty($this->data)) {
Change that to read:
if ($id && empty($this->data)) {
The Edit View
As I mentioned above you can delete the add view (add.ctp). In the edit view (edit.ctp) you’ll need to add a parameter to the form create line to make sure the form always submits to the edit action. It should like something like this (your model will vary):
<?php echo $form->create('Model', array('url' => array('action' => 'edit'))); ?>
You may also want to change the legend so that it reflects whether you are adding or editing the record. There are a couple different ways to do this, but the quickest is to check the action:
That’s it. You now have an action and view that handles both add and edits.