今天,因为要开发一个根据ip获取地理位置的需求,在网上查询资料的时候发现 淘宝的、新浪的、腾讯的地址都不可用了,百度的要申请参数。于是就使用了一个三方库,
composer require torann/geoip
然后就炸了,命令行弹出错误提示:undefind index:name.
整个项目都瘫痪了,这种情况基本都是自动加载出问题了,刚开始在网上找解决方案。都说吧composer 降一下版本就可以,这种解决方案想来是可以的,但是我没有去尝试,而是通过源码看了一下问题如何产生的。
首先第一步,我们根据错误提示找到错误位置:
/vendor/laravel/framework/src/Illuminate/Foundation/PackageManifest.php
我们找到121行左右看到以下代码:
$this->write(collect($packages)->mapWithKeys(function ($package) {
return [$this->format($package['name']) => $package['extra']['laravel'] ?? []];
})->each(function ($configuration) use (&$ignore) {
$ignore = array_merge($ignore, $configuration['dont-discover'] ?? []);
})->reject(function ($configuration, $package) use ($ignore, $ignoreAll) {
return $ignoreAll || in_array($package, $ignore);
})->filter()->all());
错误就是这里报出来的,就是package没有name这个key导致的,我们打印一下package的值,这个时候我们发现package的值是一个索引数组,它没有name下标,反而它的每一个子元素很符合执行接下来的代码的要求。package是通过闭包传递的,我们查看一下mapWithKeys函数的实现:
public function mapWithKeys(callable $callback)
{
$result = [];
foreach ($this->items as $key => $value) {
$assoc = $callback($value, $key);
foreach ($assoc as $mapKey => $mapValue) {
$result[$mapKey] = $mapValue;
}
}
return new static($result);
}
这里,使用循环迭代执行callback函数,也就是上边的mapWithKeys中的匿名函数 ,value就对应上面的package,我们打印一下$this->item 的值。发现它不是一个索引数组:
[
'package' => [
[],[].....
]
]
到这里问题就很明了了,callback的参数本来应该是子元素,结果这里因为$this->item的数据结构外面包了一层package,所导致便利的时候吧整个数组传递过去了,所以出现的undefind index : name的提示,我们直接修改源码
public function mapWithKeys(callable $callback)
{
$result = [];
$item = $this->items;
if(isset($item['packages'])){
$item = $item['packages'];
}
foreach ($item as $key => $value) {
$assoc = $callback($value, $key);
foreach ($assoc as $mapKey => $mapValue) {
$result[$mapKey] = $mapValue;
}
}
return new static($result);
}
这里做一下兼容就可以。修改之后调试,运行无误。
总结:
找到目录:
/vendor/laravel/framework/src/Illuminate/Support/Collection.php
找到方法
mapWithKeys
用上面的方法替代原来的方法。
完成!
目前并不知道会不会出现其他的问题,如果有小伙伴用上面的方法,出现了其他问题,欢迎来一起讨论。