UPDATE June 02/10: Please check out the update to Copyable behavior

Until I switched to CakePHP, any CMS I built for a client had a “copy this item” tool. The Cake framework doesn’t have anything like that built in, so for the past year or so the new Cake-powered CMS I built for work hasn’t had any sort of ‘copy item’ ability. Recently, however, I needed the functionality, so I decided to write a behavior to handle it. And now I’m happy to release it to the community as Copyable Behavior.

Download Copyable Behavior on Github.

I’ve wrapped it in a plugin, since that seems to be the trend in the community these days (though I’m not sure why just downloading a behavior file is so bad).

Copyable adds a copy() function to your model, which you can use to copy (that is, create a duplicate of) a record and any of its hasOne, hasMany, or hasAndBelongsToMany relationships. In the case of hasOne and hasMany, those records are recursively copied as well. For example, if you want to copy a LinkCategory that hasMany Link, all of the Link records will be copied. The copy is fully recursive, meaning that if Link HasMany Comment, then all of those records will be copied as well. In the case of HABTM associations, only the join table rows are copied, not the associated records. The copy() function takes one argument – the ID of the record you wish to copy.

Copyable uses Containable to help generate its queries, but don’t worry – it’ll attach Containable if it can’t find it on the model.

A handful of config options:

  • recursive: whether to copy hasOne- and hasMany-associated models (default: true)
  • habtm: whether to copy hasAndBelongsToMany relationships (default: true)
  • stripFields: an array model fields that should ignored when copying (default: id, created, modified, lft, rght)

After attaching Copyable to a model via the $actsAs array – I recommend putting it on AppModel – usage is as simple as:

// From a controller method
$this->MyModel->copy($id);

// From a model method
$this->copy($id);

This is still an early version (I just finished it – and started it – today), but results have been pretty good so far. Suggestions welcome. I’ll probably throw this on the Bakery after it’s been out there for a little while. But for now, it’s on Github.