Я использую CakePHP версии 2.X
Каждый раз, когда я прихожу, чтобы сделать это в проекте, я всегда трачу часы на то, чтобы понять, как это сделать, используя поведение поиска CakeDC, поэтому я написал это, чтобы попытаться напомнить себе простым языком, что мне нужно делать. Я также заметил, что, хотя Майкл в целом прав, нет объяснения, которое затрудняет его модификацию для собственного проекта.
Когда у вас есть отношение «есть и принадлежит многим», и вы хотите найти объединяющуюся таблицу, то есть таблицу, в которой есть два поля, объединяющие таблицы по обе стороны от нее во множество-ко-многим. Во многих отношениях вы хотите создать подзапрос со списком идентификаторов из одной из таблиц в связи. Идентификаторы из таблицы на другой стороне отношения будут проверены, чтобы увидеть, есть ли они в этой записи, и если они есть, то будет выбрана запись в основной таблице.
В следующем примере
SELECT Handover.id, Handover.title, Handover.description
FROM handovers AS Handover
WHERE Handover.id in
(SELECT ArosHandover.handover_id
FROM aros_handovers AS ArosHandover
WHERE ArosHandover.aro_id IN (3) AND ArosHandover.deleted != '1')
LIMIT 20
все записи из ArosHandover будут выбраны, если их значение aro_id равно 3, тогда Handover.id используется для определения, какие записи хэндовера выбрать.
О том, как это сделать с помощью поведения поиска CakeDC.
Сначала поместите поле в форму поиска:
echo $this->Form->create('Handover', array('class' => 'form-horizontal'));?>
echo $this->Form->input('aro_id', array('options' => $roles, 'multiple' => true, 'label' => __('For', true), 'div' => false, true));
и т.д ...
обратите внимание, что я не поместил элемент формы в пространство данных ArosHandover; Другой способ сказать, что при отправке запроса формы поле aro_id будет помещено в массив с именем Handover.
В модели под переменной $ filterArgs:
'aro_id' => array('name' => 'aro_id', 'type' => 'subquery', 'method' => 'findByAros', 'field' => 'Handover.id')
обратите внимание, что типом является «подзапрос», как я уже упоминал выше, вам нужно создать подзапрос, чтобы иметь возможность находить соответствующие записи, и, указав типу подзапрос, вы сообщаете CakeDC о создании фрагмента подзапроса SQL. Метод - это имя функции, под которой будет написан код. Элемент field - это имя поля, которое будет отображаться в этой части примера запроса выше
WHERE Handover.id in
Затем вы пишете функцию, которая будет возвращать подзапрос:
function findByAros($data = array())
{
$ids = ''; //you need to make a comma separated list of the aro_ids that are going to be checked
foreach($data['aro_id'] as $k => $v)
{
$ids .= $v . ', ';
}
if($ids != '')
{
$ids = rtrim($ids, ', ');
}
//you only need to have these two lines in if you have not already attached the behaviours in the ArosHandover model file
$this->ArosHandover->Behaviors->attach('Containable', array('autoFields' => false));
$this->ArosHandover->Behaviors->attach('Search.Searchable');
$query = $this->ArosHandover->getQuery('all',
array(
'conditions' => array('ArosHandover.aro_id IN (' . $ids . ')'),
'fields' => array('handover_id'), //the other field that you need to check against, it's the other side of the many-to-many relationship
'contain' => false //place this in if you just want to have the ArosHandover table data included
)
);
return $query;
}
В контроллере передачи обслуживания:
public $components = array('Search.Prg', 'Paginator'); //you can also place this into AppController
public $presetVars = true; //using $filterArgs in the model configuration
public $paginate = array(); //declare this so that you can change it
// this is the snippet of the search form processing
public function admin_find()
{
$this->set('title_for_layout','Find handovers');
$this->Prg->commonProcess();
if(isset($this->passedArgs) && !empty($this->passedArgs))
{//the following line passes the conditions into the Paginator component
$this->Paginator->settings = array('conditions' => $this->Handover->parseCriteria($this->passedArgs));
$handovers = $this->Paginator->paginate(); // this gets the data
$this->set('handovers', $handovers); // this passes it to the template
Если вам нужно какое-либо дальнейшее объяснение того, почему я что-то сделал, спросите, и если я получу электронное письмо с просьбой сообщить, что вы спрашивали, я дам ответ, если смогу.