【发布时间】:2022-01-23 07:41:48
【问题描述】:
我正在尝试开发一个 laravel 应用程序,该应用程序必须有一个内部 API 来始终获取数据和前端控制器来使用这个 API 来呈现视图。该 API 将被移动应用程序使用,因此所有请求都将由该 API 处理。
这是我的 API 索引操作,运行良好:
public function index(Request $request)
{
$filters = $request->all();
$query = Place::query()->with('user');
if(!isset($filters['filterType']) || !in_array(Str::lower($filters['filterType']), ['and', 'or']) ){
$filters['filterType'] = 'or';
}
//apply filters
foreach($filters as $filter => $value){
if(Place::hasProperty($filter, app(Place::class)->getTable())){
if($filters['filterType'] == 'and'){
$query->where($filter, $value);
}
else{
$query->orWhere($filter, $value);
}
}
}
//sorting
if(!isset($filters['sortOrder']) || !in_array($filters['sortOrder'], ['asc', 'desc'])){
$sortOrder = 'desc';
}
else{
$sortOrder = $filters['sortOrder'];
}
if(isset($filters['sortBy'])){
$sortBy = $filters['sortBy'];
foreach(explode(',', $sortBy) as $sortField){
if(Place::hasProperty($sortField, app(Place::class)->getTable())){
$query->orderBy($sortField, $sortOrder);
}
}
}
//default pagination
if(!isset($filters['maxResults'])){
$filters['maxResults'] = 5;
}
if(!isset($filters['page'])){
$filters['page'] = 1;
}
//apply pagination
$results = $query->paginate($filters['maxResults'], ['*'], 'page', $filters['page']);
$resultsCollectionResource = PlaceResource::collection($results);
return $resultsCollectionResource;
}
如果我通过邮递员提出这个要求 http://api.site.test/places?fields=id,name,user_id
{
"maxResults": 2
}
我得到了预期的结果,具有 meta 和 links 属性:
{
"data": [
{
"id": 1,
"name": "Lubowitz Group (Customer-focused real-time complexity)",
"user_id": 3
},
{
"id": 2,
"name": "Heaney, Dietrich and Spencer (Fully-configurable multi-state processimprovement)",
"user_id": 10
}
],
"links": {
"first": "http://api.ourplaces.test/places?page=1",
"last": "http://api.ourplaces.test/places?page=5",
"prev": null,
"next": "http://api.ourplaces.test/places?page=2"
},
"meta": {
"current_page": 1,
"from": 1,
"last_page": 5,
"links": [
{
"url": null,
"label": "« Previous",
"active": false
},
{
"url": "http://api.ourplaces.test/places?page=1",
"label": "1",
"active": true
},
{
"url": "http://api.ourplaces.test/places?page=2",
"label": "2",
"active": false
},
{
"url": "http://api.ourplaces.test/places?page=3",
"label": "3",
"active": false
},
{
"url": "http://api.ourplaces.test/places?page=4",
"label": "4",
"active": false
},
{
"url": "http://api.ourplaces.test/places?page=5",
"label": "5",
"active": false
},
{
"url": "http://api.ourplaces.test/places?page=2",
"label": "Next »",
"active": false
}
],
"path": "http://api.ourplaces.test/places",
"per_page": 2,
"to": 2,
"total": 10
}
}
然后我有前端控制器,这个动作:
public function index()
{
$request = Request::create(env('API_URL').'/places', 'GET');
$response = Route::dispatch($request);
$responseContent = $response->content();
$places = json_decode($responseContent);
return view('places.index', ['places' => $places]);
}
还有这个观点:
<x-app-layout>
<x-slot name="header">
<h2 class="font-semibold text-xl text-gray-800 leading-tight">
{{ __('Places') }}
</h2>
</x-slot>
<div class="py-12">
<div class="max-w-7xl mx-auto sm:px-6 lg:px-8">
<div class="bg-white overflow-hidden shadow-xl sm:rounded-lg">
@foreach($places->data as $place)
<div class="row">
<div class="col-md-12 text-center">
<h1 class="post-title">{{ $place->name }}</h1>
<p>{{ $place->streetAddress }}!</p>
<p><a href="{{ route('web.places.show', [ 'place' => $place->id ]) }}">Ver Sitio...</a></p>
</div>
</div>
<hr>
@endforeach
<div class="row">
<div class="col-md-12 text-center">
{{ $places->links() }}
</div>
</div>
</div>
</div>
</div>
</x-app-layout>
但我得到了错误:
错误 调用未定义的方法 stdClass::links() (查看:C:\xampp\htdocs\ourplaces\resources\views\places\index.blade.php)
我认为问题出在前端控制器上,我认为我对 API 的请求很糟糕,因为在进行 json_decode 之后,我得到了 stdClass 对象,而不是 API 控制器生成的原始对象。
API 对象:
我做错了什么? 谢谢大家。
编辑
根据@matiaslauriti 的响应,我将 API 调用更改为 guzzle:
public function index(Request $request)
{
//$places = redirect()->route('api.places.index', ['request' => $request ])->content();
$response = Http::get(env('API_URL').'/places');
$places = $response->object();
return view('places.index', ['places' => $places]);
}
但我仍然遇到完全相同的问题。我测试了 $response->object() 以外的其他方法,比如收集。但是我从来没有得到一个可以在视图中使用 $places->links() 方法的对象。
【问题讨论】:
-
$places不是collection或类似的东西,它是一个数组,因为你已经完成了json_decode并返回一个array...你也永远不会使用HTTP 调用另一个控制器,您可以重定向但永远不会创建一个新的Request对象到所需的 URL...您可以使用 Guzzle 或类似的东西,或者您在可以使用该逻辑的 Service 类中拥有它,但您从不调用控制器在控制器内... -
是的,这就是问题所在。我需要 $places 是一个集合,但我不知道该怎么做。我正在尝试获取重定向响应,但我无法做到这一点。我将使用 Guzzle 进行测试,在这种情况下是一个内部 API,但它必须是外部的。我需要从控制器执行 API 请求获取分页数据。
-
我无法从控制器使用 API,所以我改变了我的方法。也许这是一种糟糕的做法,但这对我有用。我将Controllers请求的数据抽象到Model: api controller: ```` public function index(Request $request) { return Place::getPlaces($request); } ``` 前端控制器: ``` public function index(Request $request) { $places = Place::getPlaces($request);返回视图('places.index', ['places' => $places]); } ``` 并且模型有所有曾经在我的 api 控制器中的查询
标签: php laravel api laravel-8 laravel-api