Переводите изначальный массив в плоский, содержащий все одиночные значения с добавленным флагом check
$paramsFlat = [
['value' => ['option1' => 1], 'check' => 0],
['value' => ['option1' => 2], 'check' => 0],
...
['value' => ['option3' => 2], 'check' => 0],
];
Теперь все что вам нужно - в цикле получить все варианты с check, алгоритмически проще всего это сделать, представив двоичное число с количеством разрядов равное количеству элементов:
в вашем примере таковых 9, то есть:
000000001
000000010
000000011
000000100
..
111111111
Соответственно алгоритм на каждом шаге такой - ищем в $paramsFlat первый элемент с check === 0, меняем его на единицу, а свойство check всех элементов до него обнуляем
После каждого шага включаете в очередной элемент итогового массива $result только элементы $paramsFlat с check === 1
Функция получения следующего элемента может выглядеть примерно так (не тестировал и не оптимизировал, но смысл полагаю ясен)
function getNext($paramsFlat) {
foreach($paramsFlat as &$elem) {
// Инвертируем значения до первого найденного нуля
if($elem['checked'] = !$elem['checked']) break;
}
// Получаем массив, содержащий отмеченные элементы
$retVal = array_filter($paramsFlat, function($v) {return $v['checked'];});
if(!count($retVal)) return false;
// Возвращаем массив из значений отмеченных элементов
return array_map(function($v) {return $v['value'];}, $paramsFlat);
}