Building ternary relationship using Laravel Eloquent Relationships - php

Have three entities:
Project
Employee
Employment
Problem description: Employee can work on many projects and for each he has one employment. I want to have access to all projects and your referred employments of a certain employee.
I'm not sure but the relationship must look like a ternary:
The physical table is not defined yet. So, be free to design (most basic) them.
And my question:
How i can build using Laravel Eloquent Relationships?

Basically your four tables will be something like:
employee
id
...your fields
project
id
...your fields
employments
id
...your fields
employee_project
employee_id
project_id
employment_id
You can split the problem in 2 by 2 relations:
class Employee extends Model{
public function projects(){
return $this->belongsToMany("Project")
}
// Second relation is Optional in this case
public function employments(){
return $this->belongsToMany("Employment", 'employee_project')
}
}
A Project model
class Project extends Model{
public function employees(){
return $this->belongsToMany("Employee")
}
// Second relation is Optional in this case
public function employments(){
return $this->belongsToMany("Employment",'employee_project')
}
}
A Employment model
class Employment extends Model{
public function employees(){
return $this->belongsToMany("Employee")
}
public function projects(){
return $this->belongsToMany("Project")
}
}
At this point in your controller you can manage your relation, for example if you want to add to $employee, the project with id 1 with the employment with id 2 you can simply
$employee->projects()->attach([1 => ['employment_id' => '2']]);
I hope this answer to your question.
If you need timestamps in your pivot table, add ->withTimesetamps() to your relationships.

Employee has Employment
Employment has Project

Related

Laravel: Get single model using pivot table with where clause

I've got 3 tables:
Car: belongsToMany Owner
Owner: belongsToMany Car
CarOwner: pivot table for Car and Owner with an additional column 'active' that indicates who is the current Owner of a Car
So a Car might have multiple or no Owners and vica versa BUT a Car has only 1 current ('active') Owner.
class Car extends Model
{
use HasFactory;
public function owners()
{
return $this->belongsToMany(Owner::class, 'car_owners');
}
public function currentOwner()
{
return $this->owners()->where('active', true)->first();
}
}
My problem is if a Car has no active Owner, Laravel throws the following exception when I want to use $car->currentOwner in a Blade template:
App\Models\Car::currentOwner must return a relationship instance, but "null" was returned. Was the "return" keyword used?
How can I handle if a Car doesn't have any active Owners?
You can create a custom attribute instead of a relation function:
public function getCurrentOwnerAttribute()
{
return $this->owners()->where('active', true)->first();
}

How to join two tables with a pivot table using Laravel?

I have these three tables:
tbl_lista_contactabilidad tbl_equipo_postventaatc users
------------------------- ----------------------- -----
id id id
usuarios_id asesor_id name
tbl_lista_contactabilidad.usuarios_id should be related with tbl_equipo_postventaatc.asesor_id. asesor_id should be the "pivot" between tbl_lista_contactabilidad.usuarios_id and users.id to make the relation.
I want to make this relation so I tried to do this relation in this way (I will put only the relation of the model)
Tbl_Lista_Contactabilidad (Model 1)
public function postventaatc(){
return $this->belongsTo('App\Models\Tbl_EquipoPostventaatc','usuarios_id');
}
Tbl_Equipo_Postventaatc (Model 2) -> This should be the pivot model
public function contactabilidad(){
return $this->hasMany('App\Models\Tbl_Lista_Contactabilidad','usuarios_id');
}
public function user(){
return $this->belongsTo('App\Models\User','asesor_id');
}
User (Model 3)
public function postventaatc(){
return $this->hasMany('App\Models\Tbl_Lista_Postventaatc','asesor_id');
}
EXAMPLE:
As you see in the image... if I relate usuarios_id with users directly I will get another name and I don't want that... I want the relation just like in the image
A pivot table is a structure used to join two separate models together with a single relationship. This is called a many-to-many relationship in Eloquent.
From what you've described, this is not the case here. Rather, it looks like a has-many-through relationship.
If I'm understanding correctly, your relationships should look like this:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Tbl_Lista_Contactabilidad extends Model {
protected $table = 'tbl_lista_contactabilidad';
public function postventaatc() {
return $this->belongsTo(Tbl_EquipoPostventaatc::class, 'usuarios_id');
}
}
class Tbl_EquipoPostventaatc extends Model {
protected $table = 'tbl_equipo_postventaatc';
public function contactabilidad() {
return $this->hasMany(Tbl_Lista_Contactabilidad::class, 'usuarios_id');
}
}
class User extends Model {
public function postventaatc() {
return $this->belongsTo(Tbl_EquipoPostventaatc::class, 'asesor_id');
}
public function contactabilidad() {
return $this->hasManyThrough(Tbl_Lista_Contactabilidad::class, Tbl_EquipoPostventaatc::class, 'asesor_id', 'usuarios_id');
}
}
Obviously this is easier for a native English speaker, but I cannot stress how much easier this would be if you were following the Laravel rules around naming your models, tables, and columns. Why does usuarios_id column relate to a table called tbl_equipo_postventaatc? Why use asesor_id instead of user_id? 🤷🏽‍♂️ Those names have nothing to do with each other, and make it hard to figure out what is going on.

Make 2 Different Tables Share a Common Table in Laravel

I want to have two tables one for Employees and one for Companies, both Employees & Companies should be registered within the site, thus they should have records in the users table provided with Laravel. How should I structure the relationships between the models, should I go for polymorphic relationships or use one to one?
The answer is to add two columns to the "users" table: userable_id and userable_type. userable_id will be used to store the id of the row for the entity (Employee or Company), and the userable_type will hold the class path for the Eloquent model.
in create_users_table migration file add these two lines:
// ...
$table->integer('userable_id')->unsigned();
$table->string('userable_type');
// ...
in User.php model:
class User extends Model {
// Add this declaration.
public function userable()
{
return $this->morphTo();
}
}
in your Company.php model:
class Company extends Model
{
// Add this method.
public function user()
{
return $this->morphMany(User::class, 'userable');
}
}
in the Employee.php model do the same as above:
class Employee extends Model
{
// Add this method.
public function user()
{
return $this->morphMany(User::class, 'userable');
}
}
Now you should be able to access the user by running:
App\Company::all()->get(1)->user;
// or
App\Employee::all()->get(1)->user;
And access the entity with this one-liner:
App\User::all()->get(1)->userable;

Make a simple join to a reference table with Laravel 5.1 Eloquent

I have a simple join to make, but I can't do it.
I have a tournament that has a categoryId field in the table.
The table TournamentLevel is a 10 entry table.
So I would like to be able to retrieve level->name with Eloquent.
I tried to do the following:
In Tournament, I tried to define a hasOne relationship:
class Tournament extends Model
{
....
public function level()
{
return $this->hasOne('App\TournamentLevel');
}
But then, Eloquant is looking for tourmanent_id inside of TournamentLevel Table
So I tried the opposite,
In Model TournamentLevel:
class TournamentLevel extends Model
{
...
public function tournament()
{
return $this->belongsTo('App\Tournament');
}
}
And tried to reach :
tournament->level->name
but without success
It seems pretty elementary, but I can't do it... Any idea???

laravel4 one to one relationship can not load the relationship

I have two tables like this:
users
id email
1 abc#ibm.com
2 abc#hp.com
3 abc#google.com
grp_members
grp_id user_id
1 2
2 2
13 1
13 3
2.My model
There, one group member must be a user, so its a one to one relationship just for GroupMember.
Users model about table users
class Users extends Eloquent {
protected $table = "users";
}
GroupMember model about table group_members
class GroupMember extends BaseModel{
protected $table = "grp_members";
public function user(){
return $this -> hasOne('Users', 'id');
}
}
3.In my service GroupApi.php, if I have a query like this
class GroupApi {
public function queryGroupMembers(){
$result = GroupMember::all();
var_dump(get_class(GroupMember::all())); //CODE ONE
foreach($result as $ret){
var_dump(get_class($ret)); //CODE TWO
var_dump(get_class($ret -> user)); //CODE THREE
}
}
}
As you see, when I invoke var_dump(get_class(GroupMember::all())) at CODE ONE,
I got this
.string(39) "Illuminate\Database\Eloquent\Collection"
Yes, that's what I want.
Now, at CODE TWO, it prints
string(11) "GroupMember"
Yes, also correct object, but when the code goes to CODE THREE, it give me a surprise,
the outputs like this:
string(8) "GroupApi"
Why its an instance of GroupApi, but not the instance of Users or GroupMember
And in that case , how can I invoke $ret -> user?
Any idea is welcome, thanks very much.
There are some things I'm not sure I understand in your implementation but something that could be causing you troubles is not using the conventions Laravel asks for, that being using User as the model name and users (model + s) as the table name.
Also, i would guess $g1 is not a GroupMember object as you suggest, could you getClass() it and comfirm?
Ok, I guess you have 3 tables:
users; grp_members; groups
and a many-to-many relationship between users and groups using the table grp_members as pivot table.
In this case, try this:
Class User:
class User extends Eloquent {
public function groups()
{
return $this->belongsToMany('Group', 'grp_members');
}
}
Class Group:
class Group extends Eloquent {
public function users()
{
return $this->belongsToMany('User','grp_members');
}
}
And also change the field name in the table 'grp_members' from grp_id to group_id, to follow eloquent conventions.

Categories