Использование поискового плагина CakeDC со связанными моделями - PullRequest
0 голосов
/ 13 мая 2011

Я использую CakePHP 1.3.8, и я установил Плагин CakeDC Search .У меня есть модель Tutorial, которая находится в отношениях HABTM с моделью LearningGoal.

У меня есть действие поиска и представление в контроллере Tutorials, с помощью которого я могу успешно искать поля в модели Tutorial.Я также хотел бы отфильтровать результаты поиска по учебнику, используя флажки LearningGoal в той же форме.Я попытался добавить различные параметры в $ filterArgs Tutorial и $ presetVars TutorialsController.Я также попытался переместить соответствующие $ filterArgs в модель LearningGoal.Я пока не смог успешно запустить запись для целей обучения в $ filterArgs.

Думаю, мне не хватает чего-то очевидного.Или, возможно, плагин Search не поддерживает то, что я пытаюсь сделать.Кто-нибудь знает, как использовать этот плагин для поиска на связанных моделях?

Ответы [ 2 ]

0 голосов
/ 26 февраля 2014

Я использую 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

Если вам нужно какое-либо дальнейшее объяснение того, почему я что-то сделал, спросите, и если я получу электронное письмо с просьбой сообщить, что вы спрашивали, я дам ответ, если смогу.

0 голосов
/ 02 июня 2011

Итак, вот что я понял. Вы можете комбинировать то, что ниже, с инструкциями плагина поиска для поиска по связанным моделям.

Часть $ filterArgs в модели Tutorial должна выглядеть следующим образом:

var $filterArgs = array(
  array('name' => 'LearningGoal', 'type' => 'subquery', 'method' => 'findByLearningGoals', 'field' => 'Tutorial.id'),
);

Вот вспомогательная функция в модели Tutorial:

function findByLearningGoals($data = array()) {
  $ids = explode('|', $data['LearningGoal']);
  $ids = join(',', $ids);
  $this->LearningGoalsTutorial->Behaviors->attach('Containable', array('autoFields' => false));
  $this->LearningGoalsTutorial->Behaviors->attach('Search.Searchable');

  $query = $this->LearningGoalsTutorial->getQuery('all',
     array(
       'conditions' => array('LearningGoalsTutorial.learning_goal_id IN (' . $ids . ')'),
       'fields' => array('tutorial_id'),
     )
  );
  return $query;
}

В TutorialsController $ presetVars должен выглядеть следующим образом:

public $presetVars = array(
  array('field' => 'LearningGoal', 'type' => 'checkbox', 'model' => 'Tutorial'),
);

И в своем поисковом действии в TutorialsController я сделал это:

$this->LearningGoal = $this->Tutorial->LearningGoal;

Компонент Prg, похоже, нуждается в этом.

...