Have 2 one to one relationships between the same models - laravel

I have a User model & a Sale model. A User can be either a Merchant or Customer.
When a sale is made the sale belongs to a merchant but also to a customer.
I figured I can give the sale a merchant_id & a sale_id and create 2 different relationships in the models.
Just didn't feel right to me. So my question is there a better way to go about this? I'm in a early stage of development. I wouldn't mind changing the database around a bit.
I'm using laravel 5.3

It's not one-to-one, it's many-to-many relationship and sales table should be a pivot table. Relation usually looks like this:
class User extends Authenticatable
{
public function customers()
{
return $this->belongsToMany('App\User', 'sales', 'customer_id', 'merchant_id');
}
Where customer_id and merchant_id are foreign keys pointed to id in users table.
If you do a lot of stuff with sales table, just keep using Sale model for this pivot table.

Related

Creating a "through" relationship when both foreign keys are on the same table

I have a products table. A product belongs to a category and a country.
I would like to find out what countries a category has by leaning on this relationship.
I've considered hasManyThrough and https://github.com/staudenmeir/belongs-to-through but this is sort of a belongsTo relationship, with both foreign keys on an intermediate table, I suspect the products table is sort of acting like a pivot.
I would like to know how I can set up a relationship that relates categories to countries through the products table - is this possible?
Tables:
Categories
id
title
Countries
id
title
Products
id
title
category_id
country_id
Relationships:
A product belongs to a country / A country has many products.
A product belongs to a category / A category has many products.
You've pretty much described a Many to Many relationship with Product being the pivot table.
# Category model
public function countries()
{
return $this->belongsToMany(Country::class, 'products')
->withPivot(['id', 'title']); // optional
}
# Country model
public function categories()
{
return $this->belongsToMany(Category::class, 'products')
->withPivot(['id', 'title']); // optional
}

Laravel: how to sort a collection with hasMany field

I have five tables:
details having fields id, name and has hasMany relation with contributions.
purpose having fields id, name and has hasMany relation with contributions.
period having fields id, name and has hasMany relation with contributions.
user having fields id, name and has hasMany relation with contributions.
and
contributions having id, amount and "belongsTo" relation with user_id, detail_id, purpose_id, period_id
Now, I want to get all contributions of a specific user (filtered by user_id) and then sort the result by period.name, detail.name and purpose.name.
Any suggestions?
The question has been identified as possible duplicate of Laravel orderBy on a relationship . However there is a basic difference.
there, there is relation between user and comment & user and post. however in my case, there isn't any relation between user and details/purposes/periods tables.
<?php
class User
{
public function comments()
{
return $this->hasMany('Comment');
}
}
is possible in that case, but by same analogy, in my case, class User doesn't have any details() function to get hasMany relations. My user has relation with only contributions table and contributions table has relations with details purpose etc tables.
hope I am able to clarify the difference.

Laravel pivot with multiple columns

Hi I have a problem with Laravel`s pivot table.
I have the following tables: students, courses and lessons.
The table lessons is connected with courses through a foreign key courses_id, and the tables students and courses are connected through a pivot courses_students.
So I can access the information through students like this:
//Students model
public function courses()
{
return $this->belongsToMany(Courses::class,'courses_students','student_id', 'course_id')
->with('lessons');
}
//Courses model
public function lessons()
{
return $this->hasMany(Lesson::class);
}
This works completely fine for this kind of relationship, but I want to add a third column in the pivot with name lesson_id for the lessons table.
I am doing this because, sometimes I need to get a specific set of lessons from each course for each user.
I succeeded in doing so, by using a model courseStudent for the pivot table.
Using the model for pivot my calls became like this.
Student->with('courseStudent.courses')
->with('courseStudent.lessons')
->get();
This partially does what I need it to do, but I want to maintain the relation ship between courses and students.
Is there a way to achieve that?
Example from docs(go through Many To Many):
return $this->belongsToMany('App\Role')->withPivot('column1', 'column2');
Pivot table is meant to use belongsToMany relationship on both entities.
So your students and courses should have it defined if you want pivot table between that is using eloquent default capacity.
As a side note pay attention on naming convention because that way you will reduce issues on minimum: pivot table should be tableanamesingular_tablebnamesingular where order is set by alphabetical order of tables' names (i.e. post_user Yes, user_post No).
Id fields in pivot table should be tablenamesingular_id.
You can set names however you want but this way you will have less unepected behavior in future using eloquent. All of this you have in documentation page and I recommend you go through it thoroughly.
Other way is to use dynamic properties for getting certain values. Example from docs:
$user = App\User::find(1);
foreach ($user->roles as $role) {
echo $role->pivot->created_at;
}
If you would like to manually change values in pivot table, you should create separate model for it that would be connected with that entity/table (pay attention that pivot model extends Pivot as in example from docs rather than Model):
<?php
namespace App;
use Illuminate\Database\Eloquent\Relations\Pivot;
class PostUser extends Pivot
{
// other definitions related
}
You can use join for third relation:
public function courses(){
return $this->belongsToMany(Courses::class,'courses_students','student_id', 'course_id')
->withPivot('lesson_id')
->join('lessons','lesson_id','=','lessons.id')
->select('lessons.id','lessons.title', ...);
}
If you are going to use the same pivot table for courses and lessons, you can to do something like this:
//Students model
public function courses()
{
return $this->belongsToMany(Courses::class,'courses_students','student_id', 'course_id')
->whereNotNull('course_id');
}
public function lessons()
{
return $this->belongsToMany(Lessons::class,'courses_students','student_id', 'lesson_id')
->whereNotNull('lesson_id');
}
Then just use it:
$courses = $student->courses;
$lessons = $student->lessons;

Laravel has-many-through with multiple intermediate tables

I am trying to develop multiple-shop eCommerce platform.
So the following tables created:
shops: id, name, ...
products: id, shop_id, ...
orders: id, ...
order_details: id, order_id, product_id, ...
And this is the summery of my models' relationships:
Shop->products: Shop hasMany Product
Product->shop: Product belongsTo Shop
Order->details: Order hasMany OrderDetail
OrderDetail->order: OrderDetail belongsTo Order
OrderDetail->product: OrderDetail belongsTo Product
Product->orders: Product hasMany OrderDetail
Now, 1: Is it possible to define Shop->orders relationship?(It seams has-many-through not works in this case due to multiple intermediate tables)
2: If it is possible, could the shop->orders->details contains only the records related to shop products?
It should be note that each Order may contain products from multiple shops but the shop->orders->details relation should contains only the shop products.
There is no native relationship for this case.
I created a HasManyThrough relationship with support for BelongsToMany: Repository on GitHub
After the installation, you can use it like this:
class Shop extends Model {
use \Staudenmeir\EloquentHasManyDeep\HasRelationships;
public function orders() {
return $this->hasManyDeep(Order::class, [Product::class, 'order_details']);
}
}

Laravel and pivot table to relate different model

I'm wondering how, but it's bit confusing.
I have fine belongs to many relation between users and groups tables as well as appropriate models for all of that.
But i also have table students, where not all users are student so i students table i maintain user_id field.
My question would be: Can i use pivot table "group_user" for relations between student and group model, in students table i have "user_id" field? and how?
I tried something like
public function students()
{
return $this->belongsToMany('Student','group_user','group_id','user_id');
{
but i don't see the way how to tell eloquent not to take students.id but to take students.user_id???
Assuming these relations:
Subject belongsTo Group
Group belongsToMany User
User hasOne Student
you can easily do this:
$subject = Subject::find($someId);
// of course for multiple subject use eager loading:
// $subjects = Subject::with('group.users.student')->get();
$users = $subject->group->users; // related users
foreach ($users as $user)
{
$user->student; // null|student model
}

Resources