Pre-program parameters to be removed from an object

Asked

Viewed 39 times

0

I’m making an application, I wonder 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 get information coming from a relationship, the above code illustrates all the lines taken from the table councils and has a relation (belongsTo, de laravel) with the district table. That is, I cannot access the property district->name (third column) but I can access name and to the id

I’ve tried with $item->{$value['obj_param']} but it doesn’t work either. I wanted to avoid using eval() as much as possible

  • Are you trying to access the array within the array? is that it? If you try to put "$item->$value['id']['obj_param'];" for example

1 answer

1


The way you’re doing it doesn’t look good. Always think that when you fall into complicated situations where you’re going to have to solve with coarse whims, it’s because there’s something wrong with logic. So review the logic.

But if you want to continue, just try to understand how these examples work:

/*
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 in the previous example with array, so it does 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 can 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 without complicating so much, but still doing gambiarra is if you are sure of the depth limit of the object keys.

If you have only 2, it is very easy because a simple explode() already solves half 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

  1. Use Eval()
    OMG in the!

  2. Reduce an array/object iteratively as above examples
    It’s more than a whim, it’s a complication.

  3. Rewriting a new logic
    Recommended!

  • allITems is an array of objects (Rows) from the Database, doing so will not give, I think is complicating a little

  • Obviously, as I described. The way you set up the logic you can only solve with a huge complication. That is why I recommend reviewing the logic, especially of the data returning from $model::all();.

  • Thanks, I’ll do the recommended then

Browser other questions tagged

You are not signed in. Login or sign up in order to post.