I'm just join 3 eloquent tables. it works but the response json format is not what I want. I need to customizing the format response so it will easy to read.
this is my join table code
$showPresensi = Event::join('presensis', 'presensis.event_id', '=', 'events.id')
->join('anggotas', 'presensis.anggota_id', '=', 'anggotas.id')
->where('presensis.event_id', 2)
->get(['events.*', 'anggotas.nama_lengkap','presensis.kehadiran']);
return $this->ok($showPresensi, "Success");
and this is my current response json
{
"message": "Success",
"success": true,
"code": 200,
"data": [
{
"id": 2,
"nama": "Event 2",
"tanggal": "Sabtu, 12 Februari 2022",
"permintaan_dari": "Yang bersangkutan",
"hasil_kegiatan": "nothing",
"created_at": "2022-02-12T21:53:14.000000Z",
"updated_at": "2022-02-12T21:53:14.000000Z",
"nama_lengkap": "user 1",
"kehadiran": "0"
},
{
"id": 2,
"nama": "Event 2",
"tanggal": "Sabtu, 12 Februari 2022",
"permintaan_dari": "Yang bersangkutan",
"hasil_kegiatan": "nothing",
"created_at": "2022-02-12T21:53:14.000000Z",
"updated_at": "2022-02-12T21:53:14.000000Z",
"nama_lengkap": "user 3",
"kehadiran": "0"
},
{
"id": 2,
"nama": "Event 2",
"tanggal": "Sabtu, 12 Februari 2022",
"permintaan_dari": "Yang bersangkutan",
"hasil_kegiatan": "nothing",
"created_at": "2022-02-12T21:53:14.000000Z",
"updated_at": "2022-02-12T21:53:14.000000Z",
"nama_lengkap": "user 2",
"kehadiran": "1"
}
]
}
I want to column of nama_lengkap and kehadiran become an array so it will become like this:
{
"message": "Success",
"success": true,
"code": 200,
"data": [
{
"id": 2,
"nama": "Event 2",
"tanggal": "Sabtu, 12 Februari 2022",
"permintaan_dari": "Yang bersangkutan",
"hasil_kegiatan": "nothing",
"created_at": "2022-02-12T21:53:14.000000Z",
"updated_at": "2022-02-12T21:53:14.000000Z",
"presensi": [
{
"nama_lengkap": "user 1",
"kehadiran": "0"
},
{
"nama_lengkap": "user 3",
"kehadiran": "0"
},
{
"nama_lengkap": "user 2",
"kehadiran": "1"
}
]
}
]
}
is there any solution for this? any clues are helps. thank you
The easiest way would be to use nested eager loading with Eloquent.
Then you could do:
$showPresensi = Event::with('presensis', 'presensis.anggotas').find(2);
The structure should match more closely what you're going for. Then you could either modify the collection to get exactly what you want, or add accessors to your models.
Related
The following example is used to populate a tree and use a table with a parent_id column.
The data is obtained with a recursive query.
$data = [{
"id": 1,
"name": "parent 1"
"note": "note 1",
}, {
"id": 2,
"name": " parent 2",
"note": "note 2",
"children": [{
"id": 21,
"name": "child A of 2",
"note": "note A of 2",
},{
"id": 22,
"name": "child B of 2",
"note": "note B of 2",
},{
"id": 23,
"name": "child C of 2",
"note": "note C of 2",
"children": [{
"id": 231,
"name": "child A of 23",
"note": "note A of 23",
"children": [{
"id": 2311,
"name": "child A of 231",
"note": "note A of 231",
"children": []
}]
}]
}]
}];
And the query:
$myData= Hierarchy::whereNull('parent_id')
->with('children')
->get();
So far so good.
Problem to solve:
It is necessary to obtain a simple (non-hierarchical) list of the id and name attributes of the parents and children.
Example:
"id": 1,
"name": "parent 1",
"id": 2,
"name": " parent 2",
"id": 21,
"name": "child A of 2",
"id": 23,
"name": "child C of 2",
"id": 231,
"name": "child A of 23",
"id": 2311,
"name": "child A of 231"
While this can be solved on the client side with javascript, I intended to do it with eloquent or PHP functions.
I made some attempts with the array_walk() and array_walk_recursive() PHP functions (without success).
Is there any way to solve with eloquent, bearing in mind that the number of children nodes can be infinite?
Thanks.
EDITED:
Example attempt with array_walk_recursive() PHP function
public function getList()
{
$myData= Hierarchy::whereNull('parent_id')
->with('children')
->get();
$data = array_walk_recursive($myData, "self::myFunction");
return response()->json(['success' => true, "data" => $data]);
}
public function myFunction($item, $key){
???
}
You can use the API Resouce recursively or use the recursive function to generate the hierarchy array.
Example with recursive function:
function makeHierarchy($values)
{
$result = [];
foreach($values as $item) {
$result[] = [
'id' => $item->id,
'name' => $item->name,
'children' => makeHierarchy($item->children),
];
}
return $result;
}
$values = Hierarchy::whereNull('parent_id')->with('children')->get();
$hierarchical = makeHierarchy($values);
If you want to get all values as a flat list:
$values = Hierarchy::get();
$result = [];
foreach($values as $item) {
$result[] = [
'id' => $item->id,
'name' => $item->name,
];
}
# now the result contains all the parents and children in a flat list
In the cleaner way:
$result = Hierarchy::select(['id', 'name'])->all();
I want to get author row instead of author_id. I could this with add collection and change one by one but has Laravel any function for this? Well, I want make this one line
Can i use something like this
Book::where('id',$bid)->with('author')->first('author_id AS author'); //Changes only coulmn name :(
model
public function author()
{
return $this->hasOne(Author::class,'id','author_id');
}
query
Book::where('id',$bid)->with('author')->first()
Output
{
"id": 1,
"name": "Book 1",
"author_id": 3,
"category_id": 2,
"level_id": 1,
"book_language_id": 1,
"book_length": 0,
"img": "book1.png",
"summary": "Summary 1",
"rate_avg": "2.75",
"created_at": "2022-03-04T18:46:32.000000Z",
"updated_at": "2022-03-04T18:52:28.000000Z",
"author": {
"id": 3,
"name": "Author 3",
"created_at": "2022-03-04T18:46:32.000000Z",
"updated_at": "2022-03-04T18:46:32.000000Z"
}
}
Want
{
"id": 1,
"name": "Book 1",
"author": {
"id": 3,
"name": "Author 3",
"created_at": "2022-03-04T18:46:32.000000Z",
"updated_at": "2022-03-04T18:46:32.000000Z"
},
"category_id": 2,
"level_id": 1,
"book_language_id": 1,
"book_length": 0,
"img": "book1.png",
"summary": "Summary 1",
"rate_avg": "2.75",
"created_at": "2022-03-04T18:46:32.000000Z",
"updated_at": "2022-03-04T18:52:28.000000Z",
}
in your query
Book::where('id',$bid)->with('author')->first()
you are getting the book that has that id and you are eager loading the author relation, so in order to get the author you have to access the author field:
Book::where('id',$bid)->with('author')->first()->author
As I said I can this with collection like this:
$b=Book::where('id',$bid)->with('author')->first();
$book=collect([
'id'=>$b->id,
'name'=>$b->name,
'author'=>$b->author,
'category_id'=>$b->category_id,
'level_id'=>$b->level_id,
'book_language_id'=>$b->book_language_id,
'book_length'=>$b->book_length,
'summary'=>$b->summary,
'rate_avg'=>$b->rate_avg,
]);
But this method seems unnecessary
In your example the only difference between the output and what you want is "author_id": 3, as been deleted.
So if you don't want a column or rename a column, you need to use ->select and take all the field you want. And you can also rename with something like that
-> select(DB::raw('author_id as auhtor'), 'books.*')
<v-jstree :data="data"
textFieldName="name"
#item-click="itemClick"
/>
If I use statics - then this works:
data() {
return {
data: [
{
"name": "title 1",
"children": [
{
"name": "Child 1",
},
{
"name": "Child 2",
},
]
}
]
}
},
If I use ajax, then all data is loaded, but openChildren doesn't work(
Response comes in the correct format:
[{ "id": 1, "name": "Title", "children": [{ "id": 1, "name": "Child 1" }, { "id": 2, "name": "Child 2" }.......
children are also loaded, why does the functionality break down?
By trial, I found a way to solve it) in the server response in parent, the "opened" parameter must be specified , either true or false
I want to add variable to each object of collection inside collection. Here JSON response like this:
{
"id": 16,
"survey_id": "8",
"title": "How are you?",
"created_at": "2020-02-06 04:21:44",
"updated_at": "2020-02-06 04:21:44",
"answers": [
Here I want to add variable to each answer
{
"id": 52,
"question_id": "16",
"text": "VERY GOOD",
"created_at": "2020-02-06 04:21:44",
"updated_at": "2020-02-06 04:21:44",
"reports_count": "4",
"responded": 2
},
{
"id": 53,
"question_id": "16",
"text": "OK",
"created_at": "2020-02-06 04:21:44",
"updated_at": "2020-02-06 04:21:44",
"reports_count": "4",
"responded": 2
},
{
"id": 54,
"question_id": "16",
"text": "BAD",
"created_at": "2020-02-06 04:21:44",
"updated_at": "2020-02-06 04:21:44",
"reports_count": "2",
"responded": 2
}
]
},
Overall, I want to add for every answers variable like $respond = $answer->reports()->count(); Help PLease!!
You could do something like this, if you want to calculate it in the collection directly.
$yourCollection->transform(function($collectionItem) {
$collectionItem['responded'] = $collectionItem->answers->count();
return $collectionItem;
});
But you could do this also on the sql side. I think it should be also the better way ;)
I would fetch the answers from the database before assigning that array to a new question-object-property.
public function get() {
// fetch parent question
$question = Question::where('title', $title)->get();
// fetch answers
$answers = Answers::where('parent_id', $question->id)->get();
// create property called "answers"
$question->answers = $answers;
return response()->json($question);
}
I have pivot table post_tag between posts and tags table.
I want to show the tags name for each post in resource API.
Resource file code snippets:
public function toArray($request)
{
return [
'Name'=> $this->title,
'Description'=> $this->desc,
'Image'=> $this->image_path,
'Posted By'=> $this->user->name,
'Category Name'=> $this->category->name,
'Tags' => $this->tags,
];
}
Relation added in Post model:
public function tags()
{
return $this->belongsToMany(Tag::class)->withTimestamps();
}
One of Results of an API:
"Name": "first post",
"Description": "desc of the post",
"Image": "https://blog.test/uploads/post/SjvDfC1Zk5UzGO6ViRbjUQTMocwCh0lzEYW1Gufp.jpeg",
"Posted By": "test",
"Category Name": "web dev",
"Tags": [
{
"id": 1,
"name": "HTML",
"created_at": "2020-01-08 19:19:55",
"updated_at": "2020-01-08 19:19:55",
"pivot": {
"post_id": 1,
"tag_id": 1,
"created_at": "2020-01-08 19:21:40",
"updated_at": "2020-01-08 19:21:40"
}
},
{
"id": 2,
"name": "CSS",
"created_at": "2020-01-08 19:19:55",
"updated_at": "2020-01-08 19:19:55",
"pivot": {
"post_id": 1,
"tag_id": 2,
"created_at": "2020-01-08 19:21:40",
"updated_at": "2020-01-08 19:21:40"
}
},
I need to show like that JUST names:
"Tags" : {
'HTML',
'CSS',
'JS',
}
You must be use like this
return [
'Name'=> $this->title,
'Description'=> $this->desc,
'Image'=> $this->image_path,
'Posted By'=> $this->user->name,
'Category Name'=> $this->category->name,
'Tags' => $this->tags->pluck('name')
];