【PHP】ドット記法での配列を多次元化

PHP

以前の記事でLaravelのconfig()等でよく使われているドット記法(dot notation)での配列アクセスをピュアPHPで実装しました。

今回は逆に、ドット記法で記したキーの1次元配列を多次元配列に展開していきます。

「Illuminate\Support\Arr::undot()」でサポートされていたりしますが

Laravel - The PHP Framework For Web Artisans
Laravel is a PHP web application framework with expressive, elegant syntax. We’ve already laid the foundation — freeing ...

敢えてピュアPHPで実装していきます。

使用する配列の例

▼dot-notated-data.php

<?php

return [
    'database.connection' => 'mysql',
    'database.host' => '127.0.0.1',
    'database.user' => 'dbadmin',
    'database.password' => 'Pass_w0rd',
    'database.dbname' => 'webapp',
    'database.tables.users.columns.id' => 'user id, primary key',
    'database.tables.users.columns.name' => "user's name, required",
    'database.tables.users.columns.passowrd' => 'login password, required, encrypted',
    'database.tables.users.columns.email' => "user's email",
    'database.tables.posts.columns.id' => 'post id, primary key',
    'database.tables.posts.columns.user_id' => "user's id, required",
    'database.tables.posts.columns.title' => 'title of the post',
    'database.tables.posts.columns.content' => 'content of the post',
];

オペレーターファイル

▼「undotArray.php」

<?php

// クラス読込
require __DIR__ . '/Arr.php';

// 配列データ読込
$data = require __DIR__ . '/dot-notated-data.php';

// 配列アクセッサーのインスタンス生成
$array = new MyLib\Arr();

// 多次元配列を出力
print_r($array->undot($data));

※「Arr.php」は次で作成します。

多次元配列化処理クラス

▼処理部のコア

※ $key がドット(.)を含んでいる前提

※ $key をドット(.)で分割し最下層の要素から順次構築

    protected function dig(string $key, mixed $value)
    {
        $results = $value;
        $keys = explode('.', $key);
        while ($k = array_pop($keys)) {
            $results = [$k => $results];
        }
        return $results;
    }

※ 「dig()」から受け取ったものを「array_merge_recursive()」でマージ

    public function undot(array $array)
    {
        $results = [];
        foreach ($array as $key => $value) {
            if (str_contains($key, '.')) {
                $results = array_merge_recursive($results, self::dig($key, $value));
                continue;
            }
            $results[$key] = $value;
        }
        return $results;
    }

▼「Arr.php」の完成形

<?php

namespace MyLib;

class Arr
{
    public function undot(array $array)
    {
        $results = [];
        foreach ($array as $key => $value) {
            if (str_contains($key, '.')) {
                $results = array_merge_recursive($results, self::dig($key, $value));
                continue;
            }
            $results[$key] = $value;
        }
        return $results;
    }

    protected function dig(string $key, mixed $value)
    {
        $results = $value;
        $keys = explode('.', $key);
        while ($k = array_pop($keys)) {
            $results = [$k => $results];
        }
        return $results;
    }
}

実行結果

Array
(
    [database] => Array
        (
            [connection] => mysql
            [host] => 127.0.0.1
            [user] => dbadmin
            [password] => Pass_w0rd
            [dbname] => webapp
            [tables] => Array
                (
                    [users] => Array
                        (
                            [columns] => Array
                                (
                                    [id] => user id, primary key
                                    [name] => user's name, required
                                    [passowrd] => login password, required, encrypted
                                    [email] => user's email
                                )
                        )
                    [posts] => Array
                        (
                            [columns] => Array
                                (
                                    [id] => post id, primary key
                                    [user_id] => user's id, required
                                    [title] => title of the post
                                    [content] => content of the post
                                )
                        )
                )
        )
)

コメント

タイトルとURLをコピーしました