当前位置: 首页 > article >正文

Laravel Validation validated() 的实现

Reference

  • illuminate/validation
  • laravel/laravel

Path

  • vendor/laravel/framework/src/Illuminate/Validation/Validator.php

实现

validated()
  • 结合代码可以看出 validated()方法的核心逻辑在于取值 data_get 和赋值 Arr::set()这俩个地方

/**
 * Get the attributes and values that were validated.
 *
 * @return array
 *
 * @throws \Illuminate\Validation\ValidationException
 */
public function validated()
{
    // 检查当前的验证是否通过
    if ($this->invalid()) {
        throw new ValidationException($this);
    }

    $results = [];
    
    // 随机字符串 用于给数据赋予默认的值[暂不清楚有啥作用]
    $missingValue = Str::random(10);

    // $this->getRules() 会获取到所有的验证规则的 key , key 即为我们定义的规则键名
    // 这里的 data_get 和 Arr::set 都是自定义的用于获取和定义 item.key 这样形式的数据的辅助函数
    foreach (array_keys($this->getRules()) as $key) {
        // 获取数据中的键对应的值
        $value = data_get($this->getData(), $key, $missingValue);

        // 如果值不是随机字符串, 则将值赋予给结果数组
        // 那这里也就是说,如果这个键在数据传递的数据中没有定义值,那么就不会被赋值给结果数组
        if ($value !== $missingValue) {
            Arr::set($results, $key, $value);
        }
    }

    return $results;
}
data_get()
if (! function_exists('data_get')) {
    /**
     * Get an item from an array or object using "dot" notation.
     *
     * @param  mixed  $target
     * @param  string|array|int  $key
     * @param  mixed  $default
     * @return mixed
     */
    function data_get($target, $key, $default = null)
    {
        // 如果 key 为 null,则直接返回 target,也就是直接返回原数据
        if (is_null($key)) {
            return $target;
        }

        // key 还能是数组吗???这里应该是兼容的其他地方的调用
        // validator 这里调用的时候应该是使用后面 explode 的方式
        // 为的是处理 类似 user.name 这样的 key
        $key = is_array($key) ? $key : explode('.', $key);

        // 这里是一个 while 循环,每次循环都会从 key 中取出一个元素
        // np 这里将 array 类似为一个队列,不断的从中 pop(shift) 元素,直到为空
        while (! is_null($segment = array_shift($key))) {
            // 如果当前元素为 * , 对应的是 users.*.name 这样的多维数组的场景
            if ($segment === '*') {
                // 如果 target 是一个集合,那么就将集合中的每一个元素的 key 对应的值取出来
                if ($target instanceof Collection) {
                    $target = $target->all();
                } elseif (! is_array($target)) {
                    return value($default);
                }

                $result = [];

                foreach ($target as $item) {
                    // 这里需要注意的事 array_shift 是引用传递参数的
                    // 也就是说如果最初传递的 参数是 user.*.name -> ["user", "*", "name"],那么当代码执行到此处时 key 经过前面的 pop 到此处其实只有 ["name"] 了
                    // 递归调用 data_get,将结果放入 result 中, 此时再传递进去的 key 就是数组,正好对应了上面的数据格式兼容设计()
                    $result[] = data_get($item, $key);
                }

                // Arr::collapse 顾名思义,将多维数组降低一个维度
                // 那么索引数组下同名的 key 值会进行覆盖?
                // 啥意思啊??? 类似 user.* 的场景吗 数组?["zhangsan", "lisi", "wangwu"] 这样的场景?
                // 当 key 以 * 结尾时,返回当前数组即可,不过要求当前数组机
                return in_array('*', $key) ? Arr::collapse($result) : $result;
            }
            
            if (Arr::accessible($target) && Arr::exists($target, $segment)) {
                // Arr::accessible 判断 $targe 是否实现了数组接口
                // Arr::exists 判断 $target 中是否存在 $segment 这个 key
                // 如果是数组的话 直接取值就好了
                $target = $target[$segment];
            } elseif (is_object($target) && isset($target->{$segment})) {
                // 如果是对象的话,直接取属性
                $target = $target->{$segment};
            } else {
                // 其他类型的话,直接返回默认值
                return value($default);
            }
        }

        return $target;
    }
}
Arr::set()
/**
 * Set an array item to a given value using "dot" notation.
 *
 * If no key is given to the method, the entire array will be replaced.
 *
 * @param  array  $array
 * @param  string  $key
 * @param  mixed  $value
 * @return array
 */
public static function set(&$array, $key, $value)
{
    if (is_null($key)) {
        return $array = $value;
    }

    $keys = explode('.', $key);

    while (count($keys) > 1) {
        $key = array_shift($keys);

        // If the key doesn't exist at this depth, we will just create an empty array
        // to hold the next value, allowing us to create the arrays to hold final
        // values at the correct depth. Then we'll keep digging into the array.
        if (! isset($array[$key]) || ! is_array($array[$key])) {
            $array[$key] = [];
        }

        $array = &$array[$key];
    }

    $array[array_shift($keys)] = $value;

    return $array;
}

http://www.kler.cn/a/532673.html

相关文章:

  • 圆上取点(例题)
  • 【Linux系统】信号:再谈OS与内核区、信号捕捉、重入函数与 volatile
  • pytorch实现长短期记忆网络 (LSTM)
  • EtherCAT主站IGH-- 30 -- IGH之master.h/c文件解析
  • 《MPRnet》学习笔记
  • STM32 对射式红外传感器配置
  • Selenium记录RPA初阶 - 基本输入元件
  • js --- 获取随机数
  • 预防和应对DDoS的方法
  • 【力扣】283.移动零
  • springboot后台系统开发(三)- 日志
  • 【OS】AUTOSAR架构下的Interrupt详解(上篇)
  • 某某音乐歌单下载(电脑)
  • 物联网领域的MQTT协议,优势和应用场景
  • spark君第一篇图文讲解Delta源码和实践的文章
  • C基础寒假练习(8)
  • ioDraw桌面版 v3.4.0发布!AI文生图,AI图生图,手绘风格一键转换!
  • 37、【OS】【Nuttx】OSTest分析(2):任务创建
  • 深入探索Vue 3组合式API
  • 实例研究:设计一个文档编辑器(1)
  • 有用的sql链接
  • 调用DeepSeek API实现对本地数据库的AI管理
  • 手扶电梯缺陷检测数据集VOC+YOLO格式67张1类别
  • 【Numpy核心编程攻略:Python数据处理、分析详解与科学计算】2.19 线性代数核武器:BLAS/LAPACK深度集成
  • 二叉树03(数据结构初阶)
  • Leetcode—922. 按奇偶排序数组 II【简单】