Pre program parameters to be removed from an object

0

I am making an application, I would like to know if php has any way to preprogram the properties to remove from an object:

EX:

$_datatableCollumns = array(
    'id' => array(
        'name' => 'ID',
        'obj_param' => 'id',
    ),
    'name' => array(
        'name' => 'Name',
        'obj_param' => 'name',
    ),
    'district' => array(
        'name' => 'District',
        'obj_param' => 'district->name',
    ),
);

...

$allItems = $model::all(); // retorna um array de objectos vindo da DB
$allRows = array();
foreach ($allItems as $key => $item) {
   foreach ($this->_datatableCollumns as $column => $value) {
       $allRows[$key][$column] = $item->$value['obj_param'];
   }        
}

The problem arises when I try to remove information from a relation, the code above illustrates all the rows taken from the county table and has a (belongsTo, de laravel) relation with the district table. That is, I can not access the property district->name (third column) but I can access name and id

I have tried with $item->{$value['obj_param']} but it also does not work. I wanted to avoid using eval() as much as possible

    
asked by anonymous 08.04.2016 / 16:57

1 answer

1

The way you're doing does not look good. Always think that when you fall into complicated situations where you will have to deal with gross gambiarras, it is because there is something wrong in the logic. So, review the logic.

But if you want to continue, just try to understand the operation of these examples:

/*
Não sei qual a estrutura que retorna de $allItems = $model::all();
então fiz uma estrutura simples com array. Eu sei que retorna como stdclass (objeto), mas aqui quero mostrar um exemplo com array. Mais para frente você entenderá o motivo:
*/
$item = array(
    'foo' => array(
        'bar' => 'ok'
    )
);

/*
Esse aqui seria o trecho 'obj_param' => 'district->name'
*/
$param = 'foo->bar';

/*
A lógica para montagem começa aqui. Vamos explodir num array.
*/
if (strpos($param, '->')) {

    $arr = explode('->', $param);

    /*
    Então aplicamos a função array_reduce() para chegar ao valor de $item['foo']['bar'] a partir de uma string "foo->bar"
    */
    $rs = array_reduce(
        explode('->', $param),
        function ($x, $key) {
            if (isset($x[$key])) {
                return $x[$key];
            } else {
                return null;
            }
        },
        $item
    );

    /*
    Resulta em
    string(2) "ok"
    */
    var_dump($rs);


}

Example with stdclass object

The logic is the same as the previous example with array, so I did not include comments:

$item = (object)array(
    'foo' => (object)array(
        'bar' => 'ok'
    )
);

$param = 'foo->bar';

if (strpos($param, '->')) {

    $arr = explode('->', $param);

    /*
    Isso aqui faz um "array_reduce" de um objeto.
    */
    $rs = function($item) use (&$rs, &$arr) {
        foreach ($arr as $k => $v) {
            if (
                isset($item->$v)
                && is_object($item->$v)
            ) {
                unset($arr[$k]);
                $item = $rs($item->{$v});
            } else {
                unset($arr[$k]);
                return $item;
            }
        }
        return current($item);
    };

    /*
    Mostra o resultado
    */
    var_dump($rs($item));

}

Both examples were created considering that you could use N produndity. Example:

$param = 'foo->bar->bar2->bar3->bar4';
$param = 'foo->bar->bar2';
$param = 'foo->bar->bar->bar';
$param = 'foo->bar';

Simple example, with static depth

Another way to solve it without complicating it so much, but still doing it is if you are sure of the depth limit of the object's keys.

If you only have 2, it is quite easy because a simple explode () already solves half of the problem:

$item = (object)array(
    'foo' => (object)array(
        'bar' => 'ok'
    )
);

$param = 'foo->bar';

if (strpos($param, '->')) {
    $arr = explode('->', $param);
    var_dump($item->$arr[0]->$arr[1]);
}

Of course you need to use isset($item->$arr[0]) before you want to invoke $item->$arr[0]->alguma_coisa . In this example I refrain from creating consistency checks to simplify teaching.

Summary

You have 3 paths

  • Use eval ()
    OMG no!

  • Reducing an array / object iteratively according to the examples above It is more than a gambiarra, it is a complication.

  • Rewrite a new logic
    Recommended!

  • 08.04.2016 / 18:25