合并 3 个集合以每行返回一个对象
Posted
技术标签:
【中文标题】合并 3 个集合以每行返回一个对象【英文标题】:Merging 3 collections to return one object per row 【发布时间】:2019-12-31 03:31:13 【问题描述】:我正在使用 axios 将城镇、州和国家返回到 Vue 2 自动完成字段。查询的字段都在同一个表中;地点。如果我只返回城镇,该领域的效果很好,但世界上有很多城镇同名,所以我想返回城镇所在的州/地区和国家/地区。我遇到的问题是让我的控制器为城镇、州和国家输出一个对象,而不是将它们合并为单独的对象。
我尝试过使用 Eloquent 提供的 merge、put 和 combine 方法。 Merge and put 将给我一个包含 6 个对象的数组,其中包含我的测试数据,即伯明翰,因为在英格兰西米德兰兹郡有一个,在美国阿拉巴马州有一个。对象 0 和 1 具有城镇 id、城镇名称和父 id,2 和 3 具有州 id 等,4 和 5 具有国家 id 等。在 Google 和此处搜索大多数说合并的答案,但实际上不会每个单独的集合到一个对象中。
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use \App\Location;
class AjaxLocationsController extends Controller
public function index(Request $request)
$searchquery = $request->searchquery;
$states = collect();
$countries = collect();
$all_details = collect();
$locations = Location::select('id', 'location', 'parent_id')
->where([['id', '>', 4351], ['location', 'like', '%' . $searchquery . '%']])
->orderBy('location')
->get();
foreach($locations as $location)
$state = Location::select('id as state_id', 'location as state', 'parent_id as state_parent_id')
->where('id', '=', $location->parent_id)
->get();
$states->push($state);
$states = $states->flatten();
foreach($states as $state)
$country = Location::select('id as country_id', 'location as country')
->where('id', '=', $state->state_parent_id)
->get();
$countries->push($country);
$countries = $countries->flatten();
$all_details = $all_details->merge($locations);
$all_details = $all_details->merge($states);
$all_details = $all_details->merge($countries);
$all_details = $all_details->flatten();
return $all_details;
我原以为这很容易做到,虽然我对 Laravel (5.8) 很陌生,但我在使用 php 数组方面有很多经验。我想我一定是错过了什么,因为我整天都在做这件事!
任何帮助将不胜感激。
【问题讨论】:
对 PHP 无能为力,但只返回多个对象/多个数组,然后以您想要的任何方式将它们与插槽一起显示并不难。您需要将它们配对,但如果您说一个包含许多较小对象的大对象,那么这将起作用。或索引匹配的并行数组。 感谢您的评论,迈克尔。这几乎是我想要实现的目标,但是以 Eloquent(即 Laravel)的方式。 【参考方案1】:我已经想出了我想说的更像是一种非 Eloquent 的方法,但我会在这里发布我的代码,希望它能帮助其他遇到相同类型问题的人。 ajax 响应非常快(大约 100 毫秒),所以我对结果非常满意。如果其他人有更好(更雄辩)的解决方案,请在此处发布答案。干杯!
Ajax 控制器
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use \App\Location;
class AjaxLocationsController extends Controller
public function index(Request $request)
$searchquery = $request->searchquery;
$states = collect();
$countries = collect();
$all_details = collect();
$counter = 0;
$locations = Location::select('id', 'location', 'parent_id')
->where([['id', '>', 4351], ['location', 'like', '%' . $searchquery . '%']])
->orderBy('location')
->get();
foreach ($locations as $location)
$state = Location::select('id as state_id', 'location as state', 'parent_id as state_parent_id')
->where('id', '=', $location->parent_id)
->get();
$states->push($state);
$states = $states->flatten();
foreach ($states as $state)
$country = Location::select('id as country_id', 'location as country')
->where('id', '=', $state->state_parent_id)
->get();
$countries->push($country);
$countries = $countries->flatten();
foreach ($locations as $location)
$full_location = collect([
'id' => $location->id,
'location' => $location->location,
'parent_id' => $location->parent_id,
'state_id' => $states[$counter]['state_id'],
'state' => $states[$counter]['state'],
'state_parent_id' => $states[$counter]['state_parent_id'],
'country_id' => $countries[$counter]['country_id'],
'country' => $countries[$counter]['country'],
]);
$all_details = $all_details->push($full_location);
$counter++;
return $all_details;
Vue Component
<template>
<div>
<label for="searchquery">Town</label>
<input type="text" v-model="searchquery" v-on:keyup="getLocations" class="form-
control">
<div class="panel-footer" v-if="data_results.length">
<ul class="list-group">
<a href="#" @click="setLocation(result)" class="list-group-item list-
group-item-action" v-for="result in data_results" :key="result.id"> result.location
, result.state , result.country </a>
</ul>
</div>
</div>
</template>
<script>
export default
data()
return
searchquery: '',
data_results: []
,
methods:
getLocations()
this.data_results = [];
if (this.searchquery.length > 1)
axios.get('/get-locations', params: searchquery: this.searchquery )
.then(response =>
console.log(response);
this.data_results = response.data;
);
,
setLocation(result)
this.searchquery = result.location + ', ' + result.state + ', ' + result.country;
this.data_results = [];
,
</script>
【讨论】:
以上是关于合并 3 个集合以每行返回一个对象的主要内容,如果未能解决你的问题,请参考以下文章
2021-09-28:合并区间。以数组 intervals 表示若干个区间的集合,其中单个区间为 intervals[i] = [starti, endi] 。请你合并所有重叠的区间,并返回一个不重叠