OrderedBehavior (2.1)

By Alexander Morland (alkemann)
This behavior is intended for letting you order models like pages in a book in a the same way that the treebehavior works, with the difference that there is only one level (all the pages are siblings). It includes moveUp, moveDown, moveTo, sortBy, isFirst, isLast and off course inserts itself into saves and deletes to keep the lists correct. It does also have the option of sorting an entire table as one list, if that is what you need. I hope you find it useful.

What it does

It manages the creation and updating of the order field (called weight). It also sets the models order property to this field. When adding new nodes or deleting old, this behavior will do the necessary changes to keep the list working properly. It is build to be completely automagic after the initial configuration by letting it know your foreign_key and weight fields (unless you use the defaults off course).


Use example

Lets say you have books with pages and want the pages ordered by page number (obviously a book sorted alphabetically would be silly). So you have these models:


Book hasMany Page
Page belongsTo Book

The Page mode has these fields

  • id
  • content
  • book_id
  • page_number

To set up this behavior for the Page model

Model Class:

Download code <?php 
class Page extends AppModel {
    var 
$name 'Page';
    var 
$actsAs = array('Ordered' => array('field' => 'page_number','foreign_key' => 'book_id'));
}
?>


Now when you save a new page (no changes needed to action or view, but leave page_number out of the form), it will be added to the end of the book.


When deleting, the weights will automatically be adjusted to fill in the vacum. NB! Note that if using Model::deleteAll() it is VERY important that you assign it to use callbacks 'beforeDelete' and 'afterDelete', like this:


Download code <?php
// in controller action
$this->Page->deleteAll(array('user_id'=>22),true,array('beforeDelete','afterDelete'));
?>

Now lets say the last two pages to be created got made in the wrong order, so you want to move the last page "up" one space. With the a simple controller call to the model like this that can be achieved:

Download code <?php
// in a controller action :
$this->Page->moveup($id);
// the id here is the id of the newest page
?>

You find that the first page you made is suppose to be the 5 pages later:
Download code <?php
// in a controller action :
$this->Page->movedown($id5);
?>

Also you discovered that in the first page got put in the middle. This can easily be moved first by doing this:

Download code <?php
// in a controller action :
$this->Page->moveup($id,true);
// true will move it to the extreme in that direction
?>

You can also use actions to find out if the node is first or last page
  • isfirst($id)
  • islast($id)

And a last feature is the ability to sort the list by any field you want and have it set weights based on that. You do that like this:

Download code <?php
//in controller action :
$this->Page->sortby('content DESC'$book_id);
// don't ask me why you would sort the pages of a book by its content..
?>

Default configuration

It expects the order field to be called 'weight' and the foreign_key to be called 'order_id'. You can add the behavior with no options if these are the fields in your table.


Exceptional usage

This behaviour will also let you sort an entire table as one list. To do that you simply set the 'foreign_key' to false (and not create the field in the table). Now there will only be one set of weights. (Note you need the weight field as normal)


On the next page you will find the 2.1 (php4 compatible) version of the behavior.

If you would like to get a php5 version (camelBack names and private/public) and also the tests made for this behavior (if you do use the tests and modify the behavior, please let us know if you did something smart :P) you can find the code here:


http://code.google.com/p/alkemann/downloads/list

Page 2: The code

Comments 789

CakePHP Team Comments Author Comments
 

Comment

1 New version available

Posted Nov 13, 2008 by Alexander Morland