PHP: elements with and without explicit keys in the same array

Asked

Viewed 426 times

5

I’m trying to figure out a better or cleaner way to do something like this in PHP:

// Isto será passado como argumento de uma função...
$params = array('Nome', 'Idade', 'Mail' => '[email protected]');

"Name" and "Age" are values with automatically assigned keys (0 and 1, for example), and "Mail" is a key with the value "[email protected]":

[0] => 'Nome',
[1] => 'Idade',
['Mail'] => '[email protected]'

When I run this through a "foreach" loop, I’m doing this to have "Name" and "Age" as the actual parameters:

foreach ($params as $k => $i) {

    // Esta é a parte "feia"!
    if (is_int($k)) {
        $k = $i;
        $i = false;
    }

    // Para fazer algo assim, por exemplo...
    $out = "";
    if ($i) {
        $out .= "<p><a href=\"mailto:$i\">$k</a></p>\n";
    } else {
        $out .= "<p>$k<p>\n";
    }

}

What will return something like this:

<p>Name</p>
<p>Age</p>
<p><a href="mailto:[email protected]">Mail</a></p>

The question is: is there a clear way for PHP to differentiate the elements of the same array that have an explicit key (Mail => [email protected]) from those that do not (Name and Age)?

Observing: the above code was divided into two steps to better understand the current solution, which is to differentiate the value of the key by testing whether it is an integer, but the code I’m actually using is:

$o = "";
foreach ($params as $k => $i) {
    if (!is_int($k)) {
        $o .= "<p><a href=\"$i\">$k</a></p>\n";
    } else {
        $o .= "<p>$i</p>\n";
    }
}
  • 1

    Wouldn’t it be more intuitive to have array('Nome'=>null, 'Idade'=>null, 'Mail' => '[email protected]')?

  • @bfavaretto Yes, if this procedure was not within a generic function to, for example, create rows from a table, where the tag "td" might or might not have additional parameters. The ideal would be: funcao_tal('name', 'age', array('mail' => '[email protected]')), but I don’t know if there is a way for PHP to understand that the amount of arguments in the function may vary. At the same time, passing the entire argument as a single string and slashing it afterwards would be equally dirty. Note also that I’m wanting to take advantage of the new format of PHP arrays>=3.4 "[elements]", for the sake of readability.

  • Don’t understand what you mean by dirty? Why not be dynamic? I see no problem in it, maybe it’s just your personal taste.

  • 2

    To capture the arguments: http://php.net/manual/en/function.func-get-args.php

  • @Marcelo Aymone, I just discovered this and in fact it is the solution. Thank you very much.

  • I’m glad this helped find the answer, hugging!

Show 1 more comment

2 answers

4


It would appear that the answer to the original question is indeed nay, there is no PHP way to differentiate elements with and without keys within the same array.

But, the original problem stemmed from the need to create a readable function where the amount of arguments passed could vary, hence the initial option for an array, which would allow such a call:

add_table_row(['Nome', 'Idade', 'Mail' => '[email protected]']);

or so...

add_table_row(array('Nome', 'Idade', 'Mail' => '[email protected]'));

However, as I just discovered, there is a way to pass a variable amount of arguments to a function, using the function "func_get_args()", and the function call can become even more readable:

// PHP >= 5.4
add_table_row('Nome', 'Idade', ['Mail' => '[email protected]']);

or

add_table_row('Nome', 'Idade', array('Mail' => '[email protected]'));

So an example of the full code of the function would be something like this:

function add_table_row() {
    $args = func_get_args(); // retorna uma array de argumentos...
    $o = "<tr>\n";
    foreach ($args as $value) {
        if (is_array($value)) {       // Se o argumento é uma array...
            $cont = key($value);      // O dado da célula é a chave...
            $param = current($value); // E o parâmetro da tag é o valor...
            $o .= "<td $param>$cont</td>\n";
        } else {
            $o .= "<td>$value</td>\n";
        }
    }
    $o .= "</tr>\n";
    return $o;
}

I hope this will be useful to someone else.

  • this is allowed yes. Choose your own answer as solving the problem

  • Another very common way is to pass a single array to the function, with others inside if necessary. For example: add_table_row(['Nome', 'Idade', ['Mail' => '[email protected]']]);. Within the function, you can check if each of the items is another array with is_array().

0

Since you will create a function for this, you can pass as string and find the elements markers... Just explode in , and if there is : the function will understand that is an array.

add_table_row('Nome,Idade,Mail:[email protected]')

    function add_table_row( $string )
    {
        $string = explode( ',' , $string );

        foreach( $string as $line )
        {
            if( strpos( $line , ':' ) && $elementos = explode( ':' , $line ) )
            {
                echo $elementos[0] . ', ' . $elementos[1];
            }
            else
            {
                echo $line;
            }
        }
    }

output
Name
Age
Mail, [email protected]

  • This was my first impulse, because I usually use and abuse implosions, explosions and other operations with strings. But this implies processing the data twice: preparing the string of arguments and "decoding" within the function. Already using an array (or with func_get_args(), as was my choice), I just need to prepare the data for the function, which in turn becomes much cleaner, objective and readable, I think. But your solution is as good as any.

Browser other questions tagged

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