【问题标题】:PHP object schema validationPHP 对象模式验证
【发布时间】:2014-08-29 11:35:54
【问题描述】:

是否可以动态检查两个对象架构是否相同(在 php 中)?例如:

{
   name: "Name1",
   age: 2,
   kids: [1,3,4]
}

{
   name: "Name2",
   age: 2,
   kids: [1,6,4,3]
}

对于上面的示例,我希望返回 true。这是另一个例子:

{
   name: "Name1",
   age: 2,
   kids: [1,3,4]
}

{
   name: "Name1",
   kids: [1,3,4]
}

在这里我期望得到错误(模式不一样:第二个对象缺少年龄)。

函数定义应该是这样的:Boolean isSchemaEqual($obj1, $obj2)(我知道php中没有函数定义,只是为了让我的问题更清楚)。

注意:架构可以嵌套,因为我的意思是某些属性可以包含一个对象,该对象还需要与另一个对象的(相同)属性进行检查。

【问题讨论】:

    标签: php json object recursion


    【解决方案1】:

    如果您希望验证多级架构,您可以将递归与键的无序数组比较习惯结合使用。

    // determines if an array is associative
    function isAssociative($array) {
        return (bool)count(array_filter(array_keys($array), 'is_string'));
    }
    
    // determines if the keys of two arrays are equal regardless of order
    function keysEqual($a, $b) {
        if (!is_array($a) || !is_array($b))
            return false;
    
        $keysA = array_keys($a);
        $keysB = array_keys($b);
    
        return array_diff($keysA, $keysB) === array_diff($keysB, $keysA);
    }
    
    function isSchemaEqual($a, $b) {
        // validate keys - basic validation
        if (!keysEqual($a, $b))
            return false;
    
        // if we come across any key where the value is associative and 
        // the schema isn't the same for b's value at $key, then we know 
        // the schemas aren't equal 
        foreach ($a as $key => $value) {
            if (is_array($value) && isAssociative($value) && !isSchemaEqual($value, $b[$key]))
                return false;
        }
    
        // we couldn't find any differences, so they're equal
        return true;
    }
    

    你可以找到一些测试,here。

    【讨论】:

      【解决方案2】:

      比较键:

      if (array_keys($schema1) == array_keys($schema2)) {
      
      }
      

      对于嵌套对象,您必须创建自己的函数。一种方法是将其设为一级,将{kids: {boys: [1,2,3]}} 之类的路径变为kids/boys,然后您可以比较数组:

      function flatten_keys($object, $prefix = '') {
         $result = array();
         foreach ($object as $key=>$value) {
           $result[] = $prefix . $key;
           if (is_object($value) || (is_array($value) && array_values($value) != $value) ) {
               $result = array_merge($result, flatten_keys($value, $key .'/'));
           }
         }
         return $result;
      }
      
      $a = flatten_keys($schema2);
      $b = flatten_keys($schema2);
      sort($a);
      sort($b);
      if ($a == $b){
      
      }
      

      【讨论】:

      • schema1 & schema2 是例子中的对象吗?
      • 这是一个很好的解决方案,但是,它只适用于第一级密钥,假设@vlio20 想要验证多个级别。此外,如果键的顺序不同,它将失败。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-10-23
      • 2017-11-08
      • 2015-09-14
      • 1970-01-01
      • 2020-10-31
      相关资源
      最近更新 更多