Laravel eloquent relationships hasMany two foreign keys error - laravel

I use Laravel 7.2 and I've 2 models:
User
public function orders()
{
if($this->hasRole("seller")) {
return $this->hasMany('App\Models\Order', 'seller_id', 'id');
} else if($this->hasRole("client")) {
return $this->hasMany('App\Models\Order', 'user_id', 'id');
}
}
Order
Migration:
Schema::create('orders', function (Blueprint $table) {
$table->id();
$table->boolean('status')->default(false);
$table->text('description')->nullable();
$table->unsignedBigInteger('user_id');
$table->foreign('user_id')
->references('id')
->on('users')
->onDelete('cascade');
$table->unsignedBigInteger('seller_id');
$table->foreign('seller_id')
->references('id')
->on('users')
->onDelete('cascade');
$table->timestamps();
$table->softDeletes();
});
Code:
public function user()
{
return $this->belongsTo('App\Models\User', 'user_id');
}
public function seller()
{
return $this->belongsTo('App\Models\User', 'seller_id');
}
Now in my case users has two roles seller or client. But when I try get user orders laravel return me error message:
Call to a member function addEagerConstraints() on null
Or when I try get custom order user or seller related data also return same error message.
Where I've any error or I've create relationships incorrectly?

This occurs because the condition in the relation here:
public function orders()
{
if($this->hasRole("seller")) {
return $this->hasMany('App\Models\Order', 'seller_id', 'id');
} else if($this->hasRole("client")) {
return $this->hasMany('App\Models\Order', 'user_id', 'id');
}
}
Imagine users who has neither roles 'seller' or 'client' then Null will be returned and that is exactly the issue.
I recommend you to split the method orders into two methods sellerOrders and clientOrders.

Related

sync subcategory in laravel

i made products and categories and sub categories
when i do sync them , product and category save in the category_prodcts.
but sub category shows a error message :
SQLSTATE[HY000]: General error: 1364 Field 'subcategory_id' doesn't have a default value (SQL: insert into `category_products` (`category_id`, `product_id`) values (1, 1))
and these are my codes :
productController:
$data->cats()->sync($request->cats,false);
$data->subcategory()->sync($request->subcategory,false);
Product Model:
public function CATS(){
return $this->belongsToMany(Category::class, 'category_products',
'product_id', 'category_id');
}
public function subcategory()
{
return $this->belongsToMany(SubCategory::class,
'category_products','subcategory_id','category_id' );
}
subcategory Model:
public function products()
{
return $this->belongsToMany(Products::class,'subcategory_products',
'category_id','subcategory_id');
}
public function category(){
return $this->belongsToMany(Category::class)->withTimestamps();
}
category model:
public function subcategory()
{
return $this->belongsToMany(Subcategory::class,
'category_subcategory', 'category_id', 'subcategory_id' );
}
category_product database:
$table->unsignedBigInteger('product_id');
$table->unsignedBigInteger('category_id');
$table->unsignedBigInteger('subcategory_id');
$table->foreign('product_id')
->references('id')
->on('products')
->onDelete('cascade');
$table->foreign('category_id')
->references('id')
->on('categories')
->onDelete('cascade');
$table->foreign('subcategory_id')
->references('id')
->on('categories')
->onDelete('cascade');
$table->primary(['category_id','product_id','subcategory_id']);
enter code here
thanks for your help

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');
}

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);

Mutator and relations

Using Laravel 5.2, I have a mutator set up in my Team model:
public function getNameAttribute($value)
{
if ($this->exists) {
return !empty($value) ? $value : $this->organization()->first()->name;
}
return null;
}
Relation with Organization's model:
public function organization()
{
return $this->belongsToMany('App\Models\Organization')->withTimestamps();
}
when $team->name is empty, I try to get $this->organization()->first()->name but.. an error occurred :
Trying to get property of non-object
After two hours, I haven't found the problem
EDIT:
Schema::table('organization_team', function (Blueprint $table) {
$table->foreign('organization_id')
->references('id')
->on('organizations')
->onUpdate('cascade')
->onDelete('cascade');
$table->foreign('team_id')
->references('id')
->on('teams')
->onUpdate('cascade')
->onDelete('cascade');
});
$this->organization()->first() must return a null in your application.
So check your database and add some relation data.
You can find a org name like this.
$this->organization->first(function ($item) {
return ! empty($item->name);
})->name;
It's very simple, just do it like that:
public function getNameAttribute($value)
{
if ($this->exists) {
return !empty($value) ? $value : $this->organization
->first()->name;
}
return null;
}

One to Many not working on Laravel Eloquent

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();

Resources