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

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.

Related

Laravel relationship many to many filtering on pivot field

I have a relationship between Invoice and Shift.
Invoice model
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Invoice extends Model
{
public $primaryKey = 'id';
protected $fillable = [
'user_id',
'date_ins',
'closeco',
'closedrh',
'lvl',
'new',
];
public function user()
{
return $this->hasOne(User::class,'id','user_id');
}
/**
* The roles that belong to the invoice.
*/
public function shifts()
{
return $this->belongsToMany(Shift::class, 'invoice_shift')
->withPivot([
'invoice_id', 'shift_id', 'shift_taken_id', 'shift_swapped_date', 'shift_taken_date', 'tas',
'status_tas', 'status_co', 'status_drh', 'back_co',
'msg', 'msg_co', 'msg_drh'
])
->orderBy('status_drh', 'ASC')
->orderBy('status_co', 'ASC');
}
}
Shift model
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Shift extends Model
{
public $primaryKey = 'id';
protected $fillable = [
'code',
'description',
];
/**
* The users that belong to the role.
*/
public function invoices()
{
return $this->belongsToMany(Invoice::class, 'invoice_shift')
->orderBy('status_drh', 'ASC')
->orderBy('status_co', 'ASC');
}
}
So I have a pivot table called Invoice_shift.
I cannot extract, starting from invoices table, just invoices that have tas (in invoice_shift table) = current logged user.
I cannot filter as a static value in Invoice model definition with wherepivot because it is dynamic value, every time logged user id is different.
I tried to do this in controller
$invoices = Invoice::with('shifts.invoices')
->orderBy('date_ins', 'DESC')->get();
$filter = $invoices->shifts()
->wherePivot('tas', '=', $user_id)
->get();
but I get an error because I think invoices are a collection ... I tried to insert a foreach...but it doesn't work.
The error message:
Method Illuminate\Database\Eloquent\Collection::shifts does not exist
How can I do this?
Thanks
$invoices is an instance of Illuminate\Database\Eloquent\Collection and therefore relationship shifts() cannot be used..
Maybe you need the correct Eloquent builder to filter invoices using whereHas("relationship", fn)
$filteredInvoices = Invoice::with('shifts.invoices')
->whereHas("shifts", function($query) use ($user_id) {
$query->wherePivot('tas', $user_id)
})
->orderBy('date_ins', 'DESC')
->get();

laravel one-to-many relationship is null

I have 3 models: User, Company and Branch.
In a blade file i want to be able to display the branch the company of the user belongs to.
In my opinion i should have the following relationships:
User -> Company : user belongsto a company and a company has many users , so this in a one-to-many relationship.
Company -> Branch: A company belongsto a branch and a branch can have many companies. So once again a one-to-many relationship.
I have foreign keys in the users table: company_id which references id on the company table.
Another FK in the company table: branch_id which references id on the branch table.
In my blade file want to display the branch name like this: {{ $user->company->branch->name }} where only name is a property. Company and branch are relationships.
My query looks like this:
$users = User::with(['company','company.branche' => function($q){
$q->select('name');
}])->inRandomOrder()->paginate(24);
<?php
namespace App;
use App\Events\GeneralEvent;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Nicolaslopezj\Searchable\SearchableTrait;
use Spatie\Permission\Traits\HasRoles;
class User extends Authenticatable implements MustVerifyEmail
{
use Notifiable, SoftDeletes, HasRoles, SearchableTrait;
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'gender', 'first_name','last_name', 'email', 'password',
];
/**
* The attributes that should be hidden for arrays.
*
* #var array
*/
protected $hidden = [
'password', 'remember_token',
];
/**
* The attributes that should be cast to native types.
*
* #var array
*/
...
public function company()
{
return $this->belongsTo(Company::class,'company_id');
}
}
<?php
namespace App;
use App\Events\GeneralEvent;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use Nicolaslopezj\Searchable\SearchableTrait;
class Company extends Model
{
use SoftDeletes, SearchableTrait;
...
public function branche()
{
return $this->belongsTo(Branche::class);
}
}
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
use Nicolaslopezj\Searchable\SearchableTrait;
class Branche extends Model
{
protected $fillable = [
'name'
];
protected $searchable = [
'columns' => [
'name' => 10,
],
];
public function companies()
{
return $this->hasMany(Company::class);
}
}
However when i dump the $user->company i get null. So adding the branch after that is pointless for now. When i dump the user the relation shows up but is null. I have no idea where i am going wrong. Can someone please help?
You have to include the id of the branch so that eloquent can link the branch and company
you can do like that
$users = User::with(['company','company.branche' => function($q){
$q->select('id','name');
}])->inRandomOrder()->paginate(24);
OR Like that
$users = User::with('company.branche:id,name')->inRandomOrder()->paginate(24);
So the problem was i had one of my foreign keys pointing to the wrong table. Doh.

insert data to table pivot use form and show it index.blade.php in laravel 5.7

I have form create team.blade.php below this
Form Team index.blade.php
display the name of the one-team user with that user, and display the project that is being done by the user, and display the user as what (role).
the relationship of one user has many teams. and one team has many users. therefore, I choose many to many relations. but when I create team, I want to insert user_id and team_id in the pivot user_teams table as the relation table between user and team.
but when I tried to create team failed, he did not save data to the user_teams table.
and in the team index, he does not display the name of a team user with that user, and displays the project that is being done by the user, and displays the user as what.
my user models
<?php
namespace App;
use Illuminate\Notifications\Notifiable;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Foundation\Auth\User as Authenticatable;
use App\Presence;
use App\Models\Project;
use App\Productivity;
use App\Sick_leave;
use App\Annual_leave;
use App\Models\Team;
class User extends Authenticatable
{
use Notifiable;
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'name', 'email', 'password', 'role_id',
];
/**
* The attributes that should be hidden for arrays.
*
* #var array
*/
protected $hidden = [
'password', 'remember_token',
];
public function role()
{
return $this->belongsTo(Role::class, 'role_id');
}
public function teams()
{
return $this->belongsToMany(Team::class, 'user_teams');
}
public function projects()
{
return $this->belongsToMany(Project::Class, 'user_projects');
}
}
Team Models
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use App\User;
use App\Role;
use Auth;
class Team extends Model
{
use SoftDeletes;
protected $table = 'teams';
protected $fillable = [
'id',
'project_id',
];
public function users()
{
return $this->belongsToMany(User::class, 'user_teams');
}
public function project()
{
return $this->belongsTo(Project::class);
}
public function role()
{
return $this->belongsTo(Role::class);
}
}
Project Model
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
class Project extends Model
{
use SoftDeletes;
protected $table = 'projects';
protected $fillable = [
'project_id',
'project_name',
'start_date',
'end_date',
'project_category',
];
public function users()
{
return $this->belongsToMany(User::class, 'user_projects');
}
public function team()
{
return $this->hasOne(Team::class);
}
}
UserTeam model
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
class UserTeam extends Model
{
use SoftDeletes;
protected $table = "user_teams";
public function team()
{
return $this->belongsTo(Team::class);
}
public function user()
{
return $this->belongsTo(User::class);
}
}
Team Controller
public function index()
{
$users = auth()->user()->name;
$users = User::all();
return view ('teams.index', compact ('teams', 'users', 'projects'));
}
public function create()
{
$users = User::all();
$projects = Project::pluck('project_name', 'id');
return view ('teams.form', compact('projects', 'users'));
}
public function store(Request $request)
{
$team = Team::create($request->all());
$userIds = User::find(2);
$team->users()->attach($userIds);
return redirect()->route('team.create');
}
In user_teams has fields user_id and team_id. how do i overcome this??
You have to create the team and then attach the users that belong to it.
Example from the docs:
Attaching
Eloquent also provides a few additional helper methods to make working
with related models more convenient. For example, let's imagine a user
can have many roles and a role can have many users. To attach a role
to a user by inserting a record in the intermediate table that joins
the models, use the attach method:
$user = App\User::find(1);
$user->roles()->attach($roleId);
In your case:
Team Controller
public function store(Request $request)
{
$team = Team::create($request->except('user_id'));
$team->users()->attach($request->get('user_id', []));
return redirect()->route('team.create');
}

ORM not working in Default UserController & User Model in laravel

I want to get User wise Role. here is I'm facing error ....
UserController.php ( user controller file )
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Http\Requests\UserRequest;
use App\Employee;
use App\Role;
use App\User;
use App\Site;
use App\Client;
use App\ProjectType;
use App\UserPermission;
use Auth;
use DB;
use App\Project;
class UsersController extends BaseController {
public function __construct() {
$this->isSetClientAndProjectType();
$data = User::with('Role')->first();
echo "<pre>";print_r(json_decode($data)); die;
}
}
User.php ( user model file )
namespace App;
use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Database\Eloquent\SoftDeletes;
class User extends Authenticatable {
use SoftDeletes;
use Notifiable;
protected $fillable = [
'name', 'role_id', 'password', 'siteid', 'email', 'status', 'allowed_to_bypass_pm', 'allowed_to_bypass_admin'
];
protected $hidden = [
'password', 'remember_token',
];
// Get users roles
public function Role() {
return $this->hasMany('App\Role', 'role_id', 'id');
}
}
Error is
How can i solve this error?
Help me guys.
Thank You.
If a user has many "roles" it should be public function roles().
You have defined:
A single user has a role_id
Therefore you need:
If a user has a single role it would be:
public function role() {
return $this->belongsTo('App\Role');
}
The reverse on the Role model would be:
public function users() {
return $this->belongsToMany('App\User');
}
Since many users can have the same role.
Hope this helps.
You need to add belongsTo relationship
namespace App;
use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Database\Eloquent\SoftDeletes;
class User extends Authenticatable {
use SoftDeletes, Notifiable;
protected $fillable = [
'name', 'role_id', 'password', 'siteid', 'email', 'status', 'allowed_to_bypass_pm', 'allowed_to_bypass_admin'
];
protected $hidden = [
'password', 'remember_token',
];
// Get user's role
public function role() {
return $this->belongsTo('App\Role');
}
}
Now fetch data
$user = User::with('role')->find(1);
$role = $user->role;
You need to make sure your table structure and foreign key references are compatible with the model relationship methods used.
For example, you have used "HasMany" relationship on User model. For that, you will have to make sure that each record/row in users table(User model) "has many" associated records/rows in roles table(Role model).
Here HasMany method assumes a foreign key "role_id" on roles table(Role Model). On not finding of which, it throws error.
You first need to take in consideration the table structure of roles and users table(User and Role model) as per your requirement, and than add model relationship methods accordingly.
It can be a bit tricky if you are using the methods for the first time, you can refer the laravel documentation for the same:
eloquent-relationships

Laravel 5.2 eloquent returns soft deleted records

I am using Laravel 5.2.
I have a model as below:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\SoftDeletes;
class ZoomMeeting extends BaseModel {
public $timestamps=true;
protected $table = 'zoom_meetings';
use SoftDeletes;
protected $dates = ['deleted_at'];
protected $fillable = ['user_id', 'uuid', 'meeting_id', 'host_id', 'topic', 'status', 'type', 'start_url', 'join_url', 'created_at'];
public function users() {
return $this->belongsTo('App\Models\User');
}
}
And the base model is as below:
<?php namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Auth;
use Carbon\Carbon;
class BaseModel extends Model {
public $timestamps = false;
protected static function boot()
{
//parent::boot();
static::creating(function($model) {
if(empty($model->created_at))
{
$model->created_at = date('Y-m-d H:i:s');
}
return true;
});
static::updating(function($model) {
$model->updated_at = date('Y-m-d H:i:s');
return true;
});
}
}
I am using softdeletetrait in ZoomMeeting model, and soft deleting is working fine.
However, if I fetch records from the same model using eloquent, it returns the soft deleted records too. I am using code below to get the records:
$record = ZoomMeeting::where("user_id", $user_id)->where("meeting_id", $meeting_id)->orderBy("id", "DESC")->first();
The eloquent is building the query as:
select * from `zoom_meetings` where `user_id` = 3 and `meeting_id` = 707070707 order by `id` desc limit 1
See, there is no deleted at is null set in where statement. It is not preventing the deleted records.
I am not sure where am I making mistake?
It looks like you are overriding the boot method, but you aren't ever actually calling the parent boot method (it's commented out), so the trait is never getting initialized correctly. I believe that also means the data you have been deleting is actually being deleted from the database.
Is there a reason you need to override the boot method? What you are adding is already done handled by the framework, so it doesn't appear to be necessary.

Resources