Using whereHas eloquent relationship query - php

I have the following tables :
Users
Schema::create('users', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->string('username');
$table->string('email')->unique();
$table->string('password');
$table->rememberToken();
$table->timestamps();
$table->integer('role_id')->unsigned();
$table->foreign('role_id')->references('id')->on('roles');
Areas
Schema::create('areas', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->integer('location_id')->unsigned();
$table->foreign('location_id')->references('id')->on('locations')->onDelete('cascade');
$table->timestamps();
area_user
Schema::create('area_user', function (Blueprint $table) {
$table->increments('id');
$table->integer('user_id')->unsigned();
$table->foreign('user_id')->references('id')->on('users');
$table->integer('area_id')->unsigned();
$table->foreign('area_id')->references('id')->on('areas');
});
Buildings
Schema::create('buildings', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->string('symbol')->nullable();
$table->integer('area_id')->unsigned();
$table->foreign('area_id')->references('id')->on('areas')->onDelete('cascade');
$table->integer('building_type')->unsigned();
$table->foreign('building_type')->references('id')->on('building_types');
$table->timestamps();
});
User Model:
public function areas()
{
return $this->belongsToMany('App\Area');
}
Area Model:
public function users(){
return $this->belongsToMany('App\User');
}
Building Model:
public function area(){
return $this->belongsTo('App\Area','area_id');
}
How can i write a query in User model that return all Buildings assigned to a user through his assigned areas (area_user table)
I tried this , but it returning an error
Building::whereHas('area', function ($q) {
$q->whereHas('users', function ($q) {
$q->where('id', auth()->id());
});
})->get();
Error:
SQLSTATE[23000]: Integrity constraint violation: 1052 Column 'id' in where clause is ambiguous (SQL: select * from `buildings` where exists (select * from `areas` where `buildings`.`area_id` = `areas`.`id` and exists (select * from `users` inner join `area_user` on `users`.`id` = `area_user`.`user_id` where `areas`.`id` = `area_user`.`area_id` and `id` = 11))) (View: C:\xampp\htdocs\hse\resources\views\observations\form_observation.blade.php) (View: C:\xampp\htdocs\hse\resources\views\observations\form_observation.blade.php)

You can resolve the ambiguity by specifying the table in your where clause:
Change
$q->where('id', auth()->id());
To
$q->where('users.id', auth()->id());

Related

Laravel get which Categories belong to logged user in ManyToMany

in my simple blog web application i have some categories and users which stored in database, each category may belongs to one or many user and i try to get them to show each user logged, for implementing this scenario i have this tables:
Schema::create('users', function (Blueprint $table) {
$table->bigIncrements('id');
$table->unsignedBigInteger('user_id')->index()->nullable();
$table->foreign('user_id')->references('id')->on('users');
$table->string('name')->nullable();
$table->string('family')->nullable();
$table->string('username')->unique();
$table->rememberToken();
$table->softDeletes();
$table->timestamp('created_at')->useCurrent();
$table->timestamp('updated_at')->useCurrent();
});
Schema::create('categories', function (Blueprint $table) {
$table->bigIncrements('id');
$table->unsignedBigInteger('category_id')->index()->nullable();
$table->foreign('category_id')->references('id')->on('categories')->onDelete('cascade');
$table->string('category_name');
$table->softDeletes();
$table->timestamp('created_at')->useCurrent();
$table->timestamp('updated_at')->useCurrent();
});
and then, creating many to many table:
Schema::create('category_user', function (Blueprint $table) {
$table->unsignedBigInteger('user_id')->index();
$table->unsignedBigInteger('category_id')->index();
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
$table->foreign('category_id')->references('id')->on('categories')->onDelete('cascade');
$table->primary(['user_id','category_id']);
});
now how can i get categories of logged user like with this code:
$categories = Category::whereNull('category_id')
->with(['childrenCategories', 'users' => function ($query) {
//$query->where('id',auth()->user()->id);
}])
->withCount('posts')
->get();
You can query the relationship existence with whereHas to get only the categories which belongs to the authenticated user.
$categories = Category::whereNull('category_id')
->whereHas('users', function ($query) {
$query->where('id', auth()->user()->id);
})
->with([
'childrenCategories',
'users' => function ($query) {
$query->where('id', auth()->user()->id);
}
])
->withCount('posts')
->get();
inside Your User Model, add the relationship btw both Models:
public function categories()
{
return $this->belongsToMany('App\Models\Category');
}
inside Your Controller:
$user = App\Models\User::find(1);
now you can get the categories of your user
foreach ($user->categories as $category) {
//
}
https://laravel.com/docs/8.x/eloquent-relationships#many-to-many

Laravel: How to solve "SQLSTATE[HY000]: General error: 1215 Cannot add foreign key constraint"

I am making migrations where there is a particular migration that maps one table with various other tables using a foreign key. and I am getting the following error while running the migration.
SQLSTATE[HY000]: General error: 1215 Cannot add foreign key constraint (SQL: alter table bookmaps add constraint bookmaps_subject_id_foreign foreign key (subject_id) references subject (id) on delete cascade)
Here is the migration that is creating the error:
public function up()
{
Schema::create('bookmaps', function (Blueprint $table) {
$table->unsignedBigInteger('book_id')->unique();
$table->unsignedBigInteger('subject_id')->nullable();
$table->unsignedBigInteger('grade_id')->nullable();
$table->unsignedBigInteger('author_id')->nullable();
$table->unsignedBigInteger('catagory_id')->nullable();
$table->unsignedBigInteger('language_id')->nullable();
$table->timestamps();
});
Schema::table('bookmaps', function($table) {
$table->foreign('book_id')->references('id')->on('book')->onDelete('cascade');
$table->foreign('subject_id')->references('id')->on('subject')->onDelete('cascade');
$table->foreign('grade_id')->references('id')->on('grade')->onDelete('cascade');
$table->foreign('author_id')->references('id')->on('author')->onDelete('cascade');
$table->foreign('catagory_id')->references('id')->on('catagories')->onDelete('cascade');
$table->foreign('language_id')->references('id')->on('language')->onDelete('cascade');
});
}
Migrations for other related tables are:
public function up()
{
Schema::create('book', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('discription')->nullable();
$table->string('book_file')->nullable();
$table->string('card_image')->nullable();
$table->unsignedBigInteger('user_id')->nullable();
$table->timestamps();
});
Schema::table('book', function($table) {
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
});
}
The table created by above migration is only mapped by foreign key rest of the below migrations are not mapped.
public function up()
{
Schema::create('subject', function (Blueprint $table) {
$table->id();
$table->string('subject_name');
$table->timestamps();
});
}
public function up()
{
Schema::create('grade', function (Blueprint $table) {
$table->id();
$table->string('grade_name');
$table->timestamps();
});
}
public function up()
{
Schema::create('author', function (Blueprint $table) {
$table->id();
$table->string('author_name');
$table->string('author_discription')->nullable();
$table->timestamps();
});
}
public function up()
{
Schema::create('grade', function (Blueprint $table) {
$table->id();
$table->string('grade_name');
$table->timestamps();
});
}
public function up()
{
Schema::create('author', function (Blueprint $table) {
$table->id();
$table->string('author_name');
$table->string('author_discription')->nullable();
$table->timestamps();
});
}
public function up()
{
Schema::create('catagories', function (Blueprint $table) {
$table->id();
$table->string('catagories_name');
$table->timestamps();
});
}
public function up()
{
Schema::create('language', function (Blueprint $table) {
$table->id();
$table->string('language_name');
$table->timestamps();
});
}
What could be the problem?
You have to create the subject migration before the bookmarks. When Laravel tries to migrate the bookmarks table, there is a foreign key linked to the subject table that it does not find.

Laravel find records through intermediate table

I have 3 models:
User
Company
Enquiry
A user can own more than one company, a company can only belong to one user. An enquiry can belong to many companies and a company can have many enquiries.
The migrations look as follows:
User migration
Schema::create('users', function (Blueprint $table) {
$table->increments('id');
$table->string('first_name');
$table->string('last_name');
$table->string('email')->unique();
$table->timestamp('email_verified_at')->nullable();
$table->string('contact_number');
$table->longText('address')->nullable();
$table->integer('postal_code');
$table->string('activation_token')->nullable();
$table->boolean('active')->default(false);
$table->enum('type', ['Admin', 'End User', 'Service Provider', 'Broker']);
$table->string('password')->nullable();
$table->rememberToken();
$table->timestamps();
$table->softDeletes();
});
Company Migration
Schema::create('companies', function (Blueprint $table) {
$table->increments('id');
$table->unsignedInteger('service_provider_id')->nullable();
$table->unsignedInteger('broker_id');
$table->string('name');
$table->string('email')->unique()->nullable();
$table->string('contact_number');
$table->longText('address')->nullable();
$table->integer('postal_code');
$table->enum('status', ['Confirmed', 'Declined', 'New'])->default('New');
$table->timestamps();
$table->softDeletes();
});
Schema::table('companies', function (Blueprint $table) {
$table->foreign('service_provider_id')->references('id')->on('users');
$table->foreign('broker_id')->references('id')->on('users');
});
Enquiries Migration
Schema::create('enquiries', function (Blueprint $table) {
$table->increments('id');
$table->unsignedInteger('end_user_id');
$table->unsignedInteger('category_id');
$table->string('title');
$table->longText('description');
$table->integer('radius');
$table->enum('status', ['New', 'In Progress', 'Complete'])->default('New');
$table->timestamps();
});
Schema::table('enquiries', function (Blueprint $table) {
$table->foreign('end_user_id')->references('id')->on('users');
$table->foreign('category_id')->references('id')->on('categories');
});
CompanyEnquiry Migration
Schema::create('company_enquiry', function (Blueprint $table) {
$table->integer('company_id')->unsigned()->index();
$table->foreign('company_id')->references('id')->on('companies')->onDelete('cascade');
$table->integer('enquiry_id')->unsigned()->index();
$table->foreign('enquiry_id')->references('id')->on('enquiries')->onDelete('cascade');
$table->primary(['company_id', 'enquiry_id']);
});
I have set up the various relationships in their respective models.
What I'm trying to achieve is query the database to retrieve only those enquiries which belong to the user via the company.
How can I achieve this?
Something like this (add the real model, relation names ans columns):
$enquiries = Enquiries::whereHas(['companies' => function($query){
$query->whereHas(['user' => function($query){
$query->where('id', $user_id);
}]);
})
->get();
You could do it this way with shorter code.
$enquiries = Enquiries::whereHas('companies.user', function($query) use($user_id){
$query->where('id', $user_id);
})->get();

Laravel - get data out from many to many relations

I have a many to many relation
public function products()
{
return $this->belongsToMany(Product::class); // relation between books and categories
}
public function parts()
{
return $this->belongsToMany(Part::class); // relation between books and categories
}
my migrations :
public function up()
{
Schema::create('products', function (Blueprint $table) {
$table->increments('id');
$table->unsignedInteger('user_id');
$table->string('link')->default('anohe.com');
$table->string('pname')->default('product');
$table->timestamps();
$table->string('description',3000)->nullable();
$table->string('smalldescription',500)->nullable();
});
}
public function up()
{
Schema::create('parts', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->timestamps();
});
}
public function up()
{
Schema::create('part_product', function (Blueprint $table) {
$table->increments('id');
$table->unsignedInteger('product_id');
$table->unsignedInteger('part_id');
$table->timestamps();
$table
->foreign('product_id')
->references('id')
->on('products')
->onDelete('cascade');
$table
->foreign('part_id')
->references('id')
->on('parts')
->onDelete('cascade');
});
}
How can I get products that have a special part_id?
If your relations are correct, that should work:
$specialPartIds = [1];
$products = Product::whereHas('parts', function ($query) use ($specialPartIds) {
$query->whereIn('id', $specialPartIds);
})->get();
dd($products->toArray());

Laravel Many to Many Relationship Users on Shift

I'm trying to get the users that are on today's shift. I have a many to many relationship between the User and Shift model with a pivot table called user_shifts.
My User model:
/**
* Get the users shifts
*/
public function shift()
{
return $this->belongsToMany('App\Shift', 'user_shifts', 'user_id', 'shift_id');
}
My Shift model
/**
* The shift can have many users
*/
public function users()
{
return $this->belongsToMany('App\User', 'user_shifts', 'shift_id', 'user_id')->withPivot('start_time', 'end_time');;
}
In my controller I thought I could do something like:
$shift = Shift::all()->where('date', date('Y-m-d'));
$users = User::all()->where('shift_id', $shift);
return $users;
But that is returning null. Any help would be appreciated!
If it matters my db schema is:
Schema::create('shifts', function (Blueprint $table) {
$table->increments('id');
$table->date('date');
$table->boolean('weekend');
});
Schema::create('user_shifts', function (Blueprint $table) {
$table->increments('id');
$table->integer('shift_id');
$table->integer('user_id');
$table->time('start_time');
$table->time('end_time');
});
Schema::create('users', function (Blueprint $table) {
$table->increments('id');
$table->string('fname');
$table->string('lname');
$table->string('email')->unique();
$table->string('password', 60);
$table->rememberToken();
$table->timestamps();
});

Categories