Laravel relationship many to many count related data by foreign key - laravel

I have 3 models in my project:
User model code:
<?php
namespace App\Models;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
class User extends Authenticatable
{
use Notifiable;
protected $guarded = [];
public function professions()
{
return $this->belongsToMany('App\Models\Profession', 'user_professions');
}
}
Profession model code
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Profession extends Model
{
protected $guarded = [];
public function users()
{
return $this->belongsToMany('App\Models\User', 'user_professions');
}
}
Migration:
$table->id();
$table->string("name");
$table->timestamps();
UserProfession model code
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class UserProfession extends Model
{
//
}
Migration:
$table->id();
$table->foreignId('user_id')
->constrained()
->onDelete('cascade');
$table->foreignId('profession_id')
->constrained()
->onDelete('cascade');
When I try this code where I search users by his name and get there professions name then count users in that professions.
Code:
$query = $request->get("query");
$users = User::where("name", "like", "%".$query."%");
$userIds = $users->get()->pluck("id")->toArray();
$professions = Profession::whereHas("users", function($q) use($userIds) {
$q->whereIn('id', $userIds);
})->get()->toArray();
I get error with message:
Illuminate\Database\QueryException: SQLSTATE[23000]: Integrity
constraint violation: 1052 Column 'id' in where clause is ambiguous
(SQL: select * from professions where exists (select * from users
inner join user_professions on users.id = user_professions.user_id
where professions.id = user_professions.profession_id and id in (11,
43, 82)))
Where I have error in my code and how I can fix it?

There are three tables users,user_professions and professions that all have id column.
You need to specify which table's id that you want:
$professions = Profession::whereHas("users", function($q) use($userIds) {
$q->whereIn('users.id', $userIds); // specify the table name
})->get()->toArray();

Related

Database relations in Laravel Module

I've a problem in using database relationships together with Laravel module.
for example:
I've User module & Profile Module
I've One-to-One relation between user & profile (in 2 separated modules)
I need to get profile information when I have user data (example: $user->profile)
But I think because of creating relation between two modules, I cannot access to this relation.
My received error:
"message": "SQLSTATE[42S02]: Base table or view not found: 1146 Table 'user.profiles' doesn't exist (SQL: select * from profiles where profiles.user_id = 2 and profiles.user_id is not null limit 1)",
"exception": "Illuminate\Database\QueryException",
User Module/Entities/User.php
<?php
namespace Modules\User\Entities;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Modules\VofourCourse\Entities\Profile;
class User extends Authenticatable
{
use HasFactory;
protected $connection = 'user';
protected $guarded = [];
protected $hidden = [
'password',
'remember_token',
];
protected $casts = [
'email_verified_at' => 'datetime',
];
public function profile()
{
return $this->hasOne(Profile::class);
}
}
Profile Module/Entities/Profile.php
<?php
namespace Modules\Profile\Entities;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\SoftDeletes;
use Modules\User\Entities\User;
use RichanFongdasen\EloquentBlameable\BlameableTrait;
class Profile extends Model
{
use HasFactory, SoftDeletes, BlameableTrait;
protected $guarded = [];
public function user()
{
return $this->belongsTo(User::class);
}
}
Profile Module/Controller/ProfileController.php
<?php
namespace Modules\Profiole\Http\Controllers;
use Illuminate\Routing\Controller;
class ProfileController extends Controller
{
public function showProfile()
{
$user = auth('api')->user();
return $user->profile;
}
}
Profile migration
Schema::create('profiles', function (Blueprint $table) {
$table->id();
$table->foreignId('user_id')->onDelete('cascade');
$table->string('whatsapp_mobile', 15)->unique();
$table->string('phone', 15)->unique();
$table->string('national_code', 10)->nullable();
$table->string('postal_code', 10)->nullable();
$table->text('address')->nullable();
$table->string('job_title')->nullable();
$table->foreignId('city_id')->nullable();
$table->string('father_name')->nullable();
$table->enum('marital_status', ['married', 'single', 'widow', 'divorced', 'unknown'])->default('married');
});
User migration
Schema::connection(config('modules.connections.user_database'))->create('users', function (Blueprint $table) {
$table->id();
$table->string('firstname')->nullable();
$table->string('lastname')->nullable();
$table->string('email')->unique()->nullable();
$table->string('vofour_id' , 10)->nullable();
$table->string('username', 20)->nullable();
$table->timestamp('email_verified_at')->nullable();
$table->string('password')->nullable();
$table->date('birth_date')->nullable();
$table->enum('gender', ['male', 'female'])->nullable();
$table->string('mobile', 15)->unique();
$table->enum('status', ['active', 'inactive'])->default('active');
$table->rememberToken();
});```
thanks a lot for your helps & guidance
You've a typing error in your relationship. The error states there should be a relation profiles where as from your code there's a profile.
public function profile()
{
return $this->hasOne(Profile::class);
}
What you can do is return user->with('profile') which will return the user with it's relational details. I.e.
<?php
namespace Modules\Profiole\Http\Controllers;
use Illuminate\Routing\Controller;
class ProfileController extends Controller
{
public function showProfile()
{
$user = auth('api')->user();
return $user->with('profile');
}
}
Also update your profiles migration line where user_id is written from:
$table->foreignId('user_id')->onDelete('cascade'); to $table->foreignId('user_id')->constrained('users');.
This will link up the user_id as a foreign key to users table id. and return the correct collection of users with their profiles.

laravel can't delete a row with one to many relation

I have one to many relation in my project ( the user has many details ), and when i delete any user row it says
SQLSTATE[23000]: Integrity constraint violation: 1451 Cannot delete or update a parent row: a foreign key constraint fails (`sehhatys_saudi`.`details`, CONSTRAINT `details_user_id_foreign` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`)) (SQL: delete from `users` where `id` = 9)
the details table migration
Schema::create('details', function (Blueprint $table) {
$table->id();
$table->bigInteger('user_id')->unsigned();
$table->string('check_date', 100);
$table->string('result_date', 100);
$table->string('result', 100);
$table->string('check_center', 100);
$table->timestamps();
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
});
the User model
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
use HasFactory;
protected $fillable = ['name', 'name_en', 'national_id',
'birth_date', 'user_password', 'nationality', 'nationality_en',
'vaccine_type_one', 'vaccine_type_one_en', 'date_one',
'batch_number_one', 'vaccine_type_two', 'vaccine_type_two_en',
'date_two', 'batch_number_two', 'report_id', 'qr_url', 'access_token',
'phone', 'email', 'social', 'social_en', 'weight', 'height', 'mass',
'blood_pressure', 'blood_sugar', 'waist', 'hypertension',
'hypertension_en', 'diabetes', 'diabetes_en', 'city', 'city_en',
'health_center', 'health_center_en'];
public function details(){
return $this->hasMany('App\Detail');
}
}
the Detail model
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Detail extends Model
{
use HasFactory;
protected $fillable = ['user_id', 'check_date', 'result_date',
'result', 'check_center'];
public function user(){
return $this->belongsTo('App\User');
}
}
the delete function for the user row
public function delete($id)
{
User::findOrFail($id)->delete();
return redirect(route('users.all'));
}
even when edited the delete function and make it like this
public function delete($id)
{
$user = User::findOrFail($id);
$user->details()->delete();
$user->delete();
return redirect(route('users.all'));
}
it returns this error
Class "App\Detail" not found
The name space for your Detail Model is namespace App\Models; While you are using App\Detail in User.php.
The relation in User model should be:
public function details(){
return $this->hasMany('App\Models\Detail');
}
If you are using laravel-8 it should be like:
public function details(){
return $this->hasMany(App\Models\Detail::class);
}

Laravel Eloquent: How to filter results of related models?

I have tables on Database:
orders
--id
--customer_id
customers
--id
--name
--country_id
countries
--id
--name
And next eloquent models:
Order.php:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Order extends Model
{
/**
* #return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function customer()
{
return $this->belongsTo('App\Models\Customer');
}
}
Customer:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Customer extends Model
{
/**
* #return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function country()
{
return $this->belongsTo('App\Models\Country');
}
}
Country:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Country extends Model
{
}
Now i need to get all order where customer country name like 'Uk' by one sql query. How I can do it ?
The following should do the trick:
Order::whereHas('customer.country', function($innerQuery) {
$innerQuery->where('countries.name', 'LIKE', 'Uk');
})->get();
I am not sure if this is a good way of thinking but maybe I have helped
$orders = App\Order::whereHas('customer.country', function ($query) {
$query->where('name', 'like', 'UK%');
})->get();

How to properly setup a cross database relationship in laravel? +eloquent

I can't seem to figure out how to have a table in one database have a relationship with another table in a different database.
like Customer uses the 'directory' database.
namespace App\Models;
use App\User;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
class Customer extends Model
{
use SoftDeletes;
protected $connection = 'directory';
public $fillable = [
'id',
'customer_type_id',
'user_id'
];
public function owners(){
return $this->hasMany(User::class)->whereHas('roles', function($query){ $query->where('name', 'owner');});
}
public function employees(){
return $this->hasMany(User::class)->whereHas('roles', function($query){ $query->where('name', 'employee');});
}
}
Then in the User::class just uses the default 'mysql' database
namespace App;
use App\Models\Customer_form;
use Laravel\Passport\HasApiTokens;
use Illuminate\Notifications\Notifiable;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable
{
use HasApiTokens, Notifiable, SoftDeletes;
protected $connection = 'mysql';
protected $fillable = [
'name', 'email', 'password',
];
protected $hidden = [
'password', 'remember_token',
];
protected static function boot() {
// create an event to happen on deleting
static::deleting(function($user) {
$user->roles()->detach();
});
}
public function roles()
{
return $this
->belongsToMany("App\Role")
->withPivot('id','can_read', 'can_create', 'can_update', 'can_delete');
}
public function customer(){
return $this->belongsTo(App\Models\Customer::class, "customer_id", "id")->with("primaryName");
}
}
Then i am calling this relationship in my controller like so:
$customerUsers = Customer::has('owners')->with('owners')->with('employees')->get();
Then it gives me an error like its trying to query just one of the databases looking for a table that doesn't exist in THAT database( "directory" )
SQLSTATE[42S02]: Base table or view not found: 1146 Table 'directory.role_user' doesn't exist (SQL: select * from `customers` where exists (select * from `users` where `customers`.`id` = `users`.`customer_id` and exists (select * from `roles` inner join `role_user` on `roles`.`id` = `role_user`.`role_id` where `users`.`id` = `role_user`.`user_id` and `name` = owner)) and `customers`.`deleted_at` is null)
Any idea what i am missing? Or can you not do cross-database relations?
Check this package, it allows you to use cross database subquery (has, whereHas, doesntHave, whereDoesntHave, withCount).
https://github.com/hoyvoy/laravel-cross-database-subqueries
The solution to my issue was using making an attribute method in the model that made a call to the second database.

Issue in laravel 5.3 relationship?

I want to search in contacts table and in communication links table according to name or mobile no. where my mobile is in communication_links table in 'value' and fname and lname is in contacts table. but there is a relation in communication link and in resource_status by using rest_id. and again resource_status is connected with resource type.
This is my raw sql query
SELECT contacts.fname, contacts.lname, communication_links.value FROM contacts ,communication_links,resource_status
where
(contacts.id = communication_links.cont_id)
AND
(communication_links.rest_id = resource_status.id)
AND
resource_type.status LIKE '{mobile}%'
AND
(communication_links.value LIKE '{$search_string}%' OR
contacts.fname LIKE '{$search_string}% OR contacts.lname LIKE '{$search_string}% )
I have following table structure
contacts
id
fname
lname
dob
communication_links
id
rest_id
cont_id
value
resource_type
id
type
resource_status
id
Status
rety_id
And I created following models to maintain the relationship
Contact.php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Contact extends Model
{
protected $connection = 'mysql_freesubs';
public $timestamps = false;
public function communicationLinks()
{
return $this->hasMany(Communication_link::class, 'cont_id');
}
}
Communication_link.php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Communication_link extends Model
{
protected $connection = 'mysql_freesubs';
public $timestamps = false;
public function resource()
{
return $this->belongsTo(Resource_status::class, 'rest_id');
}
public function contact()
{
return $this->belongsTo(Contact::class, 'cont_id');
}
}
Resource_status.php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Resource_status extends Model
{
protected $connection = 'mysql_freesubs';
protected $table = 'resource_status';
}
Resource_type.php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Resource_type extends Model
{
protected $connection = 'mysql_freesubs';
public $timestamps = false;
public function resourceStatuses()
{
return $this->hasMany(Resource_status::class, 'rety_id');
}
}
I tried to write same query as i have given above but i haven't got a desire result:
$parent_contact = \App\Contact::with('communicationLinks.resource')
->whereHas('communicationLinks.resource', function ($query) {
$query->where('status', 'LIKE', "{mobile}%");
})
->whereHas('communicationLinks.contact',function ($query) use($request) {
$query->where('communicationLinks.value','LIKE',"{$request->search_string}%")
->orWhere('fname','LIKE',"{$request->search_string}%")
->orWhere('lname','LIKE',"{$request->search_string}%");
})
->get();
$query = DB::table("contacts as a")
->select(array("a.fname", "b.lname", "b.value"))
->join("communication_links AS b", "a.id", "=", "b.cont_id")
->join("resource_type AS c", "b.rest_id", "=", "c.id")
->where("a.status", "like", $mobile."%")
->where("b.value", "like", $search_string."%")
->orWhere("a.fname", "like", $search_string."%")
->orWhere("a.lname", "like", $search_string."%")
->get();
That should do the job for you.
You can just iterate through it to get your values as desired

Resources