Если перестановки не нужны, то все просто. Каждый элемент либо входит в следующий вариант, либо нет. Соответственно делаете цикл 1 до pow(2, count($arr)). Преобразовываете каждое число цикла в двоичное встроенной функцией decbin, переворачиваете результат, и по нему составляете новый вариант - если 1 на соответствующем месте возвращенной decbin строки, то включаете элемент, если 0, то исключаете.
$arr = [0 => 'a', 1 => 'b', 2 => 'c'];
$res = [];
for ($i = 1; $i < pow(2, count($arr)); $i++ ) {
$bin = decbin($i);
$case = "";
foreach(str_split(strrev($bin)) as $ind => $symb) if ($symb == "1") $case .= $arr[$ind];
$res[] = $case;
}
echo implode(", ", $res); // a, b, ab, c, ac, bc, abc