抛出问题
数组下标越界真的是开发过程中的痛,除了在开发过程中各种判断是否设置,是否为空,还有其他优雅的办法解决吗?
回答问题
肯定是有的
举个栗子
比如,我有一个工具性质的方法如下:
我怎么保证 $batchUserCover[$userid]['pickedFootprint']
和 $batchFootprintList[$userid]['list']
不会有下标越界的问题呢?
//批量获得图片故事 优先精选故事 不足三个拼接最近发布的故事 public static function batchImageFootprint($userIds, $batchUserCover, $batchFootprintList) { $ret = []; foreach ($userIds as $userid) { $ret[$userid] = array_slice(array_merge($batchUserCover[$userid]['pickedFootprint'], array_slice($batchFootprintList[$userid]['list'], 0, 3)), 0, 3); } return $ret; }
解题思路
- 在方法外判断是否设置值
- 在方法外保证已经设置值,确保
$batchUserCover[$userid]['pickedFootprint']
这类参数一定是存在的,已经设置了的.
我认为思路2更好
解题实践
实践1:
在传入数据之前,设置好传入值,保证传入值的key必须存在,值可以为null,或者空数组。 核心代码如下:
public static function batchFormatCoverAndPickedFootprint($userListInfo) { foreach ($userListInfo as &$element) { $retData[$element['userid']] = [ 'pickedFootprint' => [], 'coverFootprint' => [], ]; } . . . return $retData; }
传入的数组的key必然符合[$userid]['pickedFootprint']
,不会存在数组下标越界
$batchUserCover = batchFormatCoverAndPickedFootprint(xxx); self::batchImageFootprint($userIds, $batchUserCover);
实践2:
和实践1的底层思路是一致的,区别在于实践1是在函数内首先定义了符合规范的初始值
实践2是先处理业务逻辑,在return之前定义了符合规范的初始值
(下面代码段写了注释,重点看后半部分;联合查询那部分代码质量也不错,没省略掉,看能不能抛转引玉。)
public static function batchFootprintList($userIds, $pageCount = 21, $batchPickedFootprints = [], $select = 'userid,id,mid,image,text,ST_Astext(picgeom) as "picgeom",poi,poiid,city,province,country,pictime') { . . . //联合查询 $union = self::query()->selectRaw($select)->where('userid', $userIds[0]) ->where('status', self::TYPE_STATUS_NORMAL) ->whereNotIn('mid', $batchPickedFootprints[$userIds[0]]) ->orderBy('id', 'desc') ->limit($pageCount); //避免重复查询第一条数据 unset($userIds[0]); foreach ($userIds as $userId) { $unionItem = self::query()->selectRaw($select)->where('userid', $userId) ->where('status', self::TYPE_STATUS_NORMAL) ->whereNotIn('mid', $batchPickedFootprints[$userId]) ->orderBy('id', 'desc') ->limit($pageCount); $union->unionAll($unionItem); } $allUserFootprints = $union->get()->toArray(); $res = []; $chunkFootprintByUserid = self::_chunkFootprintByUserid($allUserFootprints); // 重点在这里 foreach ($allUserIds as $userId) { $list = $chunkFootprintByUserid[$userId] ?? []; $count = count($list); //以此保证不会出现数据下标越界的问题 $res[$userId]['list'] = $list; $res[$userId]['more'] = $count < $pageCount ? 0 : 1; $res[$userId]['track'] = $count > 0 ? (string)$list[$count - 1]['id'] : ''; } return $res; }