How can I add pagination in Lumen 8 collection? - laravel

I am using Lumen to create api where I integrate collection. All code details are given below. I want to add pagination according to my code. How I add paginator in my code?
In Controller:
//To get all Employee Type
public function getAllEmployeeTypes(){
$employeeType = OsEmployeeType::where('status',1)->orderBy('priority', 'DESC')->get();
return new OsEmployeeTypeCollection($employeeType);
}
In Collection it looks like
public function toArray($request)
{
return [
'data' => $this->collection->map(function($data) {
return [
'id' => $data->id,
'name' => $data->name,
'priority' => $data->priority,
'status' => $data->status,
];
})
];
}
public function with($request)
{
return [
'success' => true,
'status' => 200
];
}
and the response that I got
{
"data": [
{
"id": 3,
"name": "Type 3",
"priority": 3,
"status": 1
},
{
"id": 2,
"name": "Type 2",
"priority": 2,
"status": 1
},
{
"id": 1,
"name": "Type 1",
"priority": 1,
"status": 1
}
],
"success": true,
"status": 200
}
How can I paginate my API response?

Paginate is the same as Laravel in Lumen. You will do just the same as in Laravel.
$employeeType = OsEmployeeType::where('status',1)->orderBy('priority', 'DESC')->skip(10)->take(5)->get();

Related

return user model with eager loading laravel

return $data =InteractiveSession::with('messages.user')->where('exercise_id',$exercise->id)->first();
This code will return data like below
{
"id": 1,
"exercise_id": 48,
"messages": [
{
"id": 1,
"from_user": 69,
"message": "Hi",
"interactive_session_id": 1,
"user": {
"id": 69,
"first_name": "Jobin"
}
}
]}
how can i return data like below??
{
"id": 1,
"exercise_id": 48,
"messages": [
{
"id": 1,
"from_user":{
"id": 69,
"first_name": "Jobin"
},
"message": "Hi",
"interactive_session_id": 1,
}
]}
i have tables interactivesession,message,users, using hasmany relation
You can create a relation for from_user to the user model, and then do return $data = InteractiveSession::with(['messages.user', 'fromUser'])->where('exercise_id',$exercise->id)->first(); (remember fromUser should be your relation name)
Try this:
$data = InteractiveSession::with('messages.user')->where('exercise_id',$exercise->id)->first();
$data->transform(function($record) {
$messages = $record->messages->transform(function($message) {
'id' => $message->id,
'from_user' => [
'id' => $message->user->id,
'first_name' => $message->user->first_name
],
'message' => $message->message,
'interactive_session_id' => $message->interactive_session_id
});
return [
'id' => $record->id,
'exercise_id' => $record->exercise_id,
'messages' => $messages
];
});

How can i use php conditions inside json data?

Below is the code inside my CategoryResource.php
[
'id' => $this->id,
'name' => $this->name,
'categories' => CategoryResource::collection($this->children),
'items' => ItemListResource::collection($this->items)
];
and by this i am getting response like:
{
"status": true,
"data": {
"categories": [
{
"id": 10,
"name": "Fast Food",
"categories": [
{
"id": 11,
"name": "Pizza",
"categories": [],
"items": [
{
"id": 9,
"name": "Ham \u0026 Crab Stick",
"price": "20.00",
"image": "up/products/c11/Mrn4OpjngYRCkRJ28rJ1LbXUOXy0XjTRyXU7eFoi.jpg"
}
]
}
],
"items": []
}
]
}
}
i dont want "categories" : [] when category does not exist for a category.
please suggest some ideas or ways i can deal with this issue.
I assume that CategoryResource::collection($this->children) returns an array, maybe empty or not.
If that's true, then:
$dataArray = [
'id' => $this->id,
'name' => $this->name,
'items' => ItemListResource::collection($this->items)
];
$categories = CategoryResource::collection($this->children);
if (count(categories) > 0) $dataArray['categories'] = $categories;

Laravel reject function on nested collection

I am trying to iterate my collection, which has nested collections, with the collection reject() function and return the original collection with the updated nested data.
So this is my quiz collection
{
"id": 1,
"title": "quiz 1",
"questions": [
{
"id": 1,
"quiz_id": 1,
"question": "q1 - q1",
"answers": [
{
"id": 1,
"question_id": 1,
"answer": "answer to question 1"
},
{
"id": 2,
"question_id": 1,
"answer": "answer to question 1"
}
]
},
{
"id": 2,
"quiz_id": 1,
"question": "q1 - q2",
"answers": [
{
"id": 3,
"question_id": 2,
"answer": "answer to question 1"
}
]
}
]
}
Now I want to iterate through the questions and reject those that were already answered and exist in the result collection. I do so by using the reject() function
$quizResults = [
{
"id": 1,
"user_id": 1,
"quiz_id": 1,
"question_id": 1,
"answer_id": 1,
"correct": 1,
"created_at": null,
"updated_at": null
}
];
$filtered = $quiz->questions->reject(function ($value, $key) use ($quizResult) {
return $quizResult->contains('question_id', $value->id);
});
I want to return the quiz collection with the updated questions (without the rejected questions), but I can't seem to figure out the correct way to accomplish this. (if i return just the $filtered variable i get the correct filtered results, however if i try putting it back in to the $quiz var it won't apply the rejected filter). If I just do
return $quiz
I will get the same original collection with all the questions as if I never ran the reject() function.
How do I make the $quiz->questions = $filtered; ?
Pass it by reference
$filtered = $quiz->questions->reject(function ($value, $key) use (&$quizResult) {
return $quizResult->contains('question_id', $value->id);
});
This is the min steps to reproduce your problem,
$quizResult = [
0 => [
'id' => 1,
'user_id' => 1,
'quiz_id' => 1,
'question_id' => 1,
'answer_id' => 1,
'correct' => 1,
'created_at' => null,
'updated_at' => null,
],
];
$quiz = [
'id' => 1,
'title' => 'quiz 1',
'questions' => [
0 => [
'id' => 1,
'quiz_id' => 1,
'question' => 'q1 - q1',
'answers' => [
0 => [
'id' => 1,
'question_id' => 1,
'answer' => 'answer to question 1',
],
1 => [
'id' => 2,
'question_id' => 1,
'answer' => 'answer to question 1',
],
],
],
1 => [
'id' => 2,
'quiz_id' => 1,
'question' => 'q1 - q2',
'answers' => [
0 => [
'id' => 3,
'question_id' => 2,
'answer' => 'answer to question 1',
],
],
],
],
];
$filtered = collect($quiz['questions'])->reject(function ($value) use ($quizResult) {
return collect($quizResult)->contains('question_id', $value['id']);
});
$quiz['questions'] = $filtered;
return $quiz;
And this the result,
{
"id": 1,
"title": "quiz 1",
"questions": {
"1": {
"id": 2,
"quiz_id": 1,
"question": "q1 - q2",
"answers": [
{
"id": 3,
"question_id": 2,
"answer": "answer to question 1"
}
]
}
}
}
I do not understand why you said it's returning original one.
I had to unset the $quiz['questions'] first so it was like this
unset($quiz['questions']);
$quiz['questions'] = $filtered->flatten();
return $quiz;
and the result was as intended:
{
"id": 1,
"title": "quiz 1",
"questions": [
{
"id": 2,
"quiz_id": 1,
"question": "q1 - q2",
"answers": [
{
"id": 3,
"question_id": 2,
"answer": "answer to question 1"
}
]
}
]
}

Laravel API Resource Collection return specific fields from other resource

I am working on an api that will be accessible via a mobile app.
I have defined resources and collections for respective endpoints. My problem is now is that I want to return different api json data based on what ever collection.
Here is an example
Provinces has cities and suburbs, so in json format I need to have
"data": [
{
"id": 1,
"name": "Eastern Cape",
"cities": [
{
"name": "Alice"
},
],
"suburbs": [
"name": "Suburb 1"
]
},
]
I want different data when the cities resource is called in news api collection
"data": [
{
"id": 1,
"name": "Eastern Cape",
"cities": [
{
"name": "Alice",
"municipality": "municipality name",
},
],
"suburbs": [
"name": "Suburb 1",
"ward_number": "ward 1"
]
},
]
This is an NewsResource Api
public function toArray($request)
{
// return parent::toArray($request);
return [
'id'=> $this->id,
'title' => $this->title,
'slug' => $this->slug,
'content' => $this->content,
'created_at' => $this->created_at,
'category_id' => $this->news_category_id,
'featured_image' => url($this->featured_image),
'author' => new UserResource($this->user),
'category' => new NewsCategoryResource($this->category), //Only category Name to be displayed
'municipality' => new MunicipalityResource($this->municipality), // Only Municipality Name to be displayed
'comments' => new NewsCommentResource($this->comments),
];
}
I don't really know what is your code structure, but hope this help for you
You may use different queries, for example
/** For the obvious resource calling */
return SomeResource::collection (SomeModel::with(['suburbs', 'cities'])
/** Other filter queries */
->get());
/** For the cities resource calling */
return SomeResource::collection (SomeModel::with(['suburbs:id,ward_number', 'cities:id,municipality'])
/** Other filter queries */
->get());
In your Resource class which you use for the cities/suburbs data, do it like so
return [
/** Some data which you need */
'municipality' => $this->when($this->municipality !== null, $this->municipality),
'ward_number' => $this->when($this->ward_number !== null, $this->ward_number),
];

returning response with json in laravel api removes the collection pagination links

i'm using laravel for webservice. i want to return a collection like this:
return response()->json([data => $data]);
and i'm using laravel api resouces for transforming the collection. this is my resource:
class Item extends JsonResource
public function toArray($request)
{
return [
'id' => $this->id,
'name'=> $this->name,
'city_dependent' => $this->city_dependent,
];
}
when i pass a collection to the resource like:
$items = Item::where('active' , 1)->paginate(10);
$data = Item::collection($items);
everything works good. if i return the $data, the pagination links and meta are returning and there is no problem.
"links": {
"first": "http://127.0.0.1:8000/api/category/items?page=1",
"last": "http://127.0.0.1:8000/api/category/items?page=1",
"prev": null,
"next": null
},
"meta": {
"current_page": 1,
"from": 1,
"last_page": 1,
"path": "http://127.0.0.1:8000/api/category/items",
"per_page": 10,
"to": 3,
"total": 3
}
but if i return the data with response()->json() like below, all data about "meta" and "links" are remove! and everything else is ok.
return response()->json([
'result' =>true,
'data' => $data
]);
why the pagination data and links are removed from the data? is there anything that i missed?

Resources