Is there something like keypath in an associative array in PHP?

亡梦爱人 提交于 2019-12-11 02:37:43

问题


I want to dissect an array like this:

[
    "ID",
    "UUID",
    "pushNotifications.sent",
    "campaigns.boundDate",
    "campaigns.endDate",
    "campaigns.pushMessages.sentDate",
    "pushNotifications.tapped"
]

To a format like this:

{
    "ID" : 1,
    "UUID" : 1,
    "pushNotifications" : 
        {
            "sent" : 1,
            "tapped" : 1
        },
    "campaigns" :
        {
            "boundDate" : 1,
            "endDate" : 1,
            "pushMessages" :
                {
                    "endDate" : 1
                }  
        }
}

It would be great if I could just set a value on an associative array in a keypath-like manner:

//To achieve this:
$dissected['campaigns']['pushMessages']['sentDate'] = 1;

//By something like this:
$keypath = 'campaigns.pushMessages.sentDate';
$dissected{$keypath} = 1;

How to do this in PHP?


回答1:


You can use :

$array = [
        "ID",
        "UUID",
        "pushNotifications.sent",
        "campaigns.boundDate",
        "campaigns.endDate",
        "campaigns.pushMessages.sentDate",
        "pushNotifications.tapped"
];

// Build Data
$data = array();
foreach($array as $v) {
    setValue($data, $v, 1);
}

// Get Value
echo getValue($data, "campaigns.pushMessages.sentDate"); // output 1

Function Used

function setValue(array &$data, $path, $value) {
    $temp = &$data;
    foreach(explode(".", $path) as $key) {
        $temp = &$temp[$key];
    }
    $temp = $value;
}

function getValue($data, $path) {
    $temp = $data;
    foreach(explode(".", $path) as $ndx) {
        $temp = isset($temp[$ndx]) ? $temp[$ndx] : null;
    }
    return $temp;
}



回答2:


function keyset(&$arr, $keypath, $value = NULL)
{
   $keys = explode('.', $keypath);
   $current = &$arr;
   while(count($keys))
   {
      $key = array_shift($keys);
      if(!isset($current[$key]) && count($keys))
      {
         $current[$key] = array();
      }
      if(count($keys))
      {
         $current = &$current[$key];
      }
   }
   $current[$key] = $value;
}

function keyget($arr, $keypath)
{
   $keys = explode('.', $keypath);
   $current = $arr;
   foreach($keys as $key)
   {
      if(!isset($current[$key]))
      {
         return NULL;
      }
      $current = $current[$key];
   }
   return $current;
}

//Testing code:
$r = array();
header('content-type: text/plain; charset-utf8');
keyset($r, 'this.is.path', 39);
echo keyget($r, 'this.is.path');
var_dump($r);

It's a little rough, I can't guarantee it functions 100%.

Edit: At first you'd be tempted to try to use variable variables, but I've tried that in the past and it doesn't work, so you have to use functions to do it. This works with some limited tests. (And I just added a minor edit to remove an unnecessary array assignment.)




回答3:


In the meanwhile, I came up with (another) solution:

private function setValueForKeyPath(&$array, $value, $keyPath)
{
    $keys = explode(".", $keyPath, 2);
    $firstKey = $keys[0];
    $remainingKeys = (count($keys) == 2) ? $keys[1] : null;
    $isLeaf = ($remainingKeys == null);

    if ($isLeaf)
        $array[$firstKey] = $value;
    else
        $this->setValueForKeyPath($array[$firstKey], $value, $remainingKeys);
}

Sorry for the "long" namings, I came from the Objective-C world. :) So calling this on each keyPath, it actually gives me the output:

fields
Array
(
    [0] => ID
    [1] => UUID
    [2] => pushNotifications.sent
    [3] => campaigns.boundDate
    [4] => campaigns.endDate
    [5] => campaigns.pushMessages.endDate
    [6] => pushNotifications.tapped
)
dissectedFields
Array
(
    [ID] => 1
    [UUID] => 1
    [pushNotifications] => Array
        (
            [sent] => 1
            [tapped] => 1
        )

    [campaigns] => Array
        (
            [boundDate] => 1
            [endDate] => 1
            [pushMessages] => Array
                (
                    [endDate] => 1
                )

        )

)


来源:https://stackoverflow.com/questions/16389168/is-there-something-like-keypath-in-an-associative-array-in-php

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!