How to use this relationship in Laravel Inertia JS? - php

My User model:
public function role() {
return $this->belongsTo(Role::class);
}
My Role model:
public function count() {
return User::where('role_id', $this->id)->count();
}
I want to retrieve how many users have a certain role in my Index.vue component.
When I type in Tinker:
$role = Role::find(1);
$role->count();
Output: 1 -> because I have one user with a role with ID 1
My Vue component:
<li v-for="role in roles">Role name: {{ role.name }}</li>
<li>Role count: {{ role.count}}</li>
But this not works as planned.
My RoleController where I passed the 'roles' variable to Index.vue component:
public function index()
{
return Inertia::render('Roles/Index', [
'roles' => Role::all(),
]);
}
I want to display it like this:
Role name: Administrator
Role count: 1
Role name: Subscriber
Role count: 5

if count is not a column on the role table, you will need to pass that data to Vue,
unlike blade, Vue doesn't have access to model/collection methods
I always use resources to transform my data to my javascript front end. see documentation https://laravel.com/docs/9.x/eloquent-resources
RoleResource
return [
'id' => $this->id,
'name' => $this->name,
'email' => $this->role()
// ....
];
now
public function index()
{
return Inertia::render('Roles/Index', [
'roles' => RoleResource::collection(Role::all()); //remember to import RoleResource
]);
}
Check if this helps

I found a solution for this:
You need to return the collection inside your controller:
return Inertia::render('Roles/Index', [
'roles' => RoleResource::collection(Role::all()),
]);
Then create RoleResource.php using the command:
php artisan make:resource RoleResource
And finally inside your RoleResource return these:
return [
'id' => $this->id,
'name' => $this->name,
'count' => User::where('role_id', $this->id)->count(),
];
Inside your Index.vue file add "roles" as prop as object like this:
props: {roles: Object}
And foreach your roles:
<tr v-for="role in roles.data">
{{role.id}} // This will print your role id
{{role.name}} // This will print your role name
{{role.count}} // This will print how much users have that role
</tr>
Final result:

Related

How to display a complex relationship field for Laravel Backpack?

I have a relationship
Candidate -> Vacancy -> User
Candidate:
class Candidate extends Model
{
public function vacancy()
{
return $this->belongsToMany(
Vacancy::class,
'vacancy_has_candidate',
'candidate_id',
'vacancy_id'
);
}
}
Vacancy:
class Vacancy extends Model
{
public function candidate()
{
return $this->belongsToMany(
Candidate::class,
'vacancy_has_candidate',
'vacancy_id',
'candidate_id'
);
}
public function manager() {
return $this->hasMany(User::class, 'manager_id');
}
}
User:
class User extends Authenticatable
{
public function vacancy()
{
return $this->belongsTo(Vacancy::class, 'manager_id');
}
}
I want to display in СRUD candidates the field of the relationship in which I call the manager method with the output of the field from the User model.
for example
class CandidateCrudController extends CrudController
{
....
public function setupCreateOperation()
{
$this->crud->addFields([
[
'name' => 'vacancy',
'type' => 'relationship',
'label' => 'Vacancy',
'model' => Vacancy::class,
'entity' => 'manager', <- this method in Vacancy model
'attribute' => 'title', <- this column name in User
'ajax' => true,
]
]);
...
I get an error
"Looks like field vacancy is not properly defined. The manager() relationship doesn't seem to exist on the App\Models\Candidate model"
I can’t understand why the backpack is looking for a manager method in Candidates, although in the model I indicated a Vacancy in which this relationship method exists. And how to do it right?
KorDEM.
You will not be able to achieve that as per Backpack Documentation:
entity is the method that defines the relationship on the current model, in your case App\Models\Candidate is the CrudController model. So entity there should be the vacancy relation.
If you are using Backpack\PRO paid addon you should be able to list the vacancies with the desired information by using something like:
$this->crud->addField([
'name' => 'vacancy',
'subfields' => [
['name' => 'manager']
]
]);
If you need aditional pivot fields you need to provide ->withPivot in the relation.
Check BelongsToMany documentation on Backpack website

How to provide unique user_id in profile factory in laravel

since this "new" update came in laravel (laravel 8) I am struggling with factories. I need help on how to provide unique id from the User model to user_id column in profile factory. In my User model I have a relationship with profile:
public function profile()
{
return $this->hasOne(Profile::class);
}
In profile model:
public function user()
{
return $this->belongsTo(User::class);
}
And now I have to provide data to profile factory:
return [
'user_id' => ,
'image' => 'image',
'bio' => $this->faker->sentence,
...
If you will only create the Profile when you already have a corresponding User, you can leave the user_id out of the Profile factory, and then use the magic methods to create both at the same time.
User::factory()->hasProfiles(1)->create();
This will automatically create a profile to match the user.
Or, if you do need to create a profile before creating a user, you can define the user_id like this in your factory, and a User will be created by the Profile.
return [
'user_id' => User::factory(),
'image' => 'image',
'bio' => $this->faker->sentence,
];
'user_id' => $this->faker->unique()->numberBetween(1,5000),
'user_id' => $this->faker->unique()->numberBetween($min = 1, $max = 500)
Should be total quantity of your users.

Laravel error: Property [name] does not exist on this collection instance

I'm trying to get a partner for each order using Laravel resource collections. But this throws up an error:
Property [name] does not exist on this collection instance
I get partners this way
Order_product.php
//...
class Order_product extends Model
{
protected $fillable = ['order_id', 'product_id', 'quantity', 'price'];
public function partner()
{
return $this->hasManyThrough(
'App\Partner', 'App\Order',
'partner_id', 'id', 'order_id');
//orders partners order_products
}
//...
Resources\Order_product.php
class Order_product extends JsonResource
{
public function toArray($request)
{
return [
'id' => $this->id,
'order_id' => $this->order_id,
'product_id' => $this->product_id,
'quantity' => $this->quantity,
'price' => $this->price,
'status' => $this->order->status,
'product_name' => $this->prod->name,
//return error
'partner_name' => $this->partner->name,
];
/*
//this method return:
//Invalid argument supplied for foreach() {"exception":"[object]...
$partners = [];
foreach($this->collection as $partner) {
array_push($partners, [
// 'partner_name' => $this->partner->name
]);
}
return $partners;
*/
}
}
Each order has one partner name. In the future, I will group them, but now I just need to output the partner_name
is relations when you use hasMany or hasManyThrough it returns you a collection, so you should use it in foreach or use with index
return [
'product_name' => $this->prod->first()->name, //first array in collection using first()
];
OR
return [
'product_name' => $this->prod[0]->name, //first array in collection using index
];
or you can write this code in foreach!
As you are using hasManyThrough or hasMany laravel relationship returns Illuminate\Database\Eloquent\Collection Instance.
If you want to get name you have to have one Model instance.
Solution 1: $this->parthner->first()->name
Solution 2: See this hasOneThough
public function partner(){
return $this->hasOneThrough(
'App\Partner', 'App\Order',
'partner_id', 'id', 'order_id');
}
Depens on your app logic
Hope this helps you

Trying to return pivot data in Resource Laravel

I am trying to return pivot data to a resource.
The pivot table works, I can add and remove entrys like expected, but I am not able to get the user_id returned in ActivityResource...
In the Laravel Documentation it looks so easy, am I missing something?
// Activity.php
class Activity extends Model
{
public function members()
{
return $this->belongsToMany('App\User', 'activity_user', 'user_id', 'activity_id')->withPivot('activity_id','user_id')->withTimestamps();
}
}
// User.php
class User extends Authenticatable
{
public function joinedactivities()
{
return $this->belongsToMany('App\Activity');
}
}
In my ActivityController I want to return a newly created ActivityResource with 'eager-loaded' relationship
// ActivityController
public function show($id)
{
$activity = Activity::with('members')->findOrFail($id);
/* foreach ($activity->members as $user) {
echo $user->id . " "; // With this I can actually see the right ids
}
return;*/
return new ActivityResource($activity);
}
ActivityResource:
public function toArray($request)
{
return [
'id' => $this->id,
'title' => $this->title,
'attendees' => $this->whenPivotLoaded('activity_user', function () {
return $this->pivot->user_id;
}),
];
}
I dont get any errors instead the attendees field is just not returned. I tried so many things, struggeling with that. Help very appreciated.
I am using Laravel 6.
->withPivot('activity_id','user_id') is not needed. Those fields will appear on your relation object no matter what. For the resource, I think you can do the following:
public function toArray($request)
{
return [
'id' => $this->id,
'title' => $this->title,
// If the relation 'members' is loaded, get an array of user ids otherwise, return null
'attendees' => $this->relationLoaded('members') ? $this->members->pluck('pivot.user_id')->unique()->all() : null
];
}
The main problem is the relationship is a Many to Many, meaning there's more than 1 pivot. With this solution, your object will look like this.
{
id: 3,
title: 'A Title',
attendees: [
1,
2,
3,
],
}
If you want the ids concatenated in a single string like in your commented foreach, replace all() by join(' ')
// If the relation 'members' is loaded, get an string of user ids otherwise, return null
'attendees' => $this->relationLoaded('members') ? $this->members->pluck('pivot.user_id')->unique()->join(' ') : null
{
id: 3,
title: 'A Title',
attendees: '1 2 3',
}

how to use laravel eloquent to get and display data from other tables

I was using these codes in my controller to get all the data from my 2 tables and it works fine
$All = Customers::with('order')->paginate(10);
return response()->json([
'code' => 0,
'success' => true,
'data' => $All
], 200);
Here is how I define the relationship between these 2 tables
class Customers extends Model
{
public function order()
{
return $this->hasMany(Orders::class, 'customer_id', 'id');
}
}
class Orders extends Model
{
public function customers()
{
return $this->belongsTo(Customers::class, 'customer_id', 'id');
}
}
Now my desire output is to hide the order id, order timestamps and change the customer_id to customer's name (the customer's name is not in my orders db table).
I'm using 'data' => DataResource::collection($All) in my controller and this is my DataResource
public function toArray($request)
{
return [
'id' => $this->id,
'name' => $this->name,
'created_at' => $this->created_at,
'updated_at' => $this->updated_at,
'order' => $this->order
];
}
and of course the output is same with the image above.
My database structure:
orders table:
customer table:
Can anyone help me with that?
The answer is simple and basically a copy of the official documentation. You simply need to wrap your orders in an OrderResource as well.
// DataResource
public function toArray($request)
{
return [
'id' => $this->id,
'name' => $this->name,
'created_at' => $this->created_at,
'updated_at' => $this->updated_at,
'order' => OrderResource::collection($this->order)
];
}
// OrderResource
public function toArray($request)
{
return [
'items' => $this->items,
'quantity' => $this->quantity
];
}
I don't really understand why you would want to include the customer_name in your orders when it is already present on the customers object one hierarchy above. But if you really want to add it, you should be able to do so with: 'customer_name' => $this->customers->name.
As a side note: you really should be more consistent with your naming. Why is the resource called DataResource when it is about Customers? Why is your model called Customers in plural form rather than Customer in singular, which is the convention (and more logical if you consider that one model represents one customer). Why is your belongsTo relation called customers() in plural when it returns one customer, while your hasMany relation is called order whereas it returns one or more orders?

Categories