Понимание объектов CodeIgniter и многомерных массивов

Я работаю над проектом в CodeIgniter 2, и теперь я застрял на самых основных концепциях.

Модель:

Получите массив объектов из моей таблицы, который содержит все строки, соответствующие определенному значению для поля с именем foo. Может быть одна или несколько совпадающих строк. В данном примере две строки.

public function get_sample($foo)
{
    $query = $this->db->get_where('sample_db', array('foo' => $foo));

    return $query->result();
}

Контроллер:

Назначьте результаты и сделайте выходные данные доступными для просмотра.

public function view($foo)
{
    $data['array'] = $this->sample_model->get_sample($foo);

    $this->load->view('view', $data);
}

Просмотр:

echo var_dump($array); // for testing

echo $array[1]->text

var_dump() из $array:

array(2) {
    [0]=> object(stdClass)#23 (4) {
        ["id"]=> string(1) "1"
        ["foo"]=> string(3) "bar"
        ["number"]=> string(4) "1234"
        ["text"]=> string(23) "This is content in 1234"
    }
    [1]=> object(stdClass)#24 (4) {
        ["id"]=> string(1) "2"
        ["foo"]=> string(3) "bar"
        ["number"]=> string(4) "9999"
        ["text"]=> string(23) "This is content in 9999"
    } 
} 

Визуализированный вывод echo $array[1]->text;: This is content in 9999

И я понимаю, как все это работает: $array[1]->text — это содержимое поля text в объекте-массиве с индексом 1, мой второй объект.

Однако у меня есть поле с именем number, и я хочу получить доступ к объекту с определенным number и получить соответствующее значение text.

Пример. Как получить значение text, где number равно 9999? Я не могу использовать $array[1]->text, так как никогда не могу быть уверен в позиции объекта в массиве. Что-то вроде $array['number' => '9999']->text, но я знаю, что это неправильно. Может быть, мне нужно перебрать массив в поисках совпадения?

Это выглядит так просто, но все, что я пробовал, потерпело неудачу и привело к различным ошибкам PHP. Я изучал руководство по PHP здесь и здесь, но не могу найти ничего о том, что я хочу сделать, или может быть, я просто неправильно применяю то, что читаю. Любое руководство приветствуется.

В дополнение к ответу с использованием лучших практик в соответствии с моделью MVC, я надеюсь получить ссылку на соответствующую страницу в документации, а также указать на любые ошибки в моей формулировке/терминологии выше.


ИЗМЕНИТЬ:

Этот ответ содержит фактический код, который я использовал для решения своей проблемы. Хотя ответ Яги был принят, потому что он направил меня в правильном направлении.


person Sparky    schedule 16.12.2012    source источник


Ответы (3)


Как насчет использования этого:

foreach ($array as $row) {
        if ($row->number == '9999') {
            echo $row->text;
        }
    }

Прокрутите массив и найдите значение числового объекта 9999 и получите текст

person Yagi    schedule 16.12.2012

возможно, вы ищете что-то вроде этого...

array_filter($array, function($o){ return $o->number == 9999; } );

http://php.net/manual/en/function.array-filter.php

ИЗМЕНИТЬ

$o — это параметр функции обратного вызова. каждый элемент массива передается функции обратного вызова. если функция возвращает false, элемент будет отфильтрован.

$arr = array(
    (object) array(
        'num' => 33,
        'text' => 'hello',
    ),
    (object) array(
        'num' => 44,
        'text' => 'world',
    ),
);
$filtered = array_filter($arr, function($o){ return $o->num == 33; });
echo $filtered[0]->text; // hello

как вы сказали, индекс останется, поэтому используйте array_values ​​или array_shift. вот пример с функцией

function get_by_num($arr, $num){
    return array_shift(array_filter($arr, function($o) use ($num) { return $o->num == $num; }));
}
$obj = get_by_num($arr, 44);
var_dump($obj);
// object(stdClass)#2 (2) { ["num"]=> int(44) ["text"]=> string(5) "world" }

в этом случае $obj будет либо NULL, если элемент не найден, либо первым совпадением. $num передается вместе, поэтому вы можете использовать любое значение. вы даже можете улучшить его:

function get_first_match($arr, $field, $val){
    return array_shift(array_filter($arr, function($o) use ($field, $val) { return $o->{$field} == $val; }));
}
$obj = get_first_match($arr, 'num', 44);

и теперь вы можете искать в любом поле. в твоем случае

$obj = get_first_match($array, 'number', 9999);
person galchen    schedule 16.12.2012
comment
echo $filtered[0]->text; выдает Undefined offset: 0 ошибку. - person Sparky; 16.12.2012
comment
тогда вы, должно быть, сделали что-то не так... код в порядке, если элемент найден. если он не найден, $filtered будет пустым, и вы получите предупреждение. в нашем случае работает - person galchen; 16.12.2012
comment
var_dump($filtered) возвращает массив, содержащий один объект array(1) { [1]=> object(stdClass)#24.... Так что на самом деле echo $filtered[1]->text работает, но это возвращает меня к исходной точке, поскольку это тот же самый индекс, который я использовал в своем исходном примере. - person Sparky; 16.12.2012
comment
запустите на нем array_values, я добавлю его внизу - person galchen; 16.12.2012

Благодаря ответу Яги я нашел следующее очень простое решение. Я перебираю массив и присваиваю значение text новому массиву с индексом, соответствующим значению number. Затем в файле представления я могу получить доступ к значению text на основе этого индекса.

Контроллер:

public function view($foo)
{
    $data['array'] = $this->sample_model->get_sample($foo);

    foreach ($data['array'] as $row) {
        $data['result'][$row->number] = $row->text;
    };

    $this->load->view('view', $data);
}

Просмотр:

if (isset($result[9999])) echo $result[9999];
person Sparky    schedule 16.12.2012