Laravel Relationship between Three Models - mysql

sold_items:
id order_id customer_id name
-- -------- ----------- ----
1 5 14 An object
orders:
id po_num
-- ------
... ...
5 123
customers:
id name
-- ----
... ...
14 John Doe
A SoldItem has an order_id and a customer_id.
I'm trying to define a hasOne relationship between an Order and its Customer through the SoldItem without having to insert a customer_id column in the Order model's table.
hasOneThrough seemed to be the solution but I couldn't figure out where to go from there, or is that even the answer?
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Order extends Model
{
public $timestamps = false;
protected $guarded = ['id'];
public function sold_items()
{
return $this->hasMany('App\SoldItem');
}
public function customer()
{
// return $this->hasOneThrough();
}
}

for Customer model
{
public function sold_items()
{
return $this->hasMany('App\SoldItem');
}
}
for Order model
{
public function sold_items()
{
return $this->hasOne('App\SoldItem');
}
}
for SoldItem model
{
public function customer()
{
return $this->belongsto('App\Cutomer');
}
public function order()
{
return $this->belongsto('App\Order');
}
}
I prefer working on their relationship first then and use with() function to get their values.
use App\Customer;
$customer = Customer::with('sold_items','sold_items.order')->get();

I ended up making the Customer an attribute of the Order through its sold_items with:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Order extends Model
{
public $timestamps = false;
protected $guarded = ['id'];
public function sold_items()
{
return $this->hasMany('App\SoldItem');
}
public function getCustomerAttribute()
{
return $this->sold_items->first()->customer;
}
}

Related

How to get data from table reference in Laravel

I have table relation like this:
Is it possible to get the data of the project from the cash mutation table?
In example in cash mutation table with id '4' I wanna call agency name from projects table.
I've done it with with (eager loading in Laravel) but it returns null like:
$cash_mutations = CashMutation::where('id', 4)->with('project')->get();
This is my CashMutation Model:
class CashMutation extends Model
{
use HasFactory;
protected $guarded = ['id'];
public function category(){
return $this->belongsTo(Category::class);
}
public function balanceType(){
return $this->belongsTo(BalanceType::class);
}
public function project(){
return $this->belongsTo(Project::class, 'cash_mutation_id', 'id');
}
public function deposit(){
return $this->hasMany(Deposit::class);
}
}
and this is my Project Model:
class Project extends Model
{
use HasFactory;
protected $guarded = ['id'];
public function cashMutation(){
return $this->belongsTo(CashMutation::class);
}
public function projectFunding(){
return $this->hasMany(ProjectFunding::class);
}
public function SharingProfit(){
return $this->hasMany(SharingProfit::class);
}
}
Is it possible to do that in Laravel? If it possible anyone want to tell me about it? Thanks
Yes. It is definitely possible.
You don’t get an error message so the basic configuration should be fine.
I suspect that the data in the database is not correct. What’s the project_id for the CashMutation with the id 4? Is it maybe null?

Laravel Sql query groupBy and Order

I need some help to make a query.
Database tabless
Example:
The user inserts a actor name(name and surname) and i need to loop over all the movies and then retrieve which category has more occurrences.
I need some help to make the query(this one is only a sketch):
$src=array("Leonardo","DiCaprio");
$film2=film::with('category')->with('actor')->wherehas('actor', function($q) use($src){
$q->where('first_name', $src[0])->where('last_name', $src[1]);
})->wherehas('category', function($qr){
$qr->groupBy('name')->orderBy('name', 'DESC');
})->FIRST();
model Film:
class film extends Model{
protected $table = "film";
protected $primaryKey = 'film_id';
public $timestamps = false;
use HasFactory;
protected $sql=['film_id', 'title', 'length'];
public function category(){
return $this->belongsToMany(category::class,'film_category', 'film_id', 'category_id');
}
public function actor(){
return $this->belongsToMany(actor::class,'film_actor', 'film_id', 'actor_id');
}
}
model Actor:
class actor extends Model{
protected $primaryKey = 'actor_id';
public $timestamps = false;
use HasFactory;
protected $sql=['actor_id', 'first_name', 'last_name'];
}
model Category:
class category extends Model{
protected $table = "category";
protected $primaryKey = 'category_id';
public $timestamps = false;
use HasFactory;
protected $sql=['category_id','name'];
public function film(){
return $this->belongsToMany(film::class,'film_category', 'category_id', 'film_id');
}
}
Here is the solution:
In Actor.php add Join
public function filmActor(){
return $this->hasMany(FilmActor::class, 'actor_id','actor_id');
}
Find the actor with filmActor join table
$src=array("Leonardo","DiCaprio");
$actor=Actor::whereHas('filmActor')->where(['first_name' => $src[0],'last_name'=> $src[1]])->first();
Put film_id in the array
foreach($actor->filmActor as $film){
$filmIds[]=$film->film_id;
}
Get FilmCategory who have filmIds
$filmCategory=FilmCategory::whereIn('film_id',$filmIds)->get();
Put category_id in the array
foreach($filmCategory as $category){
$categoryIds[]=$category->category_id;
}
Count how much is duplicate category_id
$count =array_count_values($categoryIds);
Get the higher counted $max = max($count);
Get the key of max which is category_id $key = array_search($max, $count);
Here is the category who has more occurrences.
$category=Category::where('category_id',$key)->first();

Eloquent Multiple Join With Where Clause

I am trying to join the user table with the attendance_user and attendance_supervisor table where the location id is equal to a specific value however currently the results that i am being returned doesnt seem to take into consideration the where clause.
Can anyone please tell me what i am doing wrongly?
$new_attendance_user = AttendanceUser::join('users','users.id','=','attendance_users,user_id')
->join('attendance_supervisors','users.id','=','attendance_supervisors.user_id')
->groupby('user_id')
->where('function($query)uses($location){
$query->where('attendance_supervisors.atttendance_location','=','$location')
->orWhere('attendance_users.atttendance_location','=','$location');
}
->get()
User Table
class User extends Eloquent{
public function attendance_users()
{
return $this->hasMany('attendance_user');
}
public function attendance_supervisors()
{
return $this->hasMany('attendance_supervisor');
}
}
Attendance_user
class AttendanceUser extends Eloquent{
public function userBelongsToUser()
{
return $this->belongsTo('User');
}
}
Attendance_supervisor
class AttendanceSupervisor extends Eloquent{
public function supBelongsToUser()
{
return $this->belongsTo('User');
}
}

Laravel Many models as Publisher Polymorphic Relationship with pivot?

Hi I am having problems with relation and database design.
There are three tables called 'articles' , 'users' , and 'companies' with one attribute each called id:
"articles" -id
"users" -id
"companies" -id
The article table contain many publishers that are user model or company model.
My pivot table must be something similar to 'authors' -id, -model_id, -model_name, -article_id
Is there any way to get article's publisher ids and data from models in one collection with a single query? Maybe I misunderstood the problem and there is a simpler solution for that case.
thx in advance
Assuming Article only have one company or one user , The right way to do that is to do a one to many (polymorphic) relationship creating the table with these columns:-
{ article_id , articleable_id , articleable_type }
and then define it in your model
use Illuminate\Database\Eloquent\Model;
class Article extends Model
{
/**
* Get all of the owning articleable models.
*/
public function articleable()
{
return $this->morphTo();
}
}
and the Users table:-
class Userextends Model
{
/**
* Get all of the user's articles.
*/
public function articles()
{
return $this->morphMany('App\Article', 'articleable');
}
}
and same in the Company model:-
class Company extends Model
{
/**
* Get all of the companies articles.
*/
public function articles()
{
return $this->morphMany('App\Article', 'articleable');
}
}
and then you can retrieve the relationship using:-
$user = App\User::find(1);
foreach ($user->articles as $article) {
// do this
}
as mentioned here
but if the article can have more than user or company then you have to do many to many polymorphic as mentioned here
#Mohamed Gabr
the problem is that i need this in many to many way.
and i don't have problem to receive article from User model or Company.
I need receive authors from Article.
i assume there will be something like that.
class Article extends Model
{
public function authors()
{
return $this->hasMany('App\Article_Authors','article_id');
}
}
class Article_Authors extends Model
{
public function authorable()
{
return $this->morphTo();
}
public function article(){
return $this->belongsTo('App\Article');
}
}
class User extends Model
{
public function authors()
{
return $this->morphMany('App\Article', 'authorable');
}
}
class Company extends Model
{
public function authors()
{
return $this->morphMany('App\Article', 'authorable');
}
}
i can make it work but i don't think its good practice
I implement this models
class Article extends Model
{
public function authors()
{
return $this->hasMany('App\Article_Authors','article_id');
}
}
class Article_Authors extends Model
{
public function authorable()
{
return $this->morphTo();
}
public function article(){
return $this->belongsTo('App\Article');
}
}
class User extends Model
{
public function authors()
{
return $this->morphMany('App\Article', 'authorable');
}
}
class Company extends Model
{
public function authors()
{
return $this->morphMany('App\Article', 'authorable');
}
}
and after call $article->authors i get
0
id 1
record_id 2
authorable_id 1
authorable_type "App\\User"
created_at "2019-03-22 15:56:38"
updated_at "2019-03-22 15:56:38"
1
id 2
record_id 2
authorable_id 1
authorable_type "App\\Company"
created_at "2019-03-22 15:56:59"
updated_at "2019-03-22 15:56:59"
how to call this models now :(
#MohamedGabr
Edit :
after making research i didn't find any option to get result in one query there is only option to make a loop and checking instants of model.
its generate a loot loops for collection i need cache result and please settle for this temporarily.
thx For help

Pivot table not working as expected

I am trying to use many-to-many relationships between my posts and categories models. So far I created posts , categories and post_categories tables.
In my models, I have my relationships
class Post extends Eloquent {
public function categories()
{
return $this->belongsToMany('Category', 'post_categories','category_id');
}
}
class Category extends Eloquent {
public function posts()
{
return $this->belongsToMany('Post','post_categories');
}
}
and in my controllers when I try to create a Post instance by :
$post = new Post;
$post->title = e(Input::get('title'));
$post->slug = e(Str::slug(Input::get('title')));
$post->content = e(Input::get('content'));
// Was the blog post created?
if($post->save())
{
$id = (int) Input::get('category_id');
$category = Category::find($id);
$post->categories()->attach($category);
// Redirect to the new blog post page
return Redirect::to("admin/blogs/$post->id/edit")->with('success', Lang::get('admin/blogs/message.create.success'));
}
After submitting form , I can see blog post is created normally. When I check the db , Category_id is inserted inside post_categories table but post_id is always 0.
Can anyone help me to fix this?
$post->categories()->attach($category->id);
I was using relationships in a wrong way. The table had to know the second table column name.
class Post extends Eloquent {
public function categories()
{
return $this->belongsToMany('Category', 'post_categories','category_id','post_id');
}
}
class Category extends Eloquent {
public function posts()
{
return $this->belongsToMany('Post','post_categories',,'post_id','category_id');
}
}
The best usage will be changing the table name and make it category_post table. This way all I have to do is
class Post extends Eloquent {
public function categories()
{
return $this->belongsToMany('Category');
}
}
class Category extends Eloquent {
public function posts()
{
return $this->belongsToMany('Post');
}
}