One to Many not working on Laravel Eloquent - laravel

I have three models that are related. First I have User that belongs to a Role. On the other hand, Role has many roles. Role belongs to many permissions and Permissions belongs to many Role. I am using the AuthServiceProvider as suggested by jeffrey way of laracast. But the problem now, when I want to fetch all the permissions of a User I am having error which is, "Call to a member function getKey() on boolean". Can someone please help me on this. Please refer to the codes below.
User.php
public function role()
{
return $this->belongsTo('App\Role');
}
public function assignRole($role)
{
return $this->roles()->save(
Role::whereName($role)->firstOrFail()
);
}
public function hasRole($role)
{
if(is_string($role)){
return $this->role->contains('name', $role);
}
return !! $role->intersect($this->role)->count();
}
Role.php
class Role extends Model
{
public function users()
{
return $this->hasMany('App\User');
}
public function permissions()
{
return $this->belongsToMany('App\Permission');
}
public function givePermissions(Permission $permission)
{
return $this->permissions()->save($permission);
}
}
Permission.php
class Permission extends Model
{
public function roles()
{
return $this->belongsToMany('App\Role');
}
}
AuthServiceProvider
public function boot(GateContract $gate)
{
$this->registerPolicies($gate);
//get all permissions
foreach ($this->getPermissionTo() as $permission ) {
$gate->define($permission->name, function($user) use ($permission){
return $user->hasRole($permission->roles);
});
}
}
public function getPermissionTo()
{
return Permission::with('roles')->get();
}
and lastly, heres the user table that has a foreign key of role_id
Schema::create('users', function (Blueprint $table) {
$table->increments('id');
$table->integer('role_id')->unsigned();
$table->string('id_no')->unique()->index();
$table->string('u_first_name');
$table->string('u_middle_name');
$table->string('u_last_name');
$table->string('email')->unique();
$table->string('password');
$table->rememberToken();
$table->timestamps();
});
roles table
Schema::create('roles', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->string('label')->nullable();
$table->timestamps();
});
permissions table
Schema::create('permissions', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->string('label')->nullable();
$table->timestamps();
});
permission_role table
Schema::create('permission_role', function (Blueprint $table) {
$table->integer('permission_id')->unsigned();
$table->integer('role_id')->unsigned();
$table->foreign('permission_id')
->references('id')
->on('permissions')
->onDelete('cascade');
$table->foreign('role_id')
->references('id')
->on('roles')
->onDelete('cascade');
$table->primary(['permission_id', 'role_id']);
});

In the line: return !! $role->intersect($this->role)->count();, the part that says $this->role is probably not returning a collection, which is why you're getting this error. In Collection.php there's a method that iterates through all the items in a collection you send through the intersection method that gets the primary key of it. Because you're not sending a collection to the intersect() method, it tries to use the method getKey() in a boolean. Try:
return !! $role->intersect($this->role->get())->count();

Related

Laravel: cannot insert into many to many relationship

i hope you're having a good day.
so i have this ManyToMany relationship where a user can apply to multiple jobs, and a job can have multiple applicants (users).
here is the table schema
Schema::create('applicant_job', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('job_id');
$table->unsignedBigInteger('applicant_id');
$table->unique(['job_id', 'applicant_id']);
$table->foreign('job_id')
->references('id')
->on('jobs')
->onDelete('cascade');
$table->foreign('applicant_id')
->references('id')
->on('default_users')
->onDelete('cascade');
});
and here is the model code.
DefaultUser.php
class DefaultUser extends Model
{
public function user()
{
return $this->morphOne(User::class, 'userable');
}
public function applications()
{
return $this->belongsToMany(Job::class, 'applicant_job', 'job_id', 'applicant_id');
}
}
and Job.php
class Job extends Model
{
public function owner()
{
return $this->belongsTo(BusinessUser::class, 'business_user_id');
}
public function applicants()
{
return $this->belongsToMany(DefaultUser::class, 'applicant_job', 'applicant_id', 'job_id');
}
}
everything seems ok and find, however when i try to save ( a user applying to a job), i get the following error
i'm doing so inside ApplyToJobController.php
class ApplyToJobController extends Controller
{
public function store(Job $job, Request $request) {
$default_user = auth()->user()->userable;
$job->applicants()->attach($default_user->id);
return redirect("/en");
}
}
and, Thank you very much for your answers.
EDIT
i have changed the column names to this
Schema::create('applicant_job', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('job_id');
$table->unsignedBigInteger('default_user_id');
$table->unique(['job_id', 'default_user_id']);
$table->foreign('job_id')
->references('id')
->on('jobs')
->onDelete('cascade');
$table->foreign('default_user_id')
->references('id')
->on('default_users')
->onDelete('cascade');
});
it made it work, im curios any idea why?
Try to switch the order of the foreign keys in the applicants relation declared in the Job model like the example below :
public function applicants()
{
return $this->belongsToMany(DefaultUser::class, 'applicant_job', 'job_id', 'applicant_id');
}

Trying to get property of non-object when i try to $blog->user->name

in my model user
public function blogs(){
return $this->hasMany('App\Blog');
}
in my model blog
public function user(){
return $this->belongsTo('App\User','user_id');
}
in my BlogController
public function show($id)
{
$blog = Blog::find($id);
dd($blog->user->name);
return view('admin.pages.blogs.show',compact('blog'));
}
database table user ( id,role_id,name)
if role_id = 1(admin) then result $blog->user->name is null
if role_id = 2(author) then result $blog->user->name is name of user
how can i fix when role_id = 1
You need to remove user_id from Blog model.
public function user()
{
return $this->belongsTo(User::class);
}
UPD. In any case role_id does not matter. So you need to make sure DB contains related records. For example:
blogs:
id user_id text
1 123 '...'
users:
id name
123 'Linh'
First of all you change blogs users and roles migration.
blogs migration
Schema::create('blogs', function (Blueprint $table) {
$table->bigIncrements('id');
$table->unsignedBigInteger('user_id');
$table->foreign('user_id')->references('id')->on('users');
$table->string('title');
$table->string('slug')->unique();
$table->string('image');
$table->string('body');
$table->tinyInteger('status')->default(0);
$table->tinyInteger('is_approved')->default(0);
$table->integer('view_count')->default(0);
$table->timestamps();
});
users migration
Schema::create('users', function (Blueprint $table) {
$table->bigIncrements('id');
$table->unsignedBigInteger('role_id')->default(2);
$table->foreign('role_id')->references('id')->on('roles');
$table->string('name');
$table->string('username')->unique();
$table->string('email')->unique();
$table->string('password');
$table->string('image')->default('default.png');
$table->text('about')->nullable();
$table->rememberToken();
$table->timestamps();
});
roles migration
Schema::create('roles', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('name');
$table->string('slug')->unique();
$table->timestamps();
});
User model
public function blogs(){
return $this->hasMany('App\Blog');
}
Blog model
public function user(){
return $this->belongsTo('App\User');
}
BlogController
public function show($id)
{
$blog = Blog::find($id);
dd($blog->user->name);//check
return view('admin.pages.blogs.show',compact('blog'));
}

Fetching Relationship Model Data

I have the Below Table Structure
Users table
id- integer
name-string
Casefiles table
id- integer
user_id- foreign_key
name-string
Followups table
id- integer
date- date
casefile_id-foreign_key
I'm using the below Relationship between this models
User.php
public function casefiles()
{
if ($this->hasRole(['sales_executive'])) {
return Casefile::where('user_id', $this->id);
}
}
Casefile.php
public function user()
{
return $this->belongsTo('App\User');
}
public function followups()
{
return $this->hasMany('App\FollowUp');
}
Followup.php
public function casefile()
{
return $this->belongsTo('App\Casefile');
}
I want to fetch Users followups directly. How can i achive this ?
you need to use hasManyThrough() in your User.php you can add this,
public function followUps()
{
return $this->hasManyThrough('App\FollowUp','App\Casefile');
}
then you can normally call the followups using User::with('followUps')->find(1)->followUps
I have noticed that you are checking role in your relationship $this->hasRole(['sales_executive'] this may occur error as you are not if the statement is false. I think you take another approached and handle that as well. for more information on hasManyThrough prefer this link
This should be the case for a HasManyThrough Relationship.
In your case it should be
// Followups migration
Schema::create('followups', function (Blueprint $table) {
$table->bigIncrements('id');
$table->date('date');
$table->unsignedBigInteger('casefile_id')->nullable();
$table->timestamps();
$table->foreign('casefile_id')
->references('id')
->on('casefiles');
});
// Casefile migration
Schema::create('casefiles', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('name');
$table->unsignedBigInteger('user_id')->nullable();
$table->timestamps();
$table->foreign('user_id')
->references('id')
->on('users');
});
// User.php
public function followups() {
return $this->hasManyThrough(FollowUp::class, Casefile::class);
}
// YourController.php
$user = User::all()->first();
dd($user->followups);

Eloquent relationship property access

Cant seem to figure out the probleme here, getting error - Trying to get property 'name' of non-object
User DB
Schema::create('users', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->string('lastname');
$table->string('email')->unique();
$table->string('password');
$table->integer('phone');
$table->boolean('isAdmin')->default(0);
$table->rememberToken();
$table->timestamps();
});
Sludinajums DB
Schema::create('sludinajums', function (Blueprint $table) {
$table->increments('id');
$table->string('logo');
$table->string('nosaukums');
$table->string('regnr');
$table->string('text');
$table->string('atrasanasVieta');
$table->string('adrese');
$table->integer('telefons');
$table->string('epasts');
$table->integer('profesija_id')->unsigned();
$table->foreign('profesija_id')->references('id')->on('profesijas')->onDelete('cascade');
$table->integer('lietotajs_id')->unsigned();
$table->foreign('lietotajs_id')->references('id')->on('users')->onDelete('cascade');
$table->timestamps();
});
User model function
public function sludinajums()
{
return $this->hasOne(sludinajums::class,'lietotajs_id');
}
Sludinajums model function
public function user()
{
return $this->belongsTo('App\User');
}
Here is my controller function
public function sludinajuma_skats($id){
$slud = sludinajums::where('id',$id)->with('user')->get();
return view('views.sludinajums', compact('slud'));
}
And in my view im trying to access name attribute from User table.
{{dd($sl->user->name)}}
try this for Sludinajums model function
public function user()
{
return $this->hasMany('App\User','lietotajs_id');
}

Laravel 5.4 belongsToMany relationship returns empty

In Laravel 5.4 I'am trying to set up a Many To Many Relation. but the belongsToMany returns empty! Here's my migrations and models.
botusers Table:
public function up()
{
Schema::create('botusers', function (Blueprint $table) {
$table->increments('id');
$table->integer('t_id');
$table->string('first_name');
$table->string('last_name');
$table->string('username');
$table->string('mobile');
$table->timestamps();
});
}
candidates Table:
public function up()
{
Schema::create('candidates', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->string('token');
$table->string('degree');
$table->integer('age');
$table->text('desc');
$table->string('photo_url');
$table->string('cv_url');
$table->timestamps();
});
}
Third table, botuser_candidate Table:
public function up()
{
Schema::create('botuser_candidate', function (Blueprint $table) {
$table->integer('botuser_id');
$table->integer('candidate_id');
});
}
and the votes() method in Botuser Model:
public function votes()
{
return $this->belongsToMany(Candidate::class)->get();
}
When I fire the votes() method returns an empty array. and I also tested bellow method too,
public function votes()
{
return $this->belongsToMany(Candidate::class,'botuser_candidate','botuser_id','candidate_id')->get();
}
What I missed here? What should I do?
Edit:
I also added the foreign keys to the relation but the result is still same!
I would suggest you remove the get() method on the belongsToMany
Then query the database with
$c=new App\Candidate;
$c->with('votes')->get()
if you still want to use $c->votes() then you would have to do some changes to your functions. Lets use scope to achieve it.
public function candidates()
{
return $this->belongsToMany(Candidate::class,'botuser_candidate','botuser_id','candidate_id');
}
public function scopeVotes($query)
{
return $query->with("candidates")->get();
}
Then now we can call $v->votes() and it should return all your record.
Calling get() directly on belongsToMany method will return empty array.

Resources