目前主流的删除数组子元素的方法,都是只能删除第一层级的子元素,通过下面的源码可以实现删除任意层级的数据子元素。
源码
$array = [
'a' => [
'b' => [
'c' => 'd',
'e' => 'f'
]
],
'g' => [
'h' => 'i'
]
];
$deleteKey = 'a.b.c';
$keyArray = explode('.', $deleteKey);
//change a.b.c value
$result['change'] = recurArrayDiff($array, $keyArray, 'change a.b.c value');
//delete a.b.c
$result['delete'] = recurArrayDiff($array, $keyArray);
echo json_encode($result);
function recurArrayDiff($array, $keyArray, $replace = null)
{
$key0 = $keyArray[0];
if (is_array($array) && isset($keyArray[1])) {
unset($keyArray[0]);
$keyArray = array_values($keyArray);
if (!isset($array[$key0])) {
$array[$key0] = [];
}
$array[$key0] = recurArrayDiff($array[$key0], $keyArray, $replace);
} else {
if (is_null($replace)) {
unset($array[$key0]);
} else {
$array[$key0] = $replace;
}
}
return $array;
}
输出
{
"change": {
"a": {
"b": {
"c": "change a.b.c value",
"e": "f"
}
},
"g": {
"h": "i"
}
},
"delete": {
"a": {
"b": {
"e": "f"
}
},
"g": {
"h": "i"
}
}
}
升级版
封装为一个类,支持数组任意层级子元素的增删改查
源码
<?php
namespace api\tool\lib;
/**
* 数组操作类
* @desc 支持任意层级子元素的增删改查
* @package library\logic
*/
class ArrayTool implements \ArrayAccess
{
public static function instance($array = [], $separator = '.')
{
return new self($array, $separator);
}
private $array;
private $separator;
public function __construct($array, $separator = '.')
{
$this->array = $array;
$this->separator = $separator;
}
/**
* 设置任意层级子元素
* @param string|array|int $key
* @param mixed $value
* @return $this
*/
public function set($key, $value = null)
{
if (is_array($key)) {
foreach ($key as $k => $v) {
$this->set($k, $v);
}
} else {
if (false === strpos($key, $this->separator)) {
$this->array[$key] = $value;
} else {
$keyArray = explode($this->separator, $key);
$this->array = $this->recurArrayChange($this->array, $keyArray, $value);
}
}
return $this;
}
/**
* 获取任意层级子元素
* @param null|string|int $key
* @param mixed $default
* @return mixed
*/
public function get($key = null, $default = null)
{
if (is_null($key)) {
return $this->array;
}
if (false === strpos($key, $this->separator)) {
return isset($this->array[$key]) ? $this->array[$key] : $default;
}
$keyArray = explode($this->separator, $key);
$tmp = $this->array;
foreach ($keyArray as $k) {
if (isset($tmp[$k])) {
$tmp = $tmp[$k];
} else {
$tmp = $default;
break;
}
}
return $tmp;
}
/**
* 删除任意层级子元素
* @param string|array|int $key
* @return $this
*/
public function delete($key)
{
if (is_array($key)) {
foreach ($key as $k) {
$this->set($k, null);
}
} else {
$this->set($key, null);
}
return $this;
}
/**
* 获取某一节点下的子元素key列表
* @param $key
* @return array
*/
public function getChildKeyList($key)
{
$child = $this->get($key);
$list = [];
$n = 0;
foreach ($child as $k => $v) {
$list[$n++] = $k;
}
return $list;
}
/**
* 递归遍历
* @param array $array
* @param array $keyArray
* @param mixed $value
* @return array
*/
private function recurArrayChange($array, $keyArray, $value = null)
{
$key0 = $keyArray[0];
if (is_array($array) && isset($keyArray[1])) {
unset($keyArray[0]);
$keyArray = array_values($keyArray);
if (!isset($array[$key0])) {
$array[$key0] = [];
}
$array[$key0] = $this->recurArrayChange($array[$key0], $keyArray, $value);
} else {
if (is_null($value)) {
unset($array[$key0]);
} else {
$array[$key0] = $value;
}
}
return $array;
}
/**
* isset($array[$key])
* @param mixed $offset
* @return bool
*/
public function offsetExists($offset)
{
return !is_null($this->get($offset));
}
/**
* $array[$key]
* @param mixed $offset
* @return mixed
*/
public function offsetGet($offset)
{
return $this->get($offset);
}
/**
* $array[$key] = $value
* @param mixed $offset
* @param mixed $value
* @return $this
*/
public function offsetSet($offset, $value)
{
return $this->set($offset, $value);
}
/**
* unset($array[$key])
* @param mixed $offset
* @return $this
*/
public function offsetUnset($offset)
{
return $this->delete($offset);
}
}
使用示例
//instance
$array = ArrayTool::instance([], $separator = '.');
//set
$array->set('a1.b1', 'c1');
$array['a2.b2'] = 'c2';
//get
echo $array->get('a1.b1');
echo $array['a2.b2'];
//get all
$array->get();
//get child key list
$array->getChildKeyList('a1');
//delete
$array->delete('a1.b1');
unset($array['a2.b2']);