- 需求:和客户端传输数据的字段名需要使用小驼峰命名。客户端使用小驼峰,服务端PHP使用下划线命名。示例:图片链接 imgUrl。客户端传过来的小驼峰字段转换成下划线格式 img_url。
- PHP实现:
/** * 下划线转小驼峰, 数组是对键名进行转换,数组值不变 * 转换结果举例 * little_boy => littleBoy * _title => title * title_ => title * _title_ => title * little__boy => littleBoy * title_boy__girl_中文_title => titleBoyGirl中文Title * @param string|array $data * @return mixed * @throws */ function underline2Camel($data) { if (is_string($data)) { $_data = explode('_', $data); $count = count($_data); if ($count == 1) { // 没有“_”情况, 原样返回 return $data; } // 下划线分隔的单词,除第一个外,其余首字母转大写就实现了下划线转驼峰需求。特殊字符不变。 $new_str = $_data[0]; $start = 1; // 处理第一个字符是 “_” 的情况, 不能转换成大驼峰。示例:_title 要转成 title 而不是 Title if ($data[0] == '_') { $new_str .= $_data[1]; $start = 2; } for ($i = $start; $i < $count; $i++) { $_data[$i] = ucfirst($_data[$i]); $new_str .= $_data[$i]; } return $new_str; } elseif (is_array($data)) { foreach ($data as $k => $v) { if (is_array($v)) { // 如果是多维数组,递归转换 $_k = self::underline2Camel($k); $data[$_k] = self::underline2Camel($v); unset($data[$k]); } else { // 数组下标如果是数字,则不处理 if (is_numeric($k)) { continue; } $_k = self::underline2Camel($k); $data[$_k] = $data[$k]; unset($data[$k]); } } return $data; } else { throw new \Exception('不支持的数据类型:' . gettype($data)); } }
/** * 驼峰转下划线, 数组是对键名进行转换,值不变 * littleBoy => little_boy * @param string|array $data * @return mixed * @throws */ function camel2Underline($data) { if (is_string($data)) { $data = trim($data); $len = strlen($data); // 首字母是大写的情况,首字母直接转小写不加下划线 $new_str = (ord($data[0]) >= 65 && ord($data[0]) <= 90) ? chr(ord($data[0]) + 32) : $data[0]; for ($i = 1; $i < $len; $i++) { $ascii = ord($data[$i]); if ($ascii >= 65 && $ascii <= 90) { $new_str .= '_' . chr($ascii + 32); } else { $new_str .= $data[$i]; } } return $new_str; } elseif (is_array($data)) { foreach ($data as $k => $v) { // 处理多维数组的情况 if (is_array($v)) { $_k = self::camel2Underline($k); $data[$_k] = self::camel2Underline($v); unset($data[$k]); } else { // 数组下标如果是数字,则不处理 if (is_numeric($k)) { continue; } $_k = self::camel2Underline($k); $data[$_k] = $data[$k]; unset($data[$k]); } } return $data; } else { throw new \Exception('不支持的数据类型:' . gettype($data)); } }
- 更新:上面的版本不支持下标为数字的多维数组,比如下面的数组下标2对应的数组:
$data = ['img_url' => 'dssd', 'user_name' => 'dfd', 1 => 'asd', 2 => ['u_a' => 'xcz'], 'user_bb' => ['aa_cc' => 'xxx', 'cc_dd' => ['ee_ff' => 'fds']]];
也不支持数组下标为全小写的数组,比如下面数组下标username对应的数组:
$data = ['img_url' => 'dssd', 'username' => 'dfd', 1 => 'asd', 2 => ['u_a' => 'xcz'], 'user_bb' => ['aa_cc' => 'xxx', 'cc_dd' => ['ee_ff' => 'fds']]];
在之前版本中上面的两种情况会被过滤掉,新版兼容了这两种情况。并增加了一些测试的例子。新版使用类的形式。
class Util { /** * 下划线转小驼峰, 数组是对键名进行转换,数组值不变 * 转换结果举例 * little_boy => littleBoy * _title => title * title_ => title * _title_ => title * little__boy => littleBoy * title_boy__girl_中文_title => titleBoyGirl中文Title * @param string|array $data * @return mixed * @throws */ public static function underline2Camel($data) { if (is_string($data)) { $_data = explode('_', $data); $count = count($_data); if ($count == 1) { // 没有“_”情况, 原样返回 return $data; } // 下划线分隔的单词,除第一个外,其余首字母转大写就实现了下划线转驼峰需求。特殊字符不变。 $new_str = $_data[0]; $start = 1; // 处理第一个字符是 “_” 的情况, 不能转换成大驼峰。示例:_title 要转成 title 而不是 Title if ($data[0] == '_') { $new_str .= $_data[1]; $start = 2; } for ($i = $start; $i < $count; $i++) { $_data[$i] = ucfirst($_data[$i]); $new_str .= $_data[$i]; } return $new_str; } elseif (is_array($data)) { foreach ($data as $k => $v) { if (is_array($v)) { // 如果是多维数组,递归转换.(如果下标是数字的值又是一个数组,那么仍需要递归转换,数字保留不变) $_k = is_numeric($k) ? $k : self::underline2Camel($k); $data[$_k] = self::underline2Camel($v); if (!is_numeric($k)) unset($data[$k]); // 数组下标为数字的不能删除,因为$k == $_k } else { // 数组下标如果是数字,则不处理 if (is_numeric($k)) { continue; } $_k = self::underline2Camel($k); $data[$_k] = $data[$k]; if ($k !== $_k) unset($data[$k]); } } return $data; } else { throw new \Exception('不支持的数据类型:' . gettype($data)); } } /** * 驼峰转下划线, 数组是对键名进行转换,值不变 * littleBoy => little_boy * @param string|array $data * @return mixed * @throws */ public static function camel2Underline($data) { if (is_string($data)) { $data = trim($data); $len = strlen($data); // 首字母是大写的情况,首字母直接转小写不加下划线 $new_str = (ord($data[0]) >= 65 && ord($data[0]) <= 90) ? chr(ord($data[0]) + 32) : $data[0]; for ($i = 1; $i < $len; $i++) { $ascii = ord($data[$i]); if ($ascii >= 65 && $ascii <= 90) { $new_str .= '_' . chr($ascii + 32); } else { $new_str .= $data[$i]; } } return $new_str; } elseif (is_array($data)) { foreach ($data as $k => $v) { // 处理多维数组的情况 if (is_array($v)) { // 如果是多维数组,递归转换.(如果下标是数字的值又是一个数组,那么仍需要递归转换,数字保留不变) $_k = is_numeric($k) ? $k : self::camel2Underline($k); $data[$_k] = self::camel2Underline($v); if (!is_numeric($k)) unset($data[$k]); // 数组下标为数字的不能删除,因为$k == $_k } else { // 数组下标如果是数字,则不处理 if (is_numeric($k)) { continue; } $_k = self::camel2Underline($k); $data[$_k] = $data[$k]; if ($k !== $_k) unset($data[$k]); // 数组下标如果是全小写,例如:uid,是不能删除的。要保留 } } return $data; } else { throw new \Exception('不支持的数据类型:' . gettype($data)); } } // 测试 public static function testUnderline2Camel() { $str1 = '_title'; $str2 = 'title_'; $str3 = '_title_'; $str4 = 'title_boy__girl_中文_title'; $data = ['img_url' => 'dssd', 'user_name' => 'dfd', 1 => 'asd', 2 => ['u_a' => 'xcz'], 'user_bb' => ['aa_cc' => 'xxx', 'cc_dd' => ['ee_ff' => 'fds']]]; $data = ['img_url' => 'dssd', 'username' => 'dfd', 1 => 'asd', 2 => ['u_a' => 'xcz'], 'user_bb' => ['aa_cc' => 'xxx', 'cc_dd' => ['ee_ff' => 'fds']]]; dump(Util::underline2Camel($str1)); dump(Util::underline2Camel($str2)); dump(Util::underline2Camel($str3)); dump(Util::underline2Camel($str4)); dump(Util::underline2Camel($data)); dump(Util::camel2Underline(Util::underline2Camel($data))); dump(Util::camel2Underline(Util::underline2Camel($str4))); dump(Util::camel2Underline(Util::underline2Camel($str3))); die(); } }
- 2022/8/18更新:发现了一个小bug:当传入的参数是数组并且索引是驼峰的情况下,驼峰索引对应的元素值会被删掉。已修复
class Util { /** * 下划线转小驼峰, 数组是对键名进行转换,数组值不变 * 转换结果举例 * little_boy => littleBoy * _title => title * title_ => title * _title_ => title * little__boy => littleBoy * title_boy__girl_中文_title => titleBoyGirl中文Title * @param string|array $data * @return mixed * @throws */ public static function underline2Camel($data) { if (is_string($data)) { $_data = explode('_', $data); $count = count($_data); if ($count == 1) { // 没有“_”情况, 原样返回 return $data; } // 下划线分隔的单词,除第一个外,其余首字母转大写就实现了下划线转驼峰需求。特殊字符不变。 $new_str = $_data[0]; $start = 1; // 处理第一个字符是 “_” 的情况, 不能转换成大驼峰。示例:_title 要转成 title 而不是 Title if ($data[0] == '_') { $new_str .= $_data[1]; $start = 2; } for ($i = $start; $i < $count; $i++) { $_data[$i] = ucfirst($_data[$i]); $new_str .= $_data[$i]; } return $new_str; } elseif (is_array($data)) { foreach ($data as $k => $v) { if (is_array($v)) { // 如果是多维数组,递归转换.(如果下标是数字的值又是一个数组,那么仍需要递归转换,数字保留不变) $_k = is_numeric($k) ? $k : self::underline2Camel($k); $data[$_k] = self::underline2Camel($v); if ($k !== $_k) unset($data[$k]); } else { // 数组下标如果是数字,则不处理 if (is_numeric($k)) { continue; } $_k = self::underline2Camel($k); $data[$_k] = $data[$k]; if ($k !== $_k) unset($data[$k]); } } return $data; } else { // throw new \Exception('不支持的数据类型:' . gettype($data)); // 考虑到数组中某个元素值可能会包含对象,这种情况不能抛出异常不合理。改成原样返回数据,不做处理。 return $data; } } /** * 驼峰转下划线, 数组是对键名进行转换,值不变 * littleBoy => little_boy * @param string|array $data * @return mixed * @throws */ public static function camel2Underline($data) { if (is_string($data)) { $data = trim($data); $len = strlen($data); // 首字母是大写的情况,首字母直接转小写不加下划线 $new_str = (ord($data[0]) >= 65 && ord($data[0]) <= 90) ? chr(ord($data[0]) + 32) : $data[0]; for ($i = 1; $i < $len; $i++) { $ascii = ord($data[$i]); if ($ascii >= 65 && $ascii <= 90) { $new_str .= '_' . chr($ascii + 32); } else { $new_str .= $data[$i]; } } return $new_str; } elseif (is_array($data)) { foreach ($data as $k => $v) { // 处理多维数组的情况 if (is_array($v)) { // 如果是多维数组,递归转换.(如果下标是数字的值又是一个数组,那么仍需要递归转换,数字保留不变) $_k = is_numeric($k) ? $k : self::camel2Underline($k); $data[$_k] = self::camel2Underline($v); if ($k !== $_k) unset($data[$k]); // 数组下标为数字的不能删除,因为$k == $_k } else { // 数组下标如果是数字,则不处理 if (is_numeric($k)) { continue; } $_k = self::camel2Underline($k); $data[$_k] = $data[$k]; if ($k !== $_k) unset($data[$k]); // 数组下标如果是全小写,例如:uid,是不能删除的。要保留 } } return $data; } else { // throw new \Exception('不支持的数据类型:' . gettype($data)); return $data; } } // 测试 public static function testUnderline2Camel() { $str1 = '_title'; $str2 = 'title_'; $str3 = '_title_'; $str4 = 'title_boy__girl_中文_title'; $data = ['img_url' => 'dssd', 'user_name' => 'dfd', 1 => 'asd', 2 => ['u_a' => 'xcz'], 'user_bb' => ['aa_cc' => 'xxx', 'cc_dd' => ['ee_ff' => 'fds']]]; $data = ['img_url' => 'dssd', 'username' => 'dfd', 1 => 'asd', 2 => ['u_a' => 'xcz'], 'user_bb' => ['aa_cc' => 'xxx', 'cc_dd' => ['ee_ff' => 'fds']]]; dump(Util::underline2Camel($str1)); dump(Util::underline2Camel($str2)); dump(Util::underline2Camel($str3)); dump(Util::underline2Camel($str4)); dump(Util::underline2Camel($data)); dump(Util::camel2Underline(Util::underline2Camel($data))); dump(Util::camel2Underline(Util::underline2Camel($str4))); dump(Util::camel2Underline(Util::underline2Camel($str3))); die(); } }