#php
#php
Вопрос:
Когда я перебираю массив массивов с foreach
помощью, я могу напрямую перейти к следующему измерению, используя list()
ключевое слово (или сокращенную []
нотацию), например:
$array_num = [
[1, 2, 3],
[4, 5, 6],
];
foreach ($array_num as [$deep_value]) {
echo $deep_value, ' ';
}
// prints: 1 4
$array_assoc = [
['foo' => 1, 'bar' => 2, 'baz' => 3],
['foo' => 4, 'bar' => 5, 'baz' => 6],
];
foreach ($array_assoc as ['baz' => $deep_value]) {
echo $deep_value, ' ';
}
// prints: 3 6
Существует ли аналогичная концепция для массивов объектов?
class Example {
public $foo;
public function __construct(int $number = 1) {
$this->foo = $number;
}
}
$array_obj = [
new Example,
new Example(4),
];
foreach ($array_obj as foo<-$object) { // obviously wrong
echo $object, ' ';
}
Вариант использования точно такой же, как и в начальной функции (распаковка вложенных массивов в переменные). Одним из примеров может быть доступ к большому количеству свойств в объекте:
foreach ($array_assoc as ['foo' => $foo, 'bar' => $bar, 'baz' => $baz]) {
$speed = $baz / $foo / $bar;
echo "The $foo horses ate $baz apples in the last $bar hours.n";
echo "That's $speed apples per horse per hour!nn";
}
который масштабируется в порядке (2) x (сумма длин имен свойств).
против.
foreach ($array_obj as $object) {
$speed = $object->baz / $object->foo / $object->bar;
echo "The {$object->$foo} horses ate {$object->$baz} apples in the last {$object->$bar} hours.n";
echo "That's $speed apples per horse per hour!nn";
}
который масштабируется в порядке (длина имени переменной объекта) x (количество использований в цикле).
или
foreach ($array_obj as $object) {
[$foo, $bar, $baz] = [$object->foo, $object->bar, $object->baz];
$speed = $baz / $foo / $bar;
echo "The $foo horses ate $baz apples in the last $bar hours.n";
echo "That's $speed apples per horse per hour!nn";
}
который масштабируется в порядке (длина имени переменной объекта) x (сумма длин имен свойств).
При небольших циклах или небольшом количестве свойств это не имеет большого значения. С увеличением длины имен переменных и использования в циклах последние два метода быстро становятся значительно более подробными и более трудными для чтения. Итог, я либо
- дайте моему объекту безответственно короткое имя,
- спамить мой цикл с
$object->
помощью, или - извлеките все свойства объекта в начале цикла довольно подробным способом, что делает назначение объектной переменной устаревшим в первой строке цикла.
Ни то, ни другое не способствует удобочитаемому и поддерживаемому коду. Определение прямо в цикле, какие свойства я хочу, как это можно сделать с массивами, позволило бы мне использовать разумные имена переменных, пропускать ссылки на объекты во всем моем цикле и назначать только столько переменных, сколько мне действительно нужно. По сути, он превращает foreach
операторы в эквиваленты операторов функций, которые вызываются несколько раз и сохраняют текущую область видимости.
Комментарии:
1. Я не уверен, какой результат вы ожидаете, и почему
echo $object, ' ';
недостаточно изменить intoecho $object->foo, ' ';
. Вы хотите получить «первое свойство» объектов из разных классов?2. Это упрощенный пример, вариант использования точно такой же, как и в версии массива / списка. Например, если я извлекаю кучу свойств и нуждаюсь в них в своих собственных переменных, чтобы я мог их изменять или часто использовать, не обращаясь каждый раз к объекту, написание 10 строк
$varX = $object->propertyX
довольно громоздко и многословно. Я хотел бы иметь возможность просто распаковать их так же, как я мог бы, сначала преобразовав объект в массив.
Ответ №1:
Возможно, что отсутствует важная часть головоломки, но, поскольку вопрос стоит прямо сейчас, я не вижу причины, по которой этот фрагмент не будет делать то, что вы ожидаете:
class Example {
public $foo;
public function __construct(int $number = 1) {
$this->foo = $number;
}
}
$array = [
new Example,
new Example(4),
];
foreach ($array as $object) {
echo $object->foo, ' ';
}
// prints: 1 4
Комментарии:
1. Вопрос не в поведении, этот фрагмент делает то, что я ожидаю, точно так же, как
echo $subarray[0]
илиecho $subarray['baz']
сделал бы то же самое в моих первых 2 примерах. Разница между 2 соответствующими версиями заключается не в том, что они делают, а в том, насколько они подробны, что влияет на то, насколько хорошо / быстро они могут быть написаны, прочитаны, поняты и поддержаны. Представьте себе этот пример не только с одним echo для одного свойства, но и с 20 операциями над 7 свойствами. Добавление дополнительногоobject->
каждый раз быстро раздувает код. Я добавил подробное описание варианта использования к вопросу.