2013-11-11 2 views
2

Я нашел странную проблему с использованием CakePHP 1.3 для поиска информации. Давайте использовать этот dbschema в качестве примера:CakePHP, переопределяющий идентичное поле в условиях поиска

идентификатор INT (11) ОСНОВНОЙ auto_increment сумма поплавок (10,2) NULL статус ENUM (завершено, убрано, Pending)

id amount status 
1 100.00 Completed 
2 100.00 Removed 
3 100.00 Completed 
4 100.00 Completed 
5 100.00 Pending 

При использовании торта find для извлечения данных из этой таблицы, я использую этот запрос:

$this->Testtable->find('all', array(
    'conditions' => array(
     'status LIKE ' => 'Removed', 
     'status LIKE ' => 'Pending', 
     'status LIKE ' => 'Completed' 
    ) 
)) 

Глядя на этот запрос, я бы предположить, что торт будет возвращать все строки, м atch все этих условий (что вполне приемлемо в SQL), однако оно использует только последнее условие и возвращает WHERE status LIKE 'Completed'.

Я провел тест, делая это, что возвращаемый все строки правильно (я знаю, что это более «правильный» способ сделать запрос в любом случае):

'conditions' => array(
    'status' => array('Removed', 'Pending', 'Completed')   
) 

Возьмите противоположность для примера, я хочу возвращает все строки, которые не Удалены или в ожидании:

'conditions' => array(
    'status !=' => 'Removed', 
    'status !=' => 'Pending' 
) 

Этот запрос возвращает все строки с Завершенный и Удален, поскольку он слушает только последнее утверждение. Я предполагаю, что это происходит, потому что вместо объединения этих условий поиска в запрос Cake перезаписывает условия, основанные на «поле», которое составляет status !=. Я могу доказать эту теорию, добавив пространство после != в любом из этих условий, создав желаемый результат только подтвержденных записей.

Может ли кто-нибудь сказать мне, почему Cake сделает это? Поскольку это законное дело в SQL, я не вижу причин, по которым Cake не позволит вам это сделать. Кто-нибудь знает, исправлена ​​ли эта проблема в новых версиях Cake?

ответ

1

Я полагаю, что это сводится к тому, что в конце дня я переписываю значение массива на основе этого ключа, и это вовсе не ошибка CakePHP. Я посмотрел в торта model.php и нашел это:

$query = array_merge(compact('conditions', 'fields', 'order', 'recursive'), array('limit' => 1)); 

Я побежал тест:

$array = array(
'conditions' => array(
    'test' => 'yes', 
    'test' => 'no' 
) 
); 

$var = 'hello'; 
$c = compact('array', 'var'); 
print_r($c); 

Как уже упоминалось выше, compact только получение значения no из ключа test. Я предположил, что использование compact для объединения переменных/массивов в запрос рекурсивно объединит аналогичные ключи из массива условий в последнее заданное, но оказывается, что yes даже не делает это настолько далеко, насколько он переопределяется на месте ,

Я полагаю, что это ограничение PHP, а не Cake, но это все же то, что мне не приходило, и должно быть сделано по-другому (если это еще не так) в будущем.

Редактировать

Я пробежал еще пару тестов. Я обернул идентичные условия в своих собственных массивах, а затем сравнил их с тем, как будут работать функции Cake. Используя compact (что делает Cake), массивы, содержащие идентичные ключи, остаются нетронутыми, однако с использованием array_merge первый ключ перезаписывается вторым. Я думаю, в этом случае очень, очень хорошо, что Cake использует compact вместо array_merge, чтобы объединить критерии запроса.

$array = array(
    array('test' => 'yes'), 
    array('test' => 'no') 
); 

$m = array_merge($array[0], $array[1]); 
$c = compact('array'); 

print_r($c); 
print_r($m); 

Результат:

Array 
(
    [array] => Array 
     (
      [0] => Array 
       (
        [test] => yes 
       ) 

      [1] => Array 
       (
        [test] => no 
       ) 

     ) 

) 
Array 
(
    [test] => no 
) 

Хотя это, очевидно, просто проблема в том, как вы принципиально писать PHP-код, это не было по сути очевидным при написании в Cake синтаксисом, что условия будут перезаписаны друг друга. ..

+0

+1 для устранения собственной проблемы и открытия/дезогнорирования простейшего решения (условия обертывания в другом массиве). Обратите внимание, что при использовании 'LIKE' - если это не шаблон' LIKE', это не лучший выбор для использования =). – AD7six

1

Basic PHP: не используйте один и тот же ключ массива дважды

'conditions' => array(
    'status LIKE ' => 'Removed', 
    'status LIKE ' => 'Pending', 
    'status LIKE ' => 'Completed' 
) 

должно быть

'conditions' => array(
    'status LIKE' => array('Removed', 'Pending', 'Completed'), 
) 

То же самое для любого другого ключа массива.

Обратите внимание, что некоторая быстрая отладка массива показывает это. Просьба также увидеть множество других вопросов, связанных с stackoverflow, с той же проблемой или другими областями, в которых базовые исследования могли бы указать вам в этом направлении. Взглянув на них, сначала можно решить проблему за меньшее время.

+0

Ну, некоторая быстрая отладка вернула бы этот результат. Кроме того, некоторые быстрые исследования, так как 1000 вопросов здесь также указывают то же самое. От менее опытных разработчиков обычно. Так что это не то, что личное, но утверждает, что исследований недостаточно, прежде чем публиковать. – mark

+0

Я знаю, что вы сказали в своем посте, и я тоже это сказал. Я считаю, что это недостаток в том, как CakePHP работает фундаментально, полагаясь на массивы PHP, чтобы передавать параметры (не позволяя вам делать то, что вы можете делать в SQL без пота) –

Смежные вопросы