Как сравнить два массива и список различий в PHP?

Я создаю форму, чтобы сделать следующее:

  • Распечатайте таблицу пользователей и разрешений, вытаскивая из MySQL. Каждое разрешение пользователя имеет флажок, и каждому из них не хватает флажка.
  • Разрешить администратору проверять и снимать флажки для предоставления или удаления разрешений.
  • Когда форма отправлена, покажите страницу подтверждения с ТОЛЬКО пользователями, разрешения которых будут изменены, выделив конкретные изменения.
  • Когда изменения будут подтверждены, соответствующим образом измените базу данных.

Для этого я создаю два массива пользовательских разрешений: один в соответствии с тем, что показывает база данных, и одно в соответствии с тем, что показывает форма.

Если у пользователя нет разрешения в MySQL, он будет показан как 0. Если у них нет разрешения в представлении формы, его просто не будет.

Вот два простых примера массивов:

Массив базы данных

 [User1] => Array ([public] => 1
                 [частный] => 1
                 [секрет] => 1
                ) 
 [User2] => Array ([public] => 1
                 [частный] => 0
                 [секрет] => 0
                )

Массив представления формы (аннулирование «секретного» из User1 и предоставление его пользователю2)

 [User1] => Array ([public] => 1
                 [частный] => 1 
                )

 [User2] => Array ([public] => 1
                   [секрет] => 1
                  )

Вопрос

Как я могу элегантно объединить эти два массива, чтобы создать массив «changes», например:

  • Пользователи с одинаковыми разрешениями в обоих случаях опущены
  • Остальные пользователи имеют все разрешения – публичные, частные и секретные – установлены либо 0, либо 1.
  • Каждое разрешение равно 0, если оно отсутствовало в массиве представления формы, и 1, если оно было в массиве представления формы

Например, объединение вышеизложенного даст:

 [User1] => Array ([public] => 1
                 [частный] => 1
                 [секрет] => 0
                ) 
 [User2] => Array ([public] => 1
                 [частный] => 0
                 [секрет] => 1
                )

Попытки до сих пор

  • В качестве первого шага я попытался использовать array_merge (), в котором был указан второй массив форм, считая, что он перезапишет массив баз данных, в котором они отличались. Вместо этого он удалял элементы, которые отличались.
  • Я попытался настроить инструкцию foreach () для сравнения двух массивов, но это осложняется, и я думаю, что должен быть более простой способ

ОБНОВИТЬ

Уф! Новый ответ обратил мое внимание на этот старый вопрос. Я получил эту работу, но позже я отказался от этого сумасшедшего кода – это было слишком сложно, чтобы вернуться и работать. Вместо этого, я написал скрипт назад для PHP, чтобы изменить одно разрешение за раз, а затем написал AJAX-интерфейс для отправки изменений по нему. Гораздо более простой код, и изменения мгновенно для пользователя. Эффект подсветки дает мгновенную обратную связь о том, что изменилось.

Это может быть то, что вы ищете: array_diff ()

Вы можете найти то, что вам нужно, обратившись к руководству PHP: Arrays . Вы достаточно хорошо документировали вопрос, но я все еще не могу четко разобраться, что вам нужно.

В частности, вы должны смотреть на использование array_diff () и array_intersect (), чтобы вычислить разницу или пересечение двух массивов.

Почтовые данные содержат только разрешения, которые вы должны предоставить. Итак, настройте «базовый уровень» со всеми разрешениями, установленными в 0. Затем объединитесь с представлением.

$empty_perms = array("public" => 0, "private" => 0, "secret" => 0); $new_user1_perms = array_merge($empty_perms, $_POST['User1']); $new_user2_perms = array_merge($empty_perms, $_POST['User2']); 

Теперь обновите базу данных, используя объединенные массивы. Таким образом вы установите правильные разрешения для всех элементов.

Попробуем объединить решение gnud со сравнением по значению. Я добавил еще одного ключевого «члена», чтобы показать, что нулевое разрешение остается неизменным.

 // empty permissions $empty_perms = array("public" => 0, "private" => 0, "secret" => 0, "member" => 0); // original permissions (please note that it MUST contain ALL keys) $old_perms = array("public" => 1, "private" => 0, "secret" => 1, "member" => 0); // POST data container $post_data = array("public" => 1, "private" => 1); // apply new user permissions - put them into db $new_perms = array_merge($empty_perms, $post_data); // differences to show $diff_perms = array(); // compare new and old permissions foreach($empty_perms as $k => $v) { $diff_perms[$k] = (int)($old_perms[$k] !== $new_perms[$k]); } 

Этот пример должен дать вам следующие результаты (старые, новые, изменения):

 Array ( [public] => 1 [private] => 0 [secret] => 1 [member] => 0 ) Array ( [public] => 1 [private] => 1 [secret] => 0 [member] => 0 ) Array ( [public] => 0 [private] => 1 [secret] => 1 [member] => 0 ) 

Надеюсь это поможет.

Интересно, поможет ли какая-то вариация дифференциального исполнения .

Для использования array_diff() первым аргументом должен быть надмножество или большее из двух массивов. Чтобы использовать array_diff() когда вы не уверены, какой массив больше:

  //start with the superset of for array_diff to return differences if(count($prev_wholesaler_assignments) > count($wholesalers)){ $perm_diff = array_diff($prev_wholesaler_assignments,$wholesalers); } elseif (count($prev_wholesaler_assignments) < count($wholesalers)){ $perm_diff = array_diff($wholesalers,$prev_wholesaler_assignments); } 

Это возвращает дизъюнкцию, независимо от того, какой массив окажется больше.