Разбиране на обекти на 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, надявам се на връзка към правилната страница в документацията, както и да посоча всички грешки в моята формулировка/терминология по-горе.


РЕДАКТИРАНЕ:

Този отговор съдържа действителния код, който използвах, за да реша проблема си. Въпреки това отговорът на Yagi беше приет, защото ме насочи в правилната посока.


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

Благодарение на отговора на Yagi, стигнах до следното много просто решение. Преминавам през масива и присвоявам стойността на 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