I need to return just an array of the name values for each of my roles. My roles is a hasMany relationship. This is currently how I'm trying to do it, but the returned result is unchanged, what am I missing?
/**
* Display the specified resource.
*
* #param int $id
* #return \Illuminate\Http\Response
*/
public function show(Request $request, Company $company)
{
$this->authorize('view', $company);
if ($request->boolean('with_roles')) {
$company = $company->load(['roles' => function ($query) {
$query->pluck('name');
}]);
}
return new ApiSuccessResponse($company);
}
gives me:
{
"model": {
"id": 1,
"user_id": 1,
"contact_first_name": "John",
"created_at": "2023-02-15T09:45:48.000000Z",
"updated_at": "2023-02-15T09:45:48.000000Z",
"deleted_at": null,
"is_deleting": false,
"roles": [
{
"id": 6,
"company_id": 1,
"name": "accountant",
"guard_name": "api",
"created_at": "2023-02-15T09:45:59.000000Z",
"updated_at": "2023-02-15T09:45:59.000000Z"
},
{
"id": 2,
"company_id": 1,
"name": "admin",
"guard_name": "api",
"created_at": "2023-02-15T09:45:48.000000Z",
"updated_at": "2023-02-15T09:45:48.000000Z"
},
{
"id": 4,
"company_id": 1,
"name": "affiliate",
"guard_name": "api",
"created_at": "2023-02-15T09:45:56.000000Z",
"updated_at": "2023-02-15T09:45:56.000000Z"
},
{
"id": 3,
"company_id": 1,
"name": "affiliate_manager",
"guard_name": "api",
"created_at": "2023-02-15T09:45:55.000000Z",
"updated_at": "2023-02-15T09:45:55.000000Z"
},
{
"id": 5,
"company_id": 1,
"name": "buyer",
"guard_name": "api",
"created_at": "2023-02-15T09:45:58.000000Z",
"updated_at": "2023-02-15T09:45:58.000000Z"
},
{
"id": 8,
"company_id": 1,
"name": "guest",
"guard_name": "api",
"created_at": "2023-02-15T09:46:02.000000Z",
"updated_at": "2023-02-15T09:46:02.000000Z"
},
{
"id": 7,
"company_id": 1,
"name": "user",
"guard_name": "api",
"created_at": "2023-02-15T09:46:00.000000Z",
"updated_at": "2023-02-15T09:46:00.000000Z"
}
]
}
}
I expect to see:
{
"model": {
"id": 1,
"user_id": 1,
"contact_first_name": "John",
"created_at": "2023-02-15T09:45:48.000000Z",
"updated_at": "2023-02-15T09:45:48.000000Z",
"deleted_at": null,
"is_deleting": false,
"roles": [
"accountant",
"admin",
"affiliate"
...
]
}
}
pluck doesn't modify the original relationship, it only returns an array. Try this one :
public function show(Request $request, Company $company)
{
$this->authorize('view', $company);
$result = $company->toArray();
if ($request->boolean('with_roles')) {
$result['roles'] = $company->roles()->pluck('name')->toArray();
}
return new ApiSuccessResponse($result);
}
Related
I'm using belongsToMany() in my Laravel model and i need to change the function return format.
public function platform_information(): BelongsToMany
{
return $this->belongsToMany(
PlatformInformation::class,
'platform_information_artist',
'artist_id',
'platform_information_id')->withPivot([
'date', 'value'
]);
}
When I call the function
$artist->platform_information()
->orderBy('platform_information_id', 'asc')
->orderBy('date', 'asc')
->get()
Returns the following data:
[
{
"id": 1,
"platform": "spotify",
"information": "monthly_listeners",
"description": null,
"created_at": null,
"updated_at": null,
"deleted_at": null,
"pivot": {
"artist_id": 1,
"platform_information_id": 1,
"date": "2022-11-09",
"value": 55400500
}
},
{
"id": 1,
"platform": "spotify",
"information": "monthly_listeners",
"description": null,
"created_at": null,
"updated_at": null,
"deleted_at": null,
"pivot": {
"artist_id": 1,
"platform_information_id": 1,
"date": "2022-11-10",
"value": 55395190
}
},
{
"id": 2,
"platform": "spotify",
"information": "followers",
"description": null,
"created_at": null,
"updated_at": null,
"deleted_at": null,
"pivot": {
"artist_id": 1,
"platform_information_id": 2,
"date": "2022-11-09",
"value": 25390584
}
},
{
"id": 2,
"platform": "spotify",
"information": "followers",
"description": null,
"created_at": null,
"updated_at": null,
"deleted_at": null,
"pivot": {
"artist_id": 1,
"platform_information_id": 2,
"date": "2022-11-10",
"value": 25410584
}
}
]
The data obtained are correct, but not in the format in which I need them.
This is the format that i need:
[
{
"id": 1,
"platform": "spotify",
"information": "monthly_listeners",
"data" : [
{
"artist_id": 1,
"platform_information_id": 1,
"date": "2022-11-09",
"value": 55400500
},
{
"artist_id": 1,
"platform_information_id": 1,
"date": "2022-11-10",
"value": 55395190
}
]
},
{
"id": 2,
"platform": "spotify",
"information": "followers",
"data" : [
{
"artist_id": 1,
"platform_information_id": 2,
"date": "2022-11-09",
"value": 25390584
},
{
"artist_id": 1,
"platform_information_id": 2,
"date": "2022-11-10",
"value": 25410584
}
]
}
]
Is there any way to do this using the belongsToMany() function directly?
Or do I have to do it manually in the controller?
I had not tested it but what I have get from the question, it should work.
I am assuming that you have a model Artist in your Models directory.
$artist = \App\Models\Artist::with('platform_information')->get();
Then you can dd() to verify the format
dd($artist->toArray());
I would like to perform the average rating of respective product which stored in the pivot table called "reviews".Below are my existing code.
Product Model:
public function reviews(){
return $this->belongsToMany(User::class,'reviews')->withPivot('comment','rating')->withTimestamps();
}
public function getProductRatingAttribute(){
return $this->reviews()->average('rating');
}
User Model:
public function reviews(){
return $this->belongsToMany(Product::class,'reviews')->withPivot('comment','rating')->withTimestamps();
}
Migration for the reviews
Schema::create('reviews', function (Blueprint $table) {
$table->id();
$table->timestamps();
$table->unsignedBigInteger('user_id');
$table->unsignedBigInteger('product_id');
$table->string('comment')->nullable();
$table->integer('rating');
$table->foreign('user_id')->references('id')->on('users');
$table->foreign('product_id')->references('id')->on('products');
});
I have attempted to use the below to code construct the expected output but it leads N+1 issue because it does not take advantage of the eager loading of the Laravel Eloquent.
$s = Product::with('reviews')->append('product_rating');
As I check telescope, it produces 6 query which can lead performance issue when the data is large.
Expected output:
{
"msg": [
{
"id": 4,
"created_at": "2021-04-09T07:32:35.000000Z",
"updated_at": "2021-04-09T07:32:35.000000Z",
"name": "MacDonald",
"nickname": "MCD",
"users_id": 1,
"price": "0.00",
"product_rating": "3.3333",
"reviews": [
{
"id": 1,
"name": "John Smith",
"email": "john.smith#hotmail.com",
"email_verified_at": null,
"created_at": "2021-04-08T13:29:13.000000Z",
"updated_at": "2021-04-08T13:29:13.000000Z",
"role": 0,
"pivot": {
"product_id": 4,
"user_id": 1,
"comment": "Ouch",
"rating": 3,
"created_at": "2021-05-01T11:51:26.000000Z",
"updated_at": "2021-05-01T11:52:07.000000Z"
}
},
{
"id": 2,
"name": "Kelvin Ooi",
"email": "kelvin.ooi#hotmail.com",
"email_verified_at": null,
"created_at": "2021-04-08T13:29:13.000000Z",
"updated_at": "2021-04-13T12:07:11.000000Z",
"role": 1,
"pivot": {
"product_id": 4,
"user_id": 2,
"comment": "Ouch",
"rating": 5,
"created_at": "2021-05-01T11:51:26.000000Z",
"updated_at": "2021-05-01T11:52:07.000000Z"
}
},
{
"id": 1,
"name": "John Smith",
"email": "john.smith#hotmail.com",
"email_verified_at": null,
"created_at": "2021-04-08T13:29:13.000000Z",
"updated_at": "2021-04-08T13:29:13.000000Z",
"role": 0,
"pivot": {
"product_id": 4,
"user_id": 1,
"comment": "Ouch",
"rating": 2,
"created_at": "2021-05-01T11:51:26.000000Z",
"updated_at": "2021-05-01T11:52:07.000000Z"
}
}
]
},
{
"id": 10,
"created_at": null,
"updated_at": null,
"name": "Mary Bown",
"nickname": "MB",
"users_id": 1,
"price": "2.88",
"product_rating": "2.0000",
"reviews": [
{
"id": 1,
"name": "John Smith",
"email": "john.smith#hotmail.com",
"email_verified_at": null,
"created_at": "2021-04-08T13:29:13.000000Z",
"updated_at": "2021-04-08T13:29:13.000000Z",
"role": 0,
"pivot": {
"product_id": 10,
"user_id": 1,
"comment": "Ouch",
"rating": 2,
"created_at": "2021-05-01T11:51:26.000000Z",
"updated_at": "2021-05-01T11:52:07.000000Z"
}
}
]
},
{
"id": 11,
"created_at": null,
"updated_at": null,
"name": "Pizza Hut",
"nickname": "pizzahut",
"users_id": 1,
"price": "4.10",
"product_rating": null,
"reviews": [
]
},
{
"id": 12,
"created_at": "2021-04-09T08:00:42.000000Z",
"updated_at": "2021-04-09T08:00:42.000000Z",
"name": "Domino Pizza",
"nickname": "domino",
"users_id": 3,
"price": "0.00",
"product_rating": null,
"reviews": [
]
},
{
"id": 13,
"created_at": "2021-04-26T16:12:53.000000Z",
"updated_at": "2021-04-26T16:12:53.000000Z",
"name": "Chicken Chop",
"nickname": "chickchop",
"users_id": 3,
"price": "0.00",
"product_rating": null,
"reviews": [
]
}
]
}
Appending is performing the query on each record.
Why not perform average on the collection itself?
$s = Product::with('reviews')->get();
$avg = $s->avg('pivot.rating');
Alternatively you can modify the relationship method to include a raw select of the average rating.
I am working with laravel and I have basically these 3 related models in the following way: person model (Person.php), task model (Task.php) and post model (Post.php).
Person.php
public function tasks()
{
return $this->hasMany(Task::class);
}
public function posts()
{
return $this->hasMany(Post::class);
}
Task.php
public function person()
{
return $this->belongsTo(Person::class);
}
Post.php
public function person()
{
return $this->belongsTo(Person::class);
}
this is the way in which the models are related, now I have a method to recover a person and their tasks and posts that looks like this:
Person::with(['tasks','posts'])->findOrFail($id);
this returns the formatted data similar to these (it's an example):
{
"id": 1,
"name": "jhon",
"email": "jhon#gmail.com",
"created_at": "2018-09-14 12:07:35",
"updated_at": "2018-09-14 12:07:38",
"tasks": [
{
"id": 1,
"description": "task description",
"person_id": 1,
"created_at": "2018-09-18 21:07:48",
"updated_at": "2018-09-19 20:47:37",
},
{
"id": 2,
"description": "task description",
"person_id": 1,
"created_at": "2018-09-19 00:15:45",
"updated_at": "2018-09-20 15:28:58",
}
],
"posts": [
{
"id": 1,
"title": "post title",
"person_id": 1,
"created_at": "2018-09-14 12:08:52",
"updated_at": "2018-09-14 16:21:03"
},
{
"id": 3,
"title": "post title",
"person_id": 1,
"created_at": "2018-09-17 18:33:51",
"updated_at": "2018-09-17 18:33:51"
}
]
}
my question is this: is it possible to separate the result of the tasks and posts models in a different array, if this is possible as I should do ?, I want to have a result like this:
[
{
"id": 1,
"description": "task description",
"person_id": 1,
"created_at": "2018-09-18 21:07:48",
"updated_at": "2018-09-19 20:47:37",
},
{
"id": 2,
"description": "task description",
"person_id": 1,
"created_at": "2018-09-19 00:15:45",
"updated_at": "2018-09-20 15:28:58",
},
{
"id": 1,
"title": "post title",
"person_id": 1,
"created_at": "2018-09-14 12:08:52",
"updated_at": "2018-09-14 16:21:03"
},
{
"id": 3,
"title": "post title",
"person_id": 1,
"created_at": "2018-09-17 18:33:51",
"updated_at": "2018-09-17 18:33:51"
}
]
$a = DB:table('posts')->get();
$b = DB:table('tasks')->get();
$c = array_merge($a,$b);
see doc:
https://laravel.com/docs/5.7/queries
I got a some trouble in my Laravel application, in Search function, when I do search the result is
{
"data": [
{
"id": 2,
"user_id": 8,
"identity_number": "213918273",
"name": "Pekerja_2",
"gender_id": 1,
"date_of_birth": "1999-05-25",
"address": "Jalan Bandung Raya no 50",
"province_id": 32,
"city_id": 3273,
"district_id": 3273160,
"phone": "4232343432",
"image": null,
"created_at": "2018-01-11 10:59:54",
"updated_at": "2018-01-11 10:59:54",
"partner_id": null,
"skill": [
{
"id": 3,
"worker_id": 2,
"skill_id": 6,
"sub_skill_id": 18,
"created_at": "2018-01-15 13:06:48",
"updated_at": "2018-01-15 13:06:48",
"price": null,
"unit": null
}
]
},
{
"id": 3,
"user_id": 16,
"identity_number": "213918273",
"name": "Pekerja_3",
"gender_id": 1,
"date_of_birth": "1999-05-25",
"address": "Jalan Bandung Raya no 50",
"province_id": 32,
"city_id": 3273,
"district_id": 3273160,
"phone": "2345234234",
"image": null,
"created_at": "2018-01-15 13:06:48",
"updated_at": "2018-01-15 13:06:48",
"partner_id": null,
"skill": []
}
]
}
as you can see that "Skill" with id number 3 is empty, I want all in id number 3 is empty also.
My controller is :
$worker = Worker::with(['skill' => function($q) use ($request) {
$q->where('worker_skills.sub_skill_id', $request['sub_skill_id']);
}])->whereHas('skill');
And I want something like this :
{
"data": [
{
"id": 2,
"user_id": 8,
"identity_number": "213918273",
"name": "Pekerja_2",
"gender_id": 1,
"date_of_birth": "1999-05-25",
"address": "Jalan Bandung Raya no 50",
"province_id": 32,
"city_id": 3273,
"district_id": 3273160,
"phone": "2534234234",
"image": null,
"created_at": "2018-01-11 10:59:54",
"updated_at": "2018-01-11 10:59:54",
"partner_id": null,
"skill": [
{
"id": 3,
"worker_id": 2,
"skill_id": 6,
"sub_skill_id": 18,
"created_at": "2018-01-15 13:06:48",
"updated_at": "2018-01-15 13:06:48",
"price": null,
"unit": null
}
]
},
]
}
The point is, if "skill" variable is empty then data not show and vice versa.
Thankyou any help will appreciate, sorry for bad english
You can add a callback to your whereHas function with the same filter as the with function
$worker = Worker::with(['skill' => function($q) use ($request) {
$q->where('worker_skills.sub_skill_id', $request['sub_skill_id']);
}])
->whereHas('skill', function($q) use ($request) {
$q->where('worker_skills.sub_skill_id', $request['sub_skill_id']);
})
->get();
You can try this $worker = Worker:has('skill')->get();
Only worker that have at least one skill are contained in the collection
In my forum I'm showing all topics. It looks like this:
So a user can subscribe by clicking on the red hearth.
I'm loading the topics with this json:
{
"forum": {
"id": 1,
"slug": "test",
"name": "test",
"description": "test",
"created_at": null,
"updated_at": null
},
"topics": {
"total": 6,
"per_page": 5,
"current_page": 1,
"last_page": 2,
"next_page_url": "http://forum.dev/api/forum/test?page=2",
"prev_page_url": null,
"from": 1,
"to": 5,
"data": [
{
"id": 1,
"slug": "1",
"name": "1",
"description": "1",
"forum_id": 1,
"created_at": null,
"updated_at": null
},
{
"id": 2,
"slug": "2",
"name": "1",
"description": "1\t",
"forum_id": 1,
"created_at": null,
"updated_at": null
},
{
"id": 3,
"slug": "1",
"name": "1",
"description": "1\t",
"forum_id": 1,
"created_at": null,
"updated_at": null
},
{
"id": 4,
"slug": "1",
"name": "1",
"description": "1",
"forum_id": 1,
"created_at": null,
"updated_at": null
},
{
"id": 5,
"slug": "1",
"name": "1",
"description": "1",
"forum_id": 1,
"created_at": null,
"updated_at": null
}
]
}
}
I'm returning that ^ like this:
$forum->topics()->orderBy('created_at', 'DESC')->paginate(5);
So how do I get a subscribe value on every topic object?
So like this:
"data": [
{
"id": 1,
"slug": "1",
"name": "1",
"description": "1",
"forum_id": 1,
"created_at": null,
"updated_at": null,
"subscribed": true
},
I already made this on my topic model:
/**
* #return mixed
*/
public function subscriptions()
{
return Topic::subscribedBy(Auth::user())->get();
}
And it's working. But how do I send that ^ with every topic.
You can add an attribute (which is not present in the database) by creating an accessor.
public function getSubscriptionsAttribute()
{
return Topic::subscribedBy(Auth::user())->get();
}
and then adding it to the $append property.
protected $appends = ['subscriptions'];
If you're using the $visible whitelist you might have to add it to that property too.
Source (Its all the way in the bottom.)