Hello and happy holidays everyone.
Recently I have been tasked with transforming a beta application from pure PHP/jQuery to CakePHP/ExtJS (Which I am new to).
My issue is with the most complex query that populates the main grid.
To keep things simple there are 3 tables with correct baked relationships and models: Projects, ToDo, ExtraToDo
Projects hasMany ToDo and ExtraToDo.
ToDo and ExtraToDo have columns Title and Complete.
My goal is to get a completion percent for each project based on these three tables.
The way I have gone about this is the SUM of the Complete column divided by the COUNT of the Complete column. I am trying in a CakePHP way for readability/performance/otherstuffIdontknowyet.
Originally, in raw SQL I had done it like this:
SELECT
`idProject`,
(SELECT
ROUND((SUM(`Complete`) / COUNT(`Complete`)) * 100),
FROM
(SELECT `Complete`, `ProjectID` FROM `ToDo`
UNION ALL
SELECT `Complete`, `ProjectID` FROM `ExtraToDo`) orders
WHERE
`ProjectID` = `idProject`
) AS 'Completion'
FROM
`Projects`
I also got this to work in the Kohana PHP MVC framework fairly easily which I tried before deciding on CakePHP. I LOOOVED how their queries were created…:
private function get_completion() {
$Query = DB::select('ProjectID', array(DB::expr('ROUND((SUM(`Complete`) / COUNT(`Complete`)) * 100)'), 'Completion'))
->from(array('ToDo', 'ExtraToDo'))
->group_by('ProjectID');
return $Query;
}
public function get_all() {
$Query = DB::select()
->from('Projects')
->join(array(self::get_completion(), 'Completion'))
->on('projects.id', '=', 'Completion.ProjectID')
->execute()
->as_array();
return $Query;
}
Unfortunately I have completely struggled to get this working in CakePHP while doing it the CakePHP way.
I’m pretty sure virtualFields are the key to my answer but after reading the documents and trying x, y, AND z. I have been unable to comprehend them and how they relate.
Thank you in advance
-T6
That is a lot of nested selects. IMO you would be better off building a better query.
This should get you going.
Now you have a custom find method that can be used like
find('first')orfind('all').From the controller:
Or in the Project model
It should return something like this: