Код рефакторинга от foreach к коллекциям Laravel - PullRequest
0 голосов
/ 17 октября 2018

У меня есть 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.

Может ли кто-нибудь объяснить / переписать этот код в учебных целях?Спасибо!

Ответы [ 2 ]

0 голосов
/ 18 октября 2018

Этого можно добиться с помощью помощника collect () , который добавит массив к экземпляру коллекции и позволит использовать его методы.

$processingFile = file_get_contents(storage_path('hours.txt'));
$data = json_decode($processingFile, true);
$insertData = [];

collect($data)
    ->each(function ($business, $businessKey) use (&$insertData) {
        collect($business)
            ->each(function ($day, $dayKey) use ($businessKey, &$insertData) {
                foreach ($day['period'] as $period) {
                    $insertData[] = [
                        'business_id'        => $businessKey,
                        'days_of_week'       => $dayKey,
                        'open_periods_mins'  => $period['open'],
                        'close_periods_mins' => $period['close'],
                    ];
                }
            });
    });

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

Во-первых,мы получаем $processingFile и декодируем его в переменную $data.$insertData создается как новый пустой массив, который будет использоваться позже.

Затем поместите переменную $data в помощник collect().Для каждого business мы передаем справочную переменную $insertData.Это необходимо для того, чтобы обновить переменную вне замыканий коллекции.

Внутри каждого business у нас есть days, поэтому мы собираем $business (что на самом деле days) и для каждого day, пройти через $businessKey и ссылку на переменную $insertData.

После этого мы используем обычный foreach для обновления массива $insertData новыми данными.

В конце процесса вы затем insert() вводите все данные в записи модели BusinessHour.

Надеюсь, это поможет.

0 голосов
/ 18 октября 2018

Я не уверен, существуют ли какие-либо универсальные способы, применимые к вашему случаю, учитывая, что способ манипулирования информацией в конечном массиве не универсален (например, ни строка «точка», ни числовые ключи в period Массив не используется где-либо в конечном выводе, в то время как другие ключи используются, и последние два дочерних элемента объединяются в одну запись и т. Д.).

Вот немного изящный способподготовить $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];
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...