为了账号安全,请及时绑定邮箱和手机立即绑定

将动态多维数组转换为点符号

将动态多维数组转换为点符号

PHP
12345678_0001 2023-06-18 16:28:10
我有一个数组,它实际上是一个树数组:array:2 [▼  0 => array:7 [▼    "id" => 36    "attribute_key" => "amount"    "attribute_value" => "Amount"    "input_type_id" => 3    "is_required" => 1    "parent_id" => null  ]  1 => array:8 [▼    "id" => 37    "attribute_key" => "products"    "attribute_value" => "Products"    "input_type_id" => 7    "is_required" => 1    "parent_id" => null    "event" => null    "children" => array:2 [▼      0 => array:7 [▼        "id" => 38        "attribute_key" => "product_name"        "attribute_value" => "Product Name"        "input_type_id" => 1        "is_required" => 1        "parent_id" => 37      ]      1 => array:7 [▼        "id" => 39        "attribute_key" => "price"        "attribute_value" => "Price"        "input_type_id" => 3        "is_required" => 1        "parent_id" => 37      ]    ]  ]]我想得到这样的输出:[     'amount' => 'required',     'products.*.product_name' => 'required',     'products.*.price' => 'required|numeric',]我的数据是高度动态的,我想为 Laravel 创建验证规则。这是我有什么:class EventRules{    protected $rules = [];    public function rules(array $attributes) : array    {        foreach ($attributes as $attribute) {            $this->addRules($attribute);        }        return $this->rules;    }    public function addRules($attribute) : void    {          if (isset($attribute['children'])) {            $this->rules($attribute['children']);            return;        }        $attributeKey = $attribute['attribute_key'];        $rule = '';        $rule .= $this->addRequiredRule($attribute);        $rule .= $this->addFieldTypeRule($attribute);        $this->rules[$attributeKey] = $rule;    }    protected function addRequiredRule($attribute) : string    {        $rule = '';        if ($attribute['is_required'] === 1) {            $rule .= 'required|';        }        // The rest will be here..        return $rule;    }无论如何,我坚持创建一个规则键(带*)。我知道我需要一个我使用的递归,但仍然不确定如何处理其余部分。
查看完整描述

1 回答

?
慕容3067478

TA贡献1773条经验 获得超3个赞

我弄清楚并提出一些起点:


// Enum class for field types

final class InputTypeEnum {

    const STRING_TYPE = 1;

    const INTEGER_TYPE = 2;

    const DECIMAL_TYPE = 3;

    const DATE_TYPE = 4;

    const DATE_EMAIL = 7;

}


// Here is class to flat the rules.


class RulesFlattener {


    const ATTRIBUTE_KEY = 'attribute_key';

    const CHILD_KEY = 'children';


    private $input;

    private $output = [];


    // This array keeps map to translate rules

    private $availableRules = [

        'is_required' => 'required',

        'input_type_id' => [

            InputTypeEnum::STRING_TYPE => 'string',

            InputTypeEnum::INTEGER_TYPE => 'integer',

            InputTypeEnum::DECIMAL_TYPE => 'numeric',

            InputTypeEnum::DATE_TYPE => 'date',

            InputTypeEnum::DATE_EMAIL => 'email',

        ]

    ];


    public function __construct($input) {

        $this->input = $input;

    }


    private function extractRules($row) {

        $rules = [];


        foreach($row as $k => $v) {

            if(isset($this->availableRules[$k])) {


                $mappedRule = $this->availableRules[$k];


                if(is_array($mappedRule)) {

                    $rule = $mappedRule[$v] ?? null;

                } else {

                    $rule = $mappedRule;

                }


                $rules[] = $rule;

            }

        }


        return array_unique($rules);

    }


    public function parse() {

        return $this->parseRow($this->input);

    }


    private function parseRow($input, $parentKey = null) {

        $output = [];

        foreach ($input as $row) {


            // Keep name of current attribute (for recursion)

            $currentAttribute = $row[self::ATTRIBUTE_KEY] ?? null;


            // If you want get more nested rules like product.*.photos.*.url use this:

            // $currentAttribute = ( $parentKey ? $parentKey.'.*.':'') . $row[self::ATTRIBUTE_KEY] ?? null;


            foreach($row as $k => $v) {

                switch($k) {


                    case self::ATTRIBUTE_KEY:

                        $rules = $this->extractRules($row);

                        $output[($parentKey?$parentKey.'.*.':'').$v] = implode('|', $rules);

                        break;


                    case self::CHILD_KEY:

                        $output = array_merge($output, $this->parseRow($row[$k], $currentAttribute));

                        break;


                }

            }

        }

        return $output;

    }


}



现在您可以将其用作:


$dataIn = [

    [

        "id" => 36,

        "attribute_key" => "amount",

        "attribute_value" => "Amount",

        "input_type_id" => 3,

        "is_required" => 1,

        "parent_id" => null,

    ],

    [

        "id" => 37,

        "attribute_key" => "products",

        "attribute_value" => "Products",

        "input_type_id" => 7,

        "is_required" => 1,

        "parent_id" => null,

        "event" => null,

        "children" => [

            [

                "id" => 38,

                "attribute_key" => "product_name",

                "attribute_value" => "Product Name",

                "input_type_id" => 1,

                "is_required" => 1,

                "parent_id" => 37,

            ],

            [

                "id" => 39,

                "attribute_key" => "price",

                "attribute_value" => "Price",

                "input_type_id" => 3,

                "is_required" => 1,

                "parent_id" => 37,

            ]

        ]

    ]

];


$flat = new RulesFlattener($dataIn);


$rules = $flat->parse();

我得到这个输出:


Array

(

    [amount] => numeric|required

    [products] => email|required

    [products.*.product_name] => string|required

    [products.*.price] => numeric|required

)


查看完整回答
反对 回复 2023-06-18
  • 1 回答
  • 0 关注
  • 88 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信