首页 > 解决方案 > 将代码从 foreach 重构为 Laravel 集合

问题描述

我有一个这样的 JSON 文件

{
    "20":{
        "0":{
            "period":[
                {
                    "open": 350,
                    "close": 600
                },
                {
                    "open": 660,
                    "close": 900
                }
            ]
        },
        "1":{
            "period":[
                {
                    "open": 350,
                    "close": 600
                },
                {
                    "open": 660,
                    "close": 900
                }
            ]
        },
        "2":{
            "period":[
                {
                    "open": 350,
                    "close": 600
                },
                {
                    "open": 660,
                    "close": 900
                }
            ]
        },
        "3":{
            "period":[
                {
                    "open": 350,
                    "close": 600
                },
                {
                    "open": 660,
                    "close": 900
                }
            ]
        },
        "4":{
            "period":[
                {
                    "open": 350,
                    "close": 600
                },
                {
                    "open": 660,
                    "close": 900
                }
            ]
        },
        "5":{
            "period":[
                {
                    "open": 350,
                    "close": 600
                },
                {
                    "open": 660,
                    "close": 900
                }
            ]
        },
        "6":{
            "period":[
                {
                    "open": 350,
                    "close": 600
                },
                {
                    "open": 660,
                    "close": 900
                }
            ]
        }
    },
    "21":{
        "0":{
            "period":[
                {
                    "open": 350,
                    "close": 600
                },
                {
                    "open": 660,
                    "close": 900
                }
            ]
        },
        "1":{
            "period":[
                {
                    "open": 350,
                    "close": 600
                },
                {
                    "open": 660,
                    "close": 900
                }
            ]
        },
        "2":{
            "period":[
                {
                    "open": 350,
                    "close": 600
                },
                {
                    "open": 660,
                    "close": 900
                }
            ]
        },
        "3":{
            "period":[
                {
                    "open": 350,
                    "close": 600
                },
                {
                    "open": 660,
                    "close": 900
                }
            ]
        },
        "4":{
            "period":[
                {
                    "open": 350,
                    "close": 600
                },
                {
                    "open": 660,
                    "close": 900
                }
            ]
        },
        "5":{
            "period":[
                {
                    "open": 350,
                    "close": 600
                },
                {
                    "open": 660,
                    "close": 900
                }
            ]
        },
        "6":{
            "period":[
                {
                    "open": 350,
                    "close": 600
                },
                {
                    "open": 660,
                    "close": 900
                }
            ]
        }
    }

我有一个action正在将其解码JSON为数组,并通过foreach-es 逐步传递,获取该数据,然后将其存储在数据库中。

一个人说我可以重构所有这些动作,所以我不会绝对(或近似)任何 foreach 或 if。他还说这叫做representative/functional编程。

所以,我发现了这个概念和所有那些东西,但也无法弄清楚如何去做。我的imperial代码:

$processingFile = file_get_contents(storage_path('hours.txt'));
$decodedFile = json_decode($processingFile, true);

$data = [];
$i = 0;
$batch = 10000;

foreach ($decodedFile as $business => $days) {
    foreach ($days as $dayOfWeek => $periods) {
        if (count($periods)) {
            foreach ($periods['period'] as $key => $value) { 
                $i++;  
                $tmp = [
                    'business_id' => $business,
                    'day_of_week' => $dayOfWeek,
                    'open_periods_mins' => $value['open'],
                    'close_periods_mins' => $value['close'],
                ];
                array_push($data, $tmp);
                if($i === $batch) {
                    BusinessHour::insert($data);
                    $data = [];
                    $i = 0;
                }
            }
        }
    }
}

if( count($data) ) {
    BusinessHour::insert($data); 
}

我不知道如何parse一步一步地在函数中使用Laravel Collections或其他任何东西declarative paradigm......

有人可以出于教学目的解释/重写该代码吗?谢谢!

标签: phplaravelcollections

解决方案


我不确定是否有任何适用于您的情况的通用方法,因为您将信息操作到最终数组中的方式不是通用的(例如,字符串“句点”和点数组中的数字键都不是未在最终输出中的任何地方使用,而使用其他键,最后两个子元素组合成一个记录,等等)。

$data这是在您的示例中准备的一种有点技术性的方法,在此答案中“PHP 将嵌套数组转换为单个数组同时连接键?”的方法在哪里?被采纳。有了这个,它只使用一个foreach(我认为一级循环是不可避免的,因为最终转换是非通用的)。请注意,它假定输入 JSON 没有不规则结构。

$string = http_build_query($decodedFile);
$string = urldecode($string);
$string = str_replace(
              array('[',']'),
              array('_','') , 
              $string
          );
parse_str($string, $flat_array);

$data = [];
$tmp = [];
foreach ($flat_array as $ky => $val) {
    $ary = explode('_', $ky);
    $tmp[$ary[4] . '_periods_mins'] = $val;
    if ($ary[4] == 'close') {
        array_push($data, $tmp);
        $tmp = [];
        continue;
    }
    $tmp['business_id'] = $ary[0];
    $tmp['day_of_week'] = $ary[1];
}

推荐阅读