cakephp search criteria using related models
I'm having an ongoing issue with dealing with getting lists of items based on search criteria on different but related tables. I need to have a clear idea of how to deal with this type of situation. Here is my simplest example:
if I have an Agency Model (using a table called referral with a primary key of r_num and an Agent Model using a table called agents, the agents table contains a foreign key of r_num linking to the Agencies, The agency can have many Agents:
Table: referral
r_num int -- primary key auto incremented
r_company varchar(50) -- the name of the agency
... other fields don't matter
Table: agents
a_num int -- primary key auto incremented
r_num int -- foreign key to the referral table
a_lname varchar(50) -- agent's last name
a_fname varchar(50) -- agent's first name
a_email varchar(50) -- agent's email
Models:
class Agency extends AppModel {
var $name = 'Agency';
var $useTable = 'referral';
var $primaryKey = 'r_num';
var $hasMany = array(
'Agent' => array(
'className' => 'Agent',
'foreignKey' => 'r_num',
'order' => 'Agent.a_lname DESC',
'dependent'=> true
)
);
}
class Agent extends AppModel {
var $name = 'Agent';
var $primaryKey = 'a_num';
}
All I want is to return a list using $this->Agency->find('all') using conditions from a search form, which includes agent first name, agent last name, agent email. I need a list of Agency company names and ids but the search criteria is based on the agents. I have several different models that will use this, so I need documentation on how this can work. What I've tried based on what I've found online is this in the AgencyController which works but it is a hack that won't w开发者_开发问答ork on some of my more complicated cases: I need to do this without making multiple calls, since some of my tables will return huge numbers of rows, and using this technique on those queries takes several minutes.
class AgenciesController extends AppController {
var $helpers = array ('Html','Javascript', 'Form', 'Paginator', 'Ajax', 'Phoneformat');
var $name = 'Agencies';
var $components = array('RequestHandler', 'RentalValidation');
var $uses = array('Agency', 'Agent');
function index() {
$criteria = $this->postConditions($this->data);
if (empty($criteria)){
$arrArgs = $this->passedArgs;
unset($arrArgs['page']);
$criteria = $arrArgs;
}
$searchcriteria = array();
foreach (array('Agency.r_state', 'Agency.r_company') as $item ) {
$itemvalue = '';
if (isset($criteria[$item])){
$itemvalue = $criteria[ $item];
if (!empty($itemvalue)) {
$searchcriteria[$item . " LIKE "] = '%' . $itemvalue .'%';
}
}
}
foreach (array('Agent.a_lname', 'Agent.a_email') as $item ) {
$itemvalue = '';
if (isset($criteria[$item])){
$itemvalue = $criteria[ $item];
if (!empty($itemvalue)) {
$agent_rnums = $this->Agent->find('list',
array('conditions' =>
array($item . " LIKE " => '%'. $itemvalue .'%'),
'fields' => 'Agent.r_num'));
$searchcriteria['r_num'] = $agent_rnums;
}
}
}
$this->set('passedCriteria', $criteria);
$data = $this->paginate('Agency', $searchcriteria);
if (count($data) == 1) {
$referralid = $data[0]['Agency']['id'];
$this->redirect(array('action' => 'edit', $referralid));
}
$this->set('agencies', $data);
}
}
Couldn't you do it the other way?
- Get all Agents matching the desired conditions
- do a Set::combine to get the agency_ids (and have it uniquified)
- do query with IN agency_ids
that way there would be only 2 sql calls
精彩评论