Sorting question

My action method in the controller is as follows, nothing special.




        /**                                                                                                  

         * Shows a particular model.                                                                         

         */

        public function actionShow()

        {

                $criteria=new CDbCriteria;

                $criteria->order = 'task';


                $pages=new CPagination(Task::model()->count($criteria));

                $pages->pageSize=self::PAGE_SIZE;

                $pages->applyLimit($criteria);


                $sort=new CSort('Task');

                $sort->applyOrder($criteria);


                $models=Task::model()->findAll($criteria);


                $this->render('show',array(

                        'models'=>$models,

                        'pages'=>$pages,

                        'sort'=>$sort,

                ));

        }



I would like to sort the data($models) by task numbers which happen to be such as ‘1.1’, ‘1.2’, … ,‘1.9’ and ‘1.10’.

So my question is how I would sort the task number using CSort (or some other way). I was not able to find the custom sort algorithm in CSort class.

Without a special care, the sort result might be like ‘1.1’, ‘1.10’, ‘1.2’ … Of course I prefer to have it sorted as ‘1.1’, ‘1.2’, … , ‘1.9’ and ‘1.10’.

Thank you in advance for your hint.

If in your db task are written like ‘1.1’,‘1.2’, ‘1.10’, I have no idea about how to sort.

You have to immagine a sql order condition that allows you to correctly sort this elements, because CSORT cannot do anything that db is not able to do (CSORT simply add to the query an ORDER BY statement).

You can write in DB your task in 2 separated fields (like task_1, task_2) and $criteria->order = ‘task_1, task_2’; will work properly.

You can add in model


public function getTask()

{

   return $this->task_1.'.'.$this->task_2

}



And noone will notice that the attribute task is changed!!! All "observer" views will work properly.

If you want to leave even the writer views unchanged you can write in model:


public function setTask($task)

{

   this->task_1=substring(...);

   $this->task_2=substring(...);

}



And even the view create and update task will never notice this change!

Thanks zaccaria for your hint. Unfortunately, actual task numbers are like these; ‘1.1’, '1.1.1, ‘1.1.1.1’ etc. depending on the depth of the tasks.

I understand that CSort cannot handle sort algorithms; which is left to the database and the database generally is not wise enough to handle this.

One way is to limit the depth of the tasks to say ten. I am going to consider based on this idea, thanks again!

I’m not sure, but wouldn’t be possible to have an additional left-zero after dot like in ‘1.01’, ‘1.02’, ‘1.03’, ‘1.04’, … ‘1.09’, ‘1.10’, … ‘1.20’ … ?

this way the sorting is fluid

You could also check out MySQLs string functions and try to convert the ‘1.2.3’ to an equivalent integer on DB side. You’ll have to fiddle a little with integration into your model though (adding custom select fields).