Getting distant belongsToMany through belongsToMany - php
I'm trying to grab a distant relationship and it isn't working. I've tried doing a hasManyThrough but that doesn't appear to work for belongsToMany relationships. It was throwing a query error.
Here are my migrations:
Schema::create('users', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->string('email')->unique();
$table->string('password');
$table->rememberToken();
$table->timestamps();
});
Schema::create('roles', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->timestamps();
});
Schema::create('role_user', function (Blueprint $table) {
$table->integer('role_id');
$table->integer('user_id');
});
Schema::create('permissions', function (Blueprint $table) {
$table->increments('id');
$table->string('group');
$table->string('name');
$table->timestamps();
});
Schema::create('permission_role', function (Blueprint $table) {
$table->integer('permission_id');
$table->integer('role_id');
});
Here are my models:
class User extends AuthUser
{
//
public function roles()
{
return $this->belongsToMany('App\Role');
}
}
class Role extends Model
{
//
public function permissions()
{
return $this->belongsToMany('App\Permission');
}
}
What I'm trying to do:
$user = App\User::find(1);
Log::info($user->roles->permissions);
This gives me a Property [permissions] does not exist on this collection instance. error.
How do I grab the users permissions through their roles?
EDIT:
I've come up with this ugly solution to what I'm trying to do:
if (auth()->check()) {
if (auth()->user()->roles->contains('name', 'Admin')) {
Gate::before(function () {
return true;
});
}
else {
$permissions = [];
foreach (auth()->user()->roles as $role) {
$permissions = array_merge($permissions, $role->permissions->pluck('name')->all());
}
foreach (array_unique($permissions) as $permission) {
Gate::define($permission, function () {
return true;
});
}
}
}
How can I improve this?
You should eager load those relationships like this:
$user = User::with(['roles', 'roles.permissions'])->where('id', 1)->first();
This will give you an array of roles, and each role with their respective permissions.
Permission::whereHas('role', function($query) use ($user_id) {
return $query->whereHas('user_id', $user_id);
});
The idea in the above query is that when you want the many to many of a distant relationship, you work backwards.
change $user=App\USER->find(1);
to this
$user= App\User::find(1);
try this will work for you
you have not set foreign key in migration
$table->foreign('role_id)->references('id')->on('roles');
Same define for users
It gave you Property [permissions] does not exist on this collection instance. error because: $user->roles returns a collection of roles while permissions in your model Role is for a single model only ..
Basically you have to foreach($user->roles as $role) before you can use $role->permissions
but here's a sample where you don't have to foreach to get a permission depending on a role ..
auth()->user()->roles->where('name','=','Administrator')->permissions;
and that would be returning an array/collection of permissions of an administrator ..
Related
Count how many users are there per each category
I'm trying to get user data, them get department value to array so I can group it and count how many users are part of the same department. User table: Schema::create('users', function (Blueprint $table) { $table->increments('id'); $table->string('name'); $table->string('email')->unique(); $table->timestamp('email_verified_at')->nullable(); $table->string('password'); $table->rememberToken(); $table->timestamps(); }); Department table: Schema::create('departments', function (Blueprint $table) { $table->increments('id'); $table->timestamps(); $table->string('name'); }); Assignment table: Schema::create('assignments', function (Blueprint $table) { $table->increments('id'); $table->timestamps(); $table->string('name'); $table->unsignedInteger('user_id')->nullable(); $table->foreign('user_id')->references('id')->on('users'); $table->unsignedInteger('department_id')->nullable(); $table->foreign('department_id')->references('id')->on('departments'); }); public function setDepartment($users) { $departmentArray = []; $users = DB::table('users') ->leftJoin('assignments','assignments.user_id','=','users.id') ->leftJoin('departments','assignments.department_id','=','department.id') ->select('assignments.id as assignments', 'assignments.name as assignment_name', 'departments.id as dept_id', 'departments.name as dept_name', 'users.id as user_id', 'users.name as user_name' ) ->where('user_id','=',$users->id) ->get(); foreach($users as $user) { $assignments = $user->assignments; $dept_id = $user->dept_id; $departmentArray[$user->dept_id] = $user->dept_name; } $users->department = $departmentArray; $users->dept_id = $dept_id; } } Then whenever I try to call this like: public function index() { $users = DB::table('users')->get(); $users = $this->setDepartment($users); return view('/users/list', [ 'users' => $users ]); } I receive "Trying to get property 'user_id' of non-object"
'A department has many users through assignments' Documentation for hasManyThrough: https://laravel.com/docs/5.7/eloquent-relationships#has-many-through Departments Model: public function users() { return $this->hasManyThrough('App\User', 'App\Assignment'); } 'Count how many users there are for each department' Departments controller: public function index() { $departments = Department::all(); foreach($departments as $department) { // This line returns the number of users for the department // Use this however you please $department->users->count(); } } Documentation for count() found here: https://laravel.com/docs/5.7/eloquent#retrieving-aggregates You can work out the reverse of the relationship if you need to go from users to department, but I would suggest looking into eloquent, it can be quite handy for queries such as these. Let me know if you need any further clarification. Edit: For access from user to department, this is one way of defining the relationships. User Model: // A user belongs to many departments through their assignments public function departments() { return $this->hasManyThrough('App\Department', 'App\Assignment'); } This way you can access the departments of the user like so: $departments = $user->departments(); And iterate through the $departments, accessing the count() as explained above.
Eloquent How do I store data if i have 2 models with "one-to-many" on one model?
Ok, i have the following ER Diagram that shows my relations in DB: I am willing to generate a User when the Order is made. The Order can contain many Products, also the Orders are grouped by their transaction_id, so i can include all the products in the same order for a User. I am trying to save them all but i am getting Field 'transaction_id' doesn't have a default value. I've managed to save the user, also to link the order with the product and the user but i still can't figure out how to save transaction_id linked with order. These are my migrations: Schema::create('orders', function (Blueprint $table) { $table->increments('id'); $table->integer('user_id')->unsigned()->index()->nullable(); $table->foreign('user_id')->references('id')->on('users'); $table->integer('transaction_id')->unsigned(); $table->foreign('transaction_id')->references('id')->on('transactions'); $table->timestamps(); Schema::create('order_product', function (Blueprint $table) { $table->integer('order_id')->unsigned()->index(); $table->foreign('order_id')->references('id')->on('orders')->onDelete('cascade'); $table->integer('product_id')->unsigned()->index(); $table->foreign('product_id')->references('id')->on('products')->onDelete('cascade'); $table->integer('quantity')->unsigned(); $table->timestamps(); }); Schema::create('products', function (Blueprint $table) { $table->increments('id'); $table->string('name'); $table->float('price',8,2); $table->timestamps(); }); Schema::create('transactions', function (Blueprint $table) { $table->increments('id'); $table->enum('status',['open','closed']); $table->timestamps(); }); My models: User Model: public function orders() {return $this->hasMany(Order::class);} Order Model: public function user() { return $this->belongsTo(User::class); } public function products() { return $this->belongsToMany(Product::class) ->withPivot('quantity') ->withTimestamps(); } public function transaction() { return $this->belongsTo(Transaction::class); } Transaction Model: public function orders() {return $this->hasMany(Order::class);} This is how i'm trying to save them: $user->save(); $transaction->save(); $order = new Order(); $order->user_id = $user->id; $user->orders()->save($order); $transaction->orders()->save($order); $order->products()->attach($cartItem->id, ['quantity' => $cartItem->qty]); P.S. Sorry for the long post, i am out of ideeas.
Use this: $order = new Order(); $order->user_id = $user->id; $order->transaction_id = $transaction->id; $order->save();
one to many And one to many relationship laravel
This is projects migrate Schema::create('projects', function (Blueprint $table) { $table->increments('id'); $table->string('name'); $table->string('start_date'); $table->string('end_date'); $table->string('con'); $table->timestamps(); }); and this is timesheets migrate Schema::create('timesheets', function (Blueprint $table) { $table->increments('id'); $table->string('user_id'); $table->string('project_id'); $table->string('day'); $table->string('month'); $table->string('year'); $table->string('jalali'); $table->string('timesheet_h'); $table->string('timesheet_m'); $table->timestamps(); }); and this users migrate Schema::create('users', function (Blueprint $table) { $table->increments('id'); $table->string('name'); $table->string('mobile'); $table->string('salary_base'); $table->string('salary_base_h'); $table->string('start_contract'); $table->string('end_contract'); $table->string('start_insurance'); $table->string('end_insurance')->nullable(); $table->string('first_salary'); $table->string('date_birth'); $table->string('melli_code'); $table->string('s_number'); $table->string('nda'); $table->string('work_rules'); $table->string('end_work')->nullable(); $table->string('password'); $table->rememberToken(); $table->timestamps(); }); This my project model public function timesheets() { return $this->hasMany(timesheet::class,'project_id'); } This my timesheet model : public function projects() { return $this->belongsTo(project::class,'project_id'); } public function users() { return $this->belongsTo(User::class,'user_id','id'); } and This my User model public function project_peoples() { return $this->hasMany('App\project_people'); } public function timesheets() { return $this->belongsTo(timesheet::class); } public function projects() { return $this->belongsTo(project::class); } Now I return my query from projects public function allProject() { $projects=project::with(['timesheets','users'])->get(); return $projects; } This is ok but user_id Users in timesheets.user_id And I can not get it out timesheets and get it This controller return project and timesheet by project_id in timesheet but user_id in timesheet I do not know how to get this into the system
Use dot syntax to load nested relationships: project::with('timesheets.users')->get();
[{"id":1,"name":"\u067e\u0631\u0648\u0698\u0647 \u062a\u0627\u06cc\u0645 \u0634\u06cc\u062a","start_date":"1111\/11\/11","end_date":"1111\/11\/11","con":"\u062f\u0631\u062d\u0627\u0644 \u0627\u062c\u0631\u0627","created_at":"2018-01-02 10:54:11","updated_at":"2018-01-02 10:54:11","timesheets":[{"id":7,"user_id":"2","project_id":"1","day":"12","month":"10","year":"1396","jalali":"1396\/10\/12","timesheet_h":"5","timesheet_m":"24","created_at":"2018-01-02 12:40:12","updated_at":"2018-01-02 13:47:09","users":{"id":2,"name":"\u0645\u0633\u0639\u0648\u062f \u0633\u0644\u06cc\u0645\u0627\u0646\u06cc","mobile":"0000","salary_base":"1000000","salary_base_h":"20000","start_contract":"1111\/11\/11","end_contract":"1000\/00\/00","start_insurance":"1111\/11\/11","end_insurance":null,"first_salary":"100000","date_birth":"1111\/11\/11","melli_code":"1212","s_number":"1212","nda":"\u062f\u0627\u0631\u062f","work_rules":"\u062f\u0627\u0631\u062f","end_work":null,"created_at":"2018-01-02 12:36:07","updated_at":"2018-01-02 12:36:07"}},{"id":8,"user_id":"1","project_id":"1","day":"13","month":"10","year":"1396","jalali":"1396\/10\/13","timesheet_h":"10","timesheet_m":"10","created_at":"2018-01-03 05:59:13","updated_at":"2018-01-03 05:59:13","users":{"id":1,"name":"\u0645\u062c\u06cc\u062f \u0641\u06cc\u0636\u06cc","mobile":"00","salary_base":"3000000","salary_base_h":"10000","start_contract":"1111\/11\/11","end_contract":"1111\/11\/11","start_insurance":"1111\/11\/11","end_insurance":null,"first_salary":"100000","date_birth":"1111\/11\/11","melli_code":"00","s_number":"00","nda":"\u062f\u0627\u0631\u062f","work_rules":"\u062f\u0627\u0631\u062f","end_work":null,"created_at":"2018-01-02 10:53:48","updated_at":"2018-01-02 10:53:48"}},{"id":9,"user_id":"2","project_id":"1","day":"14","month":"10","year":"1396","jalali":"1396\/10\/14","timesheet_h":"10","timesheet_m":"15","created_at":"2018-01-04 07:17:44","updated_at":"2018-01-04 07:17:44","users":{"id":2,"name":"\u0645\u0633\u0639\u0648\u062f \u0633\u0644\u06cc\u0645\u0627\u0646\u06cc","mobile":"0000","salary_base":"1000000","salary_base_h":"20000","start_contract":"1111\/11\/11","end_contract":"1000\/00\/00","start_insurance":"1111\/11\/11","end_insurance":null,"first_salary":"100000","date_birth":"1111\/11\/11","melli_code":"1212","s_number":"1212","nda":"\u062f\u0627\u0631\u062f","work_rules":"\u062f\u0627\u0631\u062f","end_work":null,"created_at":"2018-01-02 12:36:07","updated_at":"2018-01-02 12:36:07"}},{"id":10,"user_id":"2","project_id":"1","day":"16","month":"10","year":"1396","jalali":"1396\/10\/16","timesheet_h":"10","timesheet_m":"60","created_at":"2018-01-06 07:17:21","updated_at":"2018-01-06 07:17:21","users":{"id":2,"name":"\u0645\u0633\u0639\u0648\u062f \u0633\u0644\u06cc\u0645\u0627\u0646\u06cc","mobile":"0000","salary_base":"1000000","salary_base_h":"20000","start_contract":"1111\/11\/11","end_contract":"1000\/00\/00","start_insurance":"1111\/11\/11","end_insurance":null,"first_salary":"100000","date_birth":"1111\/11\/11","melli_code":"1212","s_number":"1212","nda":"\u062f\u0627\u0631\u062f","work_rules":"\u062f\u0627\u0631\u062f","end_work":null,"created_at":"2018-01-02 12:36:07","updated_at":"2018-01-02 12:36:07"}}]},{"id":2,"name":"\u067e\u0631\u0648\u0698\u0647 \u062a\u0633\u062a\u06cc","start_date":"1111\/11\/11","end_date":"1111\/11\/11","con":"\u062f\u0631\u062d\u0627\u0644 \u0627\u062c\u0631\u0627","created_at":"2018-01-02 11:28:03","updated_at":"2018-01-02 11:28:03","timesheets":[{"id":3,"user_id":"1","project_id":"2","day":"12","month":"10","year":"1396","jalali":"1396\/10\/11","timesheet_h":"8","timesheet_m":"12","created_at":"2018-01-02 11:39:46","updated_at":"2018-01-02 11:39:46","users":{"id":1,"name":"\u0645\u062c\u06cc\u062f \u0641\u06cc\u0636\u06cc","mobile":"00","salary_base":"3000000","salary_base_h":"10000","start_contract":"1111\/11\/11","end_contract":"1111\/11\/11","start_insurance":"1111\/11\/11","end_insurance":null,"first_salary":"100000","date_birth":"1111\/11\/11","melli_code":"00","s_number":"00","nda":"\u062f\u0627\u0631\u062f","work_rules":"\u062f\u0627\u0631\u062f","end_work":null,"created_at":"2018-01-02 10:53:48","updated_at":"2018-01-02 10:53:48"}},{"id":4,"user_id":"1","project_id":"2","day":"12","month":"10","year":"1396","jalali":"1396\/10\/10","timesheet_h":"4","timesheet_m":"11","created_at":"2018-01-02 11:40:41","updated_at":"2018-01-02 13:49:45","users":{"id":1,"name":"\u0645\u062c\u06cc\u062f \u0641\u06cc\u0636\u06cc","mobile":"00","salary_base":"3000000","salary_base_h":"10000","start_contract":"1111\/11\/11","end_contract":"1111\/11\/11","start_insurance":"1111\/11\/11","end_insurance":null,"first_salary":"100000","date_birth":"1111\/11\/11","melli_code":"00","s_number":"00","nda":"\u062f\u0627\u0631\u062f","work_rules":"\u062f\u0627\u0631\u062f","end_work":null,"created_at":"2018-01-02 10:53:48","updated_at":"2018-01-02 10:53:48"}},{"id":6,"user_id":"1","project_id":"2","day":"12","month":"10","year":"1396","jalali":"1396\/10\/12","timesheet_h":"1","timesheet_m":"12","created_at":"2018-01-02 12:06:31","updated_at":"2018-01-02 13:49:37","users":{"id":1,"name":"\u0645\u062c\u06cc\u062f \u0641\u06cc\u0636\u06cc","mobile":"00","salary_base":"3000000","salary_base_h":"10000","start_contract":"1111\/11\/11","end_contract":"1111\/11\/11","start_insurance":"1111\/11\/11","end_insurance":null,"first_salary":"100000","date_birth":"1111\/11\/11","melli_code":"00","s_number":"00","nda":"\u062f\u0627\u0631\u062f","work_rules":"\u062f\u0627\u0631\u062f","end_work":null,"created_at":"2018-01-02 10:53:48","updated_at":"2018-01-02 10:53:48"}}]}] This is my return i have 2 users but repeat my 2 users :(
Laravel 5.5 BelongsToMany returns empty
I'm trying to use a belongsToMany relation, i never had any problems with it but for some reason it returns empty. I've set up my relation in the Store model like this: public function images() { return $this->belongsToMany('App\Images', 'images_stores', 'image_id', 'store_id'); } When i test the relationship it returns no error just a empty collection although it's not. This is the way i access the data: public function edit($id) { $store = Store::find($id); dd($store->images); return view('admin.pages.store.edit', compact('store')); } But it would just return a empty collection, i hope someone could help me out with this. These are my migration file's but i don't think the problem is inside the migration files. Schema::create('images', function (Blueprint $table) { $table->increments('id'); $table->string('name'); $table->string('path'); $table->timestamps(); }); // pivot table Schema::create('images_stores', function (Blueprint $table) { $table->increments('id'); $table->integer('image_id')->unsigned()->nullable(); $table->foreign('image_id')->references('id')->on('images')->onDelete('cascade'); $table->integer('store_id')->unsigned()->nullable(); $table->foreign('store_id')->references('id')->on('stores')->onDelete('cascade'); $table->timestamps(); }); // store table Schema::create('stores', function (Blueprint $table) { $table->increments('id'); $table->string('name'); $table->string('location'); $table->string('email'); $table->timestamps(); }); Thanks guys.
I think the ids are inverted. Try this: public function images() { return $this->belongsToMany('App\Images', 'images_stores', 'store_id', 'image_id'); }
How to query pivot table using Eloquent in Laravel 5
I have a many-to-many relationship between my client and tag tables. A client can have many tags, and each tag can be related to multiple clients. On the client show view, I'm trying to display the client info plus all tags associated to this client. How do I change the query below to retrieve the client rows with all its related tags? public function show($id) { $client = Client::findOrFail($id); return view('clients.show')->with(['client' => $client]); } Client model public function clienttag() { return $this->belongsToMany('App\Clienttag'); } Clienttag model public function client() { return $this->belongsToMany('App\Client'); } Client_clientags table migration public function up() { Schema::create('client_clienttag', function(Blueprint $table) { $table->integer('client_id')->unsigned(); $table->foreign('client_id')->references('id')->on('clients')->onDelete('cascade'); $table->integer('clienttag_id')->unsigned(); $table->foreign('clienttag_id')->references('id')->on('clienttags')->onDelete('cascade'); $table->timestamps(); }); } Clients table migration public function up() { Schema::create('clients', function(Blueprint $table) { $table->increments('id'); $table->string('first_name'); $table->string('last_name'); $table->rememberToken(); $table->timestamps(); }); } Clienttags table migration public function up() { Schema::create('clienttags', function(Blueprint $table) { $table->increments('id'); $table->string('tag'); $table->text('description'); $table->rememberToken(); $table->timestamps(); }); }
You can use "Eager Loading" methods like the following public function show($id) { $client = Client::with('clienttag')->findOrFail($id); return view('clients.show')->with(['client' => $client]); } Check documentation at http://laravel.com/docs/5.1/eloquent-relationships#eager-loading Then at your view you can print your tags #foreach ($client->clienttag as $tag) {!! $tag->tagname!!} (or whatever your field in clienttags table name is) #endforeach