Saturday, May 23, 2009

How to exclude CakePHP's tmp directory on SVN using svn:ignore

I wrote a post before about moving CakePHP's tmp directory outside of app so it won't be included in SVN. It's a good concept but since it's a bit dirty and not standard, it might lead to some problems later and when upgrading.

A better solution to this problem is to just exclude the contents of tmp (or any other directory you don't want to include in SVN). Here's how to do it on TortoiseSVN:
1. Backup the contents of tmp/ (cache, logs, sessions, tests, etc)
2. Delete all the contents tmp/
3. Commit the empty directory tmp/ to svn
4. After commit, right click the tmp/ folder and choose TortoiseSVN-> Properties
5. On the properties dialog, click New.., then set the Property name to svn:ignore and Property value to *
6. Commit the changes to SVN
7. Move back the previous contents of tmp/

There you go! SVN will now ignore the contents of tmp/
Note: when you checkout on another machine, you will have to manually create the folders inside tmp since it's not included in your repository

Friday, May 22, 2009

Twitter-like delicious gadget for your blog

I was inspired by the great articles I've read today (which I got from Hacker News) so I decided to put links to these articles on my blog. Using the delicious API and some javascript goodness, I created a twitter-like delicious bookmarks list that I can use on my blog (or any blog for that matter). Check it out in action at my sidebar (below the twitter widget).

If you want the same thing, copy the code below and put it to where you want it to appear on your blog.

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3/jquery.min.js"></script>
<script>
// change to your username and tag
delicious_widget = {username: 'tonio95', tag: 'read'};

delicious_widget.feed = 'http://feeds.delicious.com/v2/json/'+delicious_widget.username+'/'+delicious_widget.tag+'?count=10&callback=delicious_widget.print_list';
delicious_widget.print_list = function(data) {
var box = ['<ul>'];
$.each(data, function(i, item){
box.push(['<li><a href="', item.u, '">', item.d.substring(0,60), '</a></li>'].join(''));
});
box.push('<li><a href="http://delicious.com/'+delicious_widget.username+'/'+delicious_widget.tag+'">More!</a></li></ul>');
document.write(box.join(''));
};
document.write(unescape("%3Cscript src='" + delicious_widget.feed + "' type='text/javascript'%3E%3C/script%3E"));

</script>

Enjoy! and have fun reading!
Want more delicious? check out the delicious lite firefox extension

Thursday, May 21, 2009

Smart Bro Prepaid (USB Modem)

I recently bought a Smart Wireless Broadband Prepaid (USB Modem) because I needed a backup internet connection for my work. This thing costs PhP1995 and includes PhP100 load. I was able to connect in no time (from unboxing to installing the software). It's really easy to use and you don't have to configure anything. I'm quite impressed with it (based on my initial testing). I used it at 11pm, and the download speed was around 1.5-1.8mb/s. YouTube streams *almost* in real time (it buffers sometimes but you won't have to wait long).

My plan before was to use a 3G phone as modem (LG KU250) on Globe's network (my primary network), but Globe doesn't have a 3G signal here (weird because the 2G signal is full) so I decided to go with Smart. Smart's signal in my area (I live in QC) is WCDMA, which I think is the best signal you could get. I don't know how Globe's mobile broadband compares to Smart, but one thing I like about Globe is it charges per 15mins (Php5), while Smart charges per 30mins (Php10). Globe's charging rate seems more practical especially if you're just checking email every once in a while.

Anyway, I won't be using this much since it's only a backup connection in case Bayantel's DSL goes down for a whole day, like what happened last month. Let's just hope it won't go down when I need it :)

Saturday, May 9, 2009

Essential CakePHP tips for starters

It's been 3 months since I started using CakePHP and I have to say I'm having a great time using it. Before trying it out I was using my own little framework and tried a bit of Zend Framework. I think the best thing about CakePHP is that it's a full stack framework, which means you can take advantage of a lot of built in features. It takes some time to get used to especially if you come from a do-it yourself background (like me :), but in the long run using its conventions and built in features will save you a lot of time.

First off, I will assume that you already know the basics (at least Chapter 1 & 2 of the CakePHP manual). Also, this post was inspired by Teknoid's 15 Essential CakePHP Tips which is a great read. I suggest you read it first before reading this (my favorites are #5 I’m losing the extra URL parameters when paginating and #9 Avoid using the $uses array)

Disclaimer: I'm no CakePHP expert yet so feel free to suggest or correct me if I'm wrong!

Let's start!

HABTM query
Let's suppose recipes has and belongs to many tags, how do you query recipies that contain a certain tag? There are many ways to do this, as documented on the CakePHP manual. I think the simplest and cleanest way is given on the first example:
$this->Recipe->bindModel(array('hasOne' => array('RecipesTag')));
$this->Recipe->find('all', array('conditions'=>array('RecipesTag.tag_id'=>124)));

Use named parameters
CakePHP works better with named parameters (/name:value), especially when you are using pagination and other helpers. But if you don't want to, classic style parameters (?name=value) can still be accessed via $this->params on the controller

Paginate an unrelated model
If you need to paginate a model that's not in the current controller, use loadModel('model').
$this->loadModel('User');
$this->paginate = array('limit'=>20);
$this->paginate('User');

Getting data from $this->params and $this->data
The usual way is to get request parameters directly is to get them from the $this->params (or $this->passedArgs) and $this->data array directly (eg. $input = $this->params['named']['input']). But it's a little dirty because PHP shows a notice if the key does not exist in the array. To prevent this, I created two functions on my app/app_controller.php file that gets data from the param and data array, in case the key does not exist, it will just return null.

function getParam($key)
{
// eg. http://myapp.com/pages/1/somekey:somevalue
// $somevalue = $this->getParam('named.somekey');
return Set::classicExtract($this->params, $key);
}

function getData($key)
{
// eg $name = $this->getData('Person.name')
return Set::classicExtract($this->data, $key);
}

(for more array functions, check out CakePHP's Set component)

Secure forms using the security component
If you want to quickly secure your forms, CakePHP can do this automatically by using the Security component.

Keep links relative. Use $html->link(), or Router::url()
If you want your app to be portable, take advantage of CakePHP's built in URL functions to keep your links working wherever you install your app (eg root directory or sub directory). Use $html->link() for generating full link tags, or Router::url() if you only want the URL (eg. using it inside javascript or inside the controller).
Hint: if you want to get the full URL (including http://) use Router::url('/controller/action', true)

Use form helper
Because writing a lot of forms by hand is boring :) You will also take advantage of other built in functions, like displaying validation error messages.

Use the same view for add/edit forms
Most of the time add and edit views are just the same. To avoid code duplication, you could set the add action to also use the edit view. Just add $this->render('edit') at the end of the action.
function add()
{
$this->render('edit');
}

Looking for more tips?
Check out Matt Curry's Super Awesome Advanced CakePHP Tips