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

我有一个数组,它实际上是一个树数组:


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;

    }



无论如何,我坚持创建一个规则键(带*)。我知道我需要一个我使用的递归,但仍然不确定如何处理其余部分。


12345678_0001
浏览 89回答 1
1回答

慕容3067478

我弄清楚并提出一些起点:// Enum class for field typesfinal 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)
打开App,查看更多内容
随时随地看视频慕课网APP