侯体宗的博客
  • 首页
  • 人生(杂谈)
  • 技术
  • 关于我
  • 更多分类
    • 文件下载
    • 文字修仙
    • 中国象棋ai
    • 群聊
    • 九宫格抽奖
    • 拼图
    • 消消乐
    • 相册

深入php内核之php in array

php  /  管理员 发布于 7年前   230

先给大家介绍php in array函数基本知识热热身。

定义和用法

in_array() 函数在数组中搜索给定的值。

语法
in_array(value,array,type)

参数 描述
value 必需。规定要在数组搜索的值。
array 必需。规定要搜索的数组。
type 可选。如果设置该参数为 true,则检查搜索的数据与数组的值的类型是否相同。

 说明

如果给定的值 value 存在于数组 array 中则返回 true。如果第三个参数设置为 true,函数只有在元素存在于数组中且数据类型与给定值相同时才返回 true。

如果没有在数组中找到参数,函数返回 false。

注释:如果 value 参数是字符串,且 type 参数设置为 true,则搜索区分大小写。

无意中看到一段代码

测试了一下

[root@dev tmp]# time php b.php
real    0m9.517s
user    0m4.486s
sys     0m0.015s

竟然需要9s

in_array是这个样子的

复制代码 代码如下:

bool in_array ( mixed $needle , array $haystack [, bool $strict = FALSE ] )

在 haystack 中搜索 needle,如果没有设置 strict 则使用宽松的比较。

needle

待搜索的值。如果 needle 是字符串,则比较是区分大小写的。

haystack

这个数组。

strict

如果第三个参数 strict 的值为 TRUE 则 in_array() 函数还会检查 needle 的类型是否和 haystack 中的相同。

那么我看一下源代码

第一步 在ext/standard/array.c 文件中

/* }}} */  /* {{{ proto bool in_array(mixed needle, array haystack [, bool strict]) Checks if the given value exists in the array */   PHP_FUNCTION(in_array)          {     php_search_array(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0); }    /* }}} */ /* {{{ proto mixed array_search(mixed needle, array haystack [, bool strict]) Searches the array for a given value and returns the corresponding key if successful */PHP_FUNCTION(array_search)         { php_search_array(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1); }    /* }}} */ 

顺便看到了array_search,原来和in_array的内部实现基本一致

其中函数的参数 在./zend.h中

#define INTERNAL_FUNCTION_PARAM_PASSTHRU ht, return_value, return_value_ptr, this_ptr, return_value_used TSRMLS_CC

第二步 在ext/standard/array.c 文件中 查看php_search_array原型

/* void php_search_array(INTERNAL_FUNCTION_PARAMETERS, int behavior) * 0 = return boolean * 1 = return key */  static void php_search_array(INTERNAL_FUNCTION_PARAMETERS, int behavior) /* {{{ */{   zval *value,   /* value to check for */   *array,   /* array to check in */   **entry,   /* pointer to array entry */   res;    /* comparison result */ HashPosition pos;  /* hash iterator */ zend_bool strict = 0;  /* strict comparison or not */ ulong num_key; uint str_key_len; char *string_key; int (*is_equal_func)(zval *, zval *, zval * TSRMLS_DC) = is_equal_function; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "za|b", &value, &array, &strict) == FAILURE) {  return; }  if (strict) {  is_equal_func = is_identical_function; }  zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(array), &pos); while (zend_hash_get_current_data_ex(Z_ARRVAL_P(array), (void **)&entry, &pos) == SUCCESS) {  is_equal_func(&res, value, *entry TSRMLS_CC);  if (Z_LVAL(res)) {   if (behavior == 0) {    RETURN_TRUE;   } else {    /* Return current key */    switch (zend_hash_get_current_key_ex(Z_ARRVAL_P(array), &string_key, &str_key_len, &num_key, 0, &pos)) {     case HASH_KEY_IS_STRING:      RETURN_STRINGL(string_key, str_key_len - 1, 1);      break;     case HASH_KEY_IS_LONG:      RETURN_LONG(num_key);      break;    }   }  }  zend_hash_move_forward_ex(Z_ARRVAL_P(array), &pos); }  RETURN_FALSE;}  /* }}} *//* {{{ proto bool in_array(mixed needle, array haystack [, bool strict]) Checks if the given value exists in the array */

我们发现 strict  这个值的不同有两种比较方式,看一下两个函数的不同之处

is_identical_function 检查类型是否相同

ZEND_API int is_identical_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */{   Z_TYPE_P(result) = IS_BOOL; if (Z_TYPE_P(op1) != Z_TYPE_P(op2)) {  Z_LVAL_P(result) = 0;  return SUCCESS; }  switch (Z_TYPE_P(op1)) {  case IS_NULL:   Z_LVAL_P(result) = 1;   break;  case IS_BOOL:  case IS_LONG:  case IS_RESOURCE:   Z_LVAL_P(result) = (Z_LVAL_P(op1) == Z_LVAL_P(op2));   break;  case IS_DOUBLE:   Z_LVAL_P(result) = (Z_DVAL_P(op1) == Z_DVAL_P(op2));   break;  case IS_STRING:   Z_LVAL_P(result) = ((Z_STRLEN_P(op1) == Z_STRLEN_P(op2))   && (!memcmp(Z_STRVAL_P(op1), Z_STRVAL_P(op2), Z_STRLEN_P(op1))));   break;  case IS_ARRAY:   Z_LVAL_P(result) = (Z_ARRVAL_P(op1) == Z_ARRVAL_P(op2)   zend_hash_compare(Z_ARRVAL_P(op1), Z_ARRVAL_P(op2), (compare_func_t) hash_zval_identical_function, 1 TSRMLS_CC)==0);   break;  case IS_OBJECT:   if (Z_OBJ_HT_P(op1) == Z_OBJ_HT_P(op2)) {   Z_LVAL_P(result) = (Z_OBJ_HANDLE_P(op1) == Z_OBJ_HANDLE_P(op2));   } else {   Z_LVAL_P(result) = 0;   }   break;  default:   Z_LVAL_P(result) = 0;   return FAILURE; }  return SUCCESS;}  /* }}} */

is_equal_function 不检查类型是否相同,所以需要隐式转换

ZEND_API int is_equal_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */{   if (compare_function(result, op1, op2 TSRMLS_CC) == FAILURE) {  return FAILURE; }  ZVAL_BOOL(result, (Z_LVAL_P(result) == 0)); return SUCCESS;}  /* }}} */==》compare_functionZEND_API int compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */{    int ret; int converted = 0; zval op1_copy, op2_copy; zval *op_free; while (1) {  switch (TYPE_PAIR(Z_TYPE_P(op1), Z_TYPE_P(op2))) {   case TYPE_PAIR(IS_LONG, IS_LONG):   ZVAL_LONG(result, Z_LVAL_P(op1)>Z_LVAL_P(op2)?1:(Z_LVAL_P(op1)compare_objects(op1, op2 TSRMLS_CC));    return SUCCESS;   }   /* break missing intentionally */   default:   if (Z_TYPE_P(op1) == IS_OBJECT) {    if (Z_OBJ_HT_P(op1)->get) {     op_free = Z_OBJ_HT_P(op1)->get(op1 TSRMLS_CC);     ret = compare_function(result, op_free, op2 TSRMLS_CC);     zend_free_obj_get_result(op_free TSRMLS_CC);     return ret;    } else if (Z_TYPE_P(op2) != IS_OBJECT && Z_OBJ_HT_P(op1)->cast_object) {     ALLOC_INIT_ZVAL(op_free);     if (Z_OBJ_HT_P(op1)->cast_object(op1, op_free, Z_TYPE_P(op2) TSRMLS_CC) == FAILURE) {      ZVAL_LONG(result, 1);      zend_free_obj_get_result(op_free TSRMLS_CC);      return SUCCESS;     }     ret = compare_function(result, op_free, op2 TSRMLS_CC);     zend_free_obj_get_result(op_free TSRMLS_CC);     return ret;    }   }   if (Z_TYPE_P(op2) == IS_OBJECT) {    if (Z_OBJ_HT_P(op2)->get) {     op_free = Z_OBJ_HT_P(op2)->get(op2 TSRMLS_CC);     ret = compare_function(result, op1, op_free TSRMLS_CC);     zend_free_obj_get_result(op_free TSRMLS_CC);     return ret;    } else if (Z_TYPE_P(op1) != IS_OBJECT && Z_OBJ_HT_P(op2)->cast_object) {     ALLOC_INIT_ZVAL(op_free);     if (Z_OBJ_HT_P(op2)->cast_object(op2, op_free, Z_TYPE_P(op1) TSRMLS_CC) == FAILURE) {      ZVAL_LONG(result, -1);      zend_free_obj_get_result(op_free TSRMLS_CC);      return SUCCESS;     }     ret = compare_function(result, op1, op_free TSRMLS_CC);     zend_free_obj_get_result(op_free TSRMLS_CC);     return ret;    } else if (Z_TYPE_P(op1) == IS_OBJECT) {     ZVAL_LONG(result, 1);     return SUCCESS;    }   }   if (!converted) {    if (Z_TYPE_P(op1) == IS_NULL) {     zendi_convert_to_boolean(op2, op2_copy, result);     ZVAL_LONG(result, Z_LVAL_P(op2) ? -1 : 0);     return SUCCESS;    } else if (Z_TYPE_P(op2) == IS_NULL) {     zendi_convert_to_boolean(op1, op1_copy, result);     ZVAL_LONG(result, Z_LVAL_P(op1) ? 1 : 0);     return SUCCESS;    } else if (Z_TYPE_P(op1) == IS_BOOL) {     zendi_convert_to_boolean(op2, op2_copy, result);     ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_LVAL_P(op1) - Z_LVAL_P(op2)));     return SUCCESS;    } else if (Z_TYPE_P(op2) == IS_BOOL) {     zendi_convert_to_boolean(op1, op1_copy, result);     ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_LVAL_P(op1) - Z_LVAL_P(op2)));     return SUCCESS;    } else {     zendi_convert_scalar_to_number(op1, op1_copy, result);     zendi_convert_scalar_to_number(op2, op2_copy, result);     converted = 1;    }   } else if (Z_TYPE_P(op1)==IS_ARRAY) {    ZVAL_LONG(result, 1);    return SUCCESS;   } else if (Z_TYPE_P(op2)==IS_ARRAY) {    ZVAL_LONG(result, -1);    return SUCCESS;   } else if (Z_TYPE_P(op1)==IS_OBJECT) {    ZVAL_LONG(result, 1);    return SUCCESS;   } else if (Z_TYPE_P(op2)==IS_OBJECT) {    ZVAL_LONG(result, -1);    return SUCCESS;   } else {    ZVAL_LONG(result, 0);    return FAILURE;   }  }  }  }   /* }}} */

您可能感兴趣的文章:

  • php natsort内核函数浅析
  • php in_array 函数使用说明与in_array需要注意的地方说明
  • PHP数组的交集array_intersect(),array_intersect_assoc(),array_inter_key()函数的小问题
  • php array_intersect比array_diff快(附详细的使用说明)
  • PHP内核介绍及扩展开发指南―基础知识
  • php数组函数序列之in_array() 查找数组值是否存在
  • php数组函数序列之array_combine() - 数组合并函数使用说明
  • php数组函数序列之in_array() - 查找数组中是否存在指定值
  • php数组函数序列之array_intersect() 返回两个或多个数组的交集数组
  • 使用js判断数组中是否包含某一元素(类似于php中的in_array())
  • PHP内核探索:变量存储与类型使用说明
  • PHP内核探索:变量概述
  • php内核解析:PHP中的哈希表
  • 2个自定义的PHP in_array 函数,解决大量数据判断in_array的效率问题
  • php数组查找函数in_array()、array_search()、array_key_exists()使用实例
  • PHP函数in_array()使用详解
  • php提示Warning:mysql_fetch_array() expects的解决方法
  • PHP内核探索:哈希表碰撞攻击原理
  • 深入理解PHP内核(一)
  • 深入理解PHP内核(二)之SAPI探究


  • 上一条:
    PHP防止刷新重复提交页面的示例代码
    下一条:
    php实现可运算的验证码
  • 昵称:

    邮箱:

    0条评论 (评论内容有缓存机制,请悉知!)
    最新最热
    • 分类目录
    • 人生(杂谈)
    • 技术
    • linux
    • Java
    • php
    • 框架(架构)
    • 前端
    • ThinkPHP
    • 数据库
    • 微信(小程序)
    • Laravel
    • Redis
    • Docker
    • Go
    • swoole
    • Windows
    • Python
    • 苹果(mac/ios)
    • 相关文章
    • Laravel从Accel获得5700万美元A轮融资(0个评论)
    • PHP 8.4 Alpha 1现已发布!(0个评论)
    • 用Time Warden监控PHP中的代码处理时间(0个评论)
    • 在PHP中使用array_pop + yield实现读取超大型目录功能示例(0个评论)
    • Property Hooks RFC在PHP 8.4中越来越接近现实(0个评论)
    • 近期文章
    • 在windows10中升级go版本至1.24后LiteIDE的Ctrl+左击无法跳转问题解决方案(0个评论)
    • 智能合约Solidity学习CryptoZombie第四课:僵尸作战系统(0个评论)
    • 智能合约Solidity学习CryptoZombie第三课:组建僵尸军队(高级Solidity理论)(0个评论)
    • 智能合约Solidity学习CryptoZombie第二课:让你的僵尸猎食(0个评论)
    • 智能合约Solidity学习CryptoZombie第一课:生成一只你的僵尸(0个评论)
    • 在go中实现一个常用的先进先出的缓存淘汰算法示例代码(0个评论)
    • 在go+gin中使用"github.com/skip2/go-qrcode"实现url转二维码功能(0个评论)
    • 在go语言中使用api.geonames.org接口实现根据国际邮政编码获取地址信息功能(1个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf分页文件功能(95个评论)
    • gmail发邮件报错:534 5.7.9 Application-specific password required...解决方案(0个评论)
    • 近期评论
    • 122 在

      学历:一种延缓就业设计,生活需求下的权衡之选中评论 工作几年后,报名考研了,到现在还没认真学习备考,迷茫中。作为一名北漂互联网打工人..
    • 123 在

      Clash for Windows作者删库跑路了,github已404中评论 按理说只要你在国内,所有的流量进出都在监控范围内,不管你怎么隐藏也没用,想搞你分..
    • 原梓番博客 在

      在Laravel框架中使用模型Model分表最简单的方法中评论 好久好久都没看友情链接申请了,今天刚看,已经添加。..
    • 博主 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 @1111老铁这个不行了,可以看看近期评论的其他文章..
    • 1111 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 网站不能打开,博主百忙中能否发个APP下载链接,佛跳墙或极光..
    • 2016-10
    • 2016-11
    • 2017-06
    • 2017-07
    • 2017-08
    • 2017-09
    • 2017-11
    • 2017-12
    • 2018-01
    • 2018-02
    • 2018-03
    • 2020-03
    • 2020-04
    • 2020-05
    • 2020-06
    • 2020-07
    • 2020-09
    • 2021-02
    • 2021-03
    • 2021-04
    • 2021-05
    • 2021-06
    • 2021-07
    • 2021-08
    • 2021-09
    • 2021-10
    • 2021-11
    • 2021-12
    • 2022-01
    • 2022-02
    • 2022-05
    • 2022-06
    • 2022-07
    • 2022-08
    • 2022-09
    • 2022-10
    • 2022-11
    • 2022-12
    • 2023-01
    • 2023-02
    • 2023-03
    • 2023-04
    • 2023-05
    • 2023-06
    • 2023-07
    • 2023-08
    • 2023-09
    • 2023-10
    • 2023-11
    • 2023-12
    • 2024-01
    • 2024-02
    • 2024-03
    • 2024-04
    • 2024-05
    • 2024-06
    • 2024-07
    • 2024-09
    Top

    Copyright·© 2019 侯体宗版权所有· 粤ICP备20027696号 PHP交流群

    侯体宗的博客