0
$variable = '
    persons.0.name = "peter"
    persons.0.lastname = "griffin"
    persons.1.name = "homer"
    persons.1.lastname = "simpsons"';

I want to generate from that $variable an array that looks like this

array(2) {
  [0]=>
  array(2) {
    ["name"]=>
    string(5) "peter"
    ["lastname"]=>
    string(7) "griffin"
  }
  [1]=>
  array(2) {
    ["name"]=>
    string(5) "homer"
    ["lastname"]=>
    string(7) "simpson"
  }
} 

so far this is what I have so far.

$temp = explode('\r\n', $persons);

$sets = [];
foreach ($temp as $value)
{
    $array = explode('=', $value);

    if ($array[0] != '')
    {
        $array[1] = trim($array[1], '"');
        $sets[$array[0]] = $array[1];
        $output = $sets;
    }
}

that generates "persons.1.name" as a key and "peter" as a value I´m not sure how to generate arrays based on "." thank you.

I tried with parse_ini_string() but basically is doing the same thing.

handsome
  • 2,335
  • 7
  • 45
  • 73

3 Answers3

2

You can use array_reduce and explode

$variable = '
    persons.0.name = "peter"
    persons.0.lastname = "griffin"
    persons.1.name = "homer"
    persons.1.lastname = "simpsons"';

$temp = explode(PHP_EOL, $variable);

$result = array_reduce($temp, function($c, $v){
    $v = explode( "=", $v );
    if ( trim( $v[0] ) !== "" ) {
        $k = explode( ".", $v[0]  );
        $c[ $k[ 1 ] ][ $k[ 2 ] ] = $v[1];       
    }
    return $c;
}, array());

echo "<pre>";
print_r( $result );
echo "</pre>";

This will result to:

Array
(
    [0] => Array
        (
            [name ] =>  "peter"
            [lastname ] =>  "griffin"
        )

    [1] => Array
        (
            [name ] =>  "homer"
            [lastname ] =>  "simpsons"
        )

)

Doc: http://php.net/manual/en/function.array-reduce.php


UPDATE: If you want to set depth, you can

$variable = '
persons.0.name = "peter"
persons.0.lastname = "griffin"
persons.1.name = "homer"
persons.1.lastname = "simpsons"
data = "foo"
url = so.com?var=true
';

$temp = explode(PHP_EOL, $variable);

$result = array_reduce($temp, function($c, $v){
    $v = explode( "=", $v, 2 );

    if ( trim( $v[0] ) !== "" ) {
        $k = explode( ".", $v[0]  );
        $data = $v[1];
        foreach (array_reverse($k) as $key) {
            $data = array( trim( $key ) => $data);
        }

        $c = array_replace_recursive( $c, $data );
    }

    return $c;
}, array());

echo "<pre>";
print_r( $result );
echo "</pre>";

This will result to:

Array
(
    [persons] => Array
        (
            [0] => Array
                (
                    [name] =>  "peter"
                    [lastname] =>  "griffin"
                )

            [1] => Array
                (
                    [name] =>  "homer"
                    [lastname] =>  "simpsons"
                )

        )

    [data] =>  "foo"
    [url] =>  so.com?var=true
)
Eddie
  • 26,593
  • 6
  • 36
  • 58
  • Yes, it is set coz thats what the OP is asking (as far as i understand). If you are going to set all (dynamic) the array will look like ["persons"][1]["lastname"] -Which is not what the OP wants :) – Eddie Feb 16 '18 at 05:04
  • well. it was an example. it only works with that data set. if I add another linea with data like foo = bar it will break – handsome Feb 16 '18 at 05:27
  • What data did you add? – Eddie Feb 16 '18 at 05:28
  • hey Eddie. I added this $variable = ' persons.0.name = "peter" persons.0.lastname = "griffin" persons.1.name = "homer" persons.1.lastname = "simpsons" other = "data" ' – handsome Feb 16 '18 at 06:15
  • How do you want to present the `other` on your final array? – Eddie Feb 16 '18 at 06:17
  • @handsome I added a new alternative. Please check. – Eddie Feb 16 '18 at 06:39
  • Happy to help. @handsome – Eddie Feb 16 '18 at 06:57
  • hey @Eddie one more question. I found that if the value contains = it breaks for example url = so.com?var=true how to fix this?? – handsome Feb 18 '18 at 09:19
  • @handsome You have to use `$v = explode( "=", $v, 2 );` Please updated answer – Eddie Feb 18 '18 at 10:22
0

PHP's ini parsing is limited and wouldn't parse that even if it was persons[0][name] = "peter".

Taken from my answer here How to write getter/setter to access multi-level array by key names?, first just explode on = to get the key path and value, and then explode on . for the keys and build the array:

$lines = explode("\n", $variable);  //get lines

list($path, $value) = explode('=', $lines); //get . delimited path to build keys and value
$path = explode('.', $path); //explode path to get individual key names

$array = array();
$temp  = &$array;

foreach($path as $key) {
    $temp =& $temp[trim($key)];
}
$temp = trim($value, '"');

Also trims spaces and ".

AbraCadaver
  • 78,200
  • 7
  • 66
  • 87
0

Because each line contains the full address to and data for the array, we can create everything with a loop instead of recursion.

// Create variable for final result
$output=[];

// Loop over input lines, and let PHP figure out the key/val
foreach (parse_ini_string($variable) AS $key=>$val) {
    $stack = explode('.', $key);
    $pos = &$output;

    // Loop through elements of key, create when necessary
    foreach ($stack AS $elem) {
        if (!isset($pos[$elem]))
            $pos[$elem] = [];
        $pos = &$pos[$elem];
    }

    // Whole key stack created, drop in value
    $pos = $val;
}

// The final output
var_dump($output);

Output:

array(1) {
  ["persons"]=>
  array(2) {
    [0]=>
    array(2) {
      ["name"]=>
      string(5) "peter"
      ["lastname"]=>
      string(7) "griffin"
    }
    [1]=>
    array(2) {
      ["name"]=>
      string(5) "homer"
      ["lastname"]=>
      &string(8) "simpsons"
    }
  }
}
sorak
  • 2,607
  • 2
  • 16
  • 24