I have a Users and Roles table in my database. One user can have many roles. I am using Laravel 8, I want to be able to return all roles for that user within the middleware (I am using inertia.js - handleinertiarequest.php).
Roles Table:
id
role
user_id
1
super_admin
3
2
admin
3
3
user
3
Users Table:
id
name
1
Some name
2
Some other name
3
Joe Bloggs
User Model (User.php):
public function userroles()
{
return $this->hasMany(Roles::class);
}
Roles Model (Roles.php):
public function user()
{
return $this->belongsTo(User::class);
}
HandleInertiaRequest.php:
public function share(Request $request)
{
return array_merge(parent::share($request), [
'auth' => function () use ($request) {
return [
'user' => $request->user() ? [
'id' => $request->user()->reference,
'first_name' => $request->user()->first_name,
'last_name' => $request->user()->last_name,
'role_staff' => \App\Models\Roles::select('id'),
] : null,
];
},
]);
}
Layout.vue:
{{ $page.props.auth.user.role_staff }}
So if I am logged in as Joe Bloggs (id = 3), I want it to return 3 roles (or even just 1, if using the id). But this doesn't return anything or show any errors. What am i missing here? Thanks
Use this relationship method in user modal:
public function userRoles()
{
$this->hasMany('App\Models\role_table_modal_name','user_id');
}
Then in controller/middleware call your User modal:
$ user_roles = User::find($id)->with('userRoles')->get();
Related
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:
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
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.
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',
}
Here is my model relationship...
class User extends Eloquent {
public function loginLog(){
return $this->hasMany('LoginLog');
}
}
class LoginLog extends Eloquent {
public function user(){
return $this->belongsTo('User');
}
}
When I insert data into the login_logs table in my database all the data is input correctly but it does not insert the id of the user into user_id (laravel expects this).
Here is how I am inserting into login_logs.
$user->loginLog()->insert(array(
'user_id' => $user->id, //I could put it here, but then what is the point in a relationship?
'email' => $user->email,
'ip_address' => Request::getClientIp(),
'country_code' => $country_code,
'status' => $status,
'created_at' => Helper::dateTimeNow()
));
You have to attach the user.
Its here in the docs
http://laravel.com/docs/eloquent#inserting-related-models
Update:
On rereading your question I think you want to find the user by their id first as you are doing $user->loginLog()->insert not $loginLog->insert
Try chaining it so:
$user::find($theIDYouWant)->loginLog()->insert