Problem

I recently ran into an issue where I found it much more efficient to write a custom query to gather the data I needed to perform some processing than it was to utilize CakePHP’s model/controller normal data accessing functionality.

At first, I wanted to make sure that all of my related tables gathered all of the data from each other. This created numerous objects filled with data that I may or may not use. It also resulted in the need to loop through every array multiple times to gather the final data required.

So, I decided to make a custom query  in the model that would handle joining all the tables into one array. I ran into trouble where fields were being grouped into their respective models as expected by CakePHP’s model class. This caused a headache to access the data properly again.

Original Custom Query

SELECT
	environments.id,
	environments.name,
	deploy_files.name,
	web_services.name,
	CONCAT(web_services.name,\'.\',users.name,\'=\',users.password) line
FROM
	deploy_files,
	environments,
	users,
	web_services,
	users_web_services,
	users_environments,
	web_services_deploy_files
WHERE
users.id = users_web_services.user_id
AND web_services.id = users_web_services.web_service_id
AND users.id = users_environments.user_id
AND environments.id = users_environments.environment_id
AND web_services.id = web_services_deploy_files.web_service_id
AND deploy_files.id = web_services_deploy_files.deploy_file_id
AND users.active = 1
AND web_services.active = 1
AND deploy_files.active = 1
AND environments.active = 1
ORDER BY
	environments.name,
	deploy_files.name,
	web_services.name,
	users.hidden DESC,
	users.name

Original Output

array (
  0 =>
  array (
    'environments' =>
    array (
      'id' => '1',
      'name' => 'Production',
    ),
    'deploy_files' =>
    array (
      'name' => 'test.login',
    ),
    'web_services' =>
    array (
      'name' => 'WebService',
    ),
    0 =>
    array (
      'line' => 'WebService.security=on',
    ),
  )
)

This output is usable, but I would have preferred to have everything simplified a bit and not grouped into sub associative arrays

Solution

I noticed the results of the CONCAT in the original query were in their own sub-array (0, zero). So, I took every column and put them in their own CONCAT and gave them an alias.

New Custom Query

SELECT
	CONCAT(environments.id) env_id,
	CONCAT(environments.name) env_name,
	CONCAT(deploy_files.name) file_name,
	CONCAT(web_services.name) ws_name,
	CONCAT(web_services.name,\'.\',users.name,\'=\',users.password) line
FROM
	deploy_files,
	environments,
	users,
	web_services,
	users_web_services,
	users_environments,
	web_services_deploy_files
WHERE
users.id = users_web_services.user_id
AND web_services.id = users_web_services.web_service_id
AND users.id = users_environments.user_id
AND environments.id = users_environments.environment_id
AND web_services.id = web_services_deploy_files.web_service_id
AND deploy_files.id = web_services_deploy_files.deploy_file_id
AND users.active = 1
AND web_services.active = 1
AND deploy_files.active = 1
AND environments.active = 1
ORDER BY
	environments.name,
	deploy_files.name,
	web_services.name,
	users.hidden DESC,
	users.name

New Output

array (
  0 =>
  array (
    0 =>
    array (
      'env_id' => '1',
      'env_name' => 'Production',
      'file_name' => 'test.login',
      'ws_name' => 'WebService',
      'line' => 'WebService.security=on',
    ),
  )
)

Now everything is inside the single 0 sub-array. The biggest problem I see with this is that I have concocted a custom query that breaks any CakePHP naming conventions. My controller and other data consuming components now rely on KNOWING these specific columns from this query. However, it is a large query that generates a lot more data than has been shown in these examples. Therefore, I think it is more efficient and memory-saving than the CakePHP natural methods or even a basic custom query like the original custom query above.

 
© 2010 FuGeRTech Suffusion theme by Sayontan Sinha