Laravel Eloquent Relation Model - laravel

I have 3 table on my database :
table 1 = user (hasMany order)
table 2 = order (hasMany order_detail, belongsTo user)
table 3 = order_detail (belongsTo order)
On my order_detail model i add this function :
public function order() {
return $this->belongsTo('App\Order');
}
so i can call the order data without define it from controller, i just define order_detail on my controller
$order_detail->order->invoice_number
but how to call the user data from the order detail?
I try use this
$order_detail->order->user
but it didn't work for me..
Is there any idea to call the grand parent relation?

In order model add function for order_detail:
public function order_details() {
return $this->hasMany('order_detail');
}
and for user:
public function user() {
return $this->belongsTo('user');
}
In user model add:
public function orders() {
return $this->hasMany('order');
}
Then, you can call in the controller:
$details = Order::find(1)->order_details->where('order_detail_id', 5)->first();
$userName = $details->username;
// ^
// column name in order_detail table
More info in the docs.

I think this is the more complete way to define the relationships:
// User model
public function orders(){
// I'm telling that users has many order. The orders have an user_id field that match with the ID field of the user.
return $this->hasMany('App/Order', 'user_id' , 'id');
}
// Order model
public function order_details(){
// I'm telling that order has many order_details. The order_details have an order_id field that match with the ID field of the order.
return $this->hasMany('App/OrderDetail', 'order_id' , 'id');
}
public function user(){
// I'm telling that an order belongs to an user. The user has an ID field that match with the order_id field of the order.
return $this->belongTo('App/User', 'id', 'user_id');
}
// OrderDetail Model
public function order(){
// I'm telling that an order detail belongs to an order. The order has an ID field that match with the order_id field of the order detail.
return $this->belongTo('App/Order', 'id', 'order_id');
}
I have seen that you put just the model name as first parameter in your relation definition. I think you must put the relative path from the root to the Model. In my case, I have the models as childs of the App folder.

Related

get relatinal column HasManyThrough, set in response

i have craete membership that user can purchase one time of get all users with their membership and when they have purchase and when expired i'm confuse with this how to get my table structure is as:
User Model:
id
membership_id
public function membership() {
return $this->belongsTo(Membership::class);
}
Order:
id
user_id
public function item() {
return $this->hasOne(OrderItem::class, 'order_id', '_id');
}
order_item:
order_id
membership_id
created_at
expiration_date
public function membership() {
return $this->belongsTo(Membership::class, 'membership_id', '_id');
}
public function order() {
return $this->belongsTo(Order::class, 'order_id', '_id');
}
membership:
id
name
type
I want get data on time of listing like this how to load relation:
user{
name
email
membership{
name
type
order_item{
expiration_date
created_at
}
}
}
In membership model create this relation.
public function orderitems() {
return $this->hasOne(OrderItem::class, 'membership_id', 'id');
//It's upto you to confirm that whether it is a one-to-one or one-to-many relation
}
Then inside controller you can do something like
User::with('membership.orderitems')->get();
Updated
Alternatively you can create this hasManyThrough relation which will give you all order_items related users. Place this relation inside User Model.
public function items()
{
return $this->hasManyThrough( //please also check hasOneThrough according to your need
'App\OrderItem',
'App\Order',
'user_id', // Foreign key on order table...
'order_id', // Foreign key on order_item table...
'id', // Local key on users table...
'id' // Local key on order table...
);
}

How to setup relationship between 2 table which has both one-to-many and many-to-many relationship?

I have a Users table and an Events table.
It's has one-to-many relationship.
Each user can create many event.
Each event belongs to one user.
Also, it has many-to-many relationship.
Each user can join as many event as they want.
Each event can be joined by many user.
This needs pivot table.
Now, I'm stuck.
This is event model.
public function user(){
return $this->belongsTo('App\User');
}
public function users(){
return $this->belongsToMany('App\User')
->withTimestamps();
}
This is user model.
public function events(){
return $this->hasMany('App\Event');
}
public function events(){
return $this->belongsToMany('App\Event');
}
The problem is in the user model where I can't define multiple function with the same name.
So, is there a way to do this correctly?
Quick answer
Of course you can't have two functions with the same name. In your case, try to use more specific names for each function:
public function createdEvents()
{
return $this->hasMany('App\Event');
}
public function joinedEvents()
{
return $this->belongsToMany('App\Event');
}
Recommendation
You can use a single many-to-many relationship to manage both relations with Pivot information:
users table
id
username
...
events table
id
name
...
event_user table
user_id
event_id
is_creator (default FALSE, unsigned integer)
...
Then when creating an event, relate the user and event objects and set the is_creator field to TRUE.
So in your User model:
app/User.php
public function events()
{
return $this->belongsToMany('App\Event')->withPivot('is_creator');
}
Then in your controller when you want to create an event:
app/Http/Controllers/SomeCoolController.php
public function store(CreateEventRequest $request)
{
// Get your event data
$data = $request->only(['your', 'event', 'fields']);
// create your object
$newEvent = Event::create($data);
// create the relationship with the additional pivot flag.
auth()->user()->events()->attach($newEvent, ['is_creator' => true]);
// the rest of your code.
}
And when a user want to 'join' an event:
app/Http/Controllers/SomeCoolController.php
public function join(JoinEventRequest $request)
{
// Get the event
$event = Event::find($request->event_id);
// relate the ev
auth()->user()->events()->attach($newEvent, ['is_creator' => false]);
// or just this, because its already set to false by default:
// auth()->user()->events()->attach($newEvent);
// the rest of your code.
}
It seems like it's many to many relationships between User and Event so there will be pivot name like user_event
user model
public function events() {
return $this->belongsToMany('App\Event')->using('App\UserEvent');
}
Reference: https://laravel.com/docs/5.7/eloquent-relationships#many-to-many

Using HasManyThrough in Laravel

I have the following structure:
orders
id
name
products
id
name
items
id
order_id
product_id
quantity
The relationships are as follows:
Order
public function items(){
return $this->hasMany(Item::class)
}
public function products(){
return $this->hasManyThrough(Product::class, Item::class);
}
Item
public function order(){
return $this->belongsTo(Order::class);
}
public function product(){
return $this->belongsTo(Product::class);
}
Product
public function items(){
return $this->hasMany(Item::class);
}
I wish to get all products for the order doing something like this:
$order->items()->products()->get() using the hasManyThrough method, but I must be doing it wrong since it tries to look for item_id in the products table.
I realized that I do not need many through, I just need to use items table as a pivot table, defining the relationship on the Order model just like this:
public function products(){
return $this->belongsToMany(Product::class, 'items');
}

eloquent multi table query and relationships

I am new to this so bear with me.
I have 4 tables (users, scores, scorecards, courses) and I need to bring into a view info from all of these tables.
Here are the relationships:
Scores model
public function user(){
return $this->belongsTo('App\User');
}
public function scorecard(){
return $this->belongsTo('App\Scorecard');
}
public function course() {
return $this->belongsTo('App\Course');
}
Course model
public function club(){
return $this->belongsTo('App\Club');
}
public function scorecard(){
return $this->hasMany('App\Scorecard');
}
public function score() {
return $this->hasMany('App\Score');
}
Scorecard model
public function course(){
return $this->belongsTo('App\Course');
}
public function club(){
return $this->belongsTo('App\Club');
}
In my controller I get the scores id from a dropdown in the request. I need to essentially get the following info:
the scores record which is easy as i have the score id.
use the scorecard_id from the scores table to get the scorecard record from the scorecards table
grab the course info from the courses table using the course_id thats in the scorecards table.
You can eager load the relations using dot . as scorecard.course and it will load both scorecard and course.
$score = Score::with('scorecard.course')->find($id);
and then you can access corresponding attributes as:
$score->scorecard;
$score->scorecard->course;
if $id is the scores id from a dropdown,
$score=Score::with('scorecard','scorecard.course')->where(['id'=$id])->first();
then,
print_r($score);
gives the scores record.
print_r($score->scorecard);
gives the scorecard record.
print_r($score->scorecard->course);
gives the courses record.

laravel display only specific column from relation

I have read a few topics about this, but they managed to solve my problem partially ...
this is my controller
class DeskController extends BaseController{
public function getDeskUsers($deskId){
$user = DeskUserList::where(function($query) use ($deskId){
$query->where('deskId', $deskId);
})->with('userName')->get(array('deskId'));
if (!$user->isEmpty())
return $user;
return 'fail';
}
this is the model
class DeskUserList extends Eloquent {
protected $table = 'desk_user_lists';
public function userName(){
return $this->belongsTo('User', 'userId')->select(array('id','userName'));
}
}
the method getDeskUsers may returns ALL the DeskUserList table records, related with the User table record (on deskUserList.userId = User.id).
practically I want each record returned is composed of:
DeskUserList.deskId
User.userName
eg. [{"deskId":"1","user_name":antonio}]
What i get is
[{"deskId":"1","user_name":null}]
As you can see the user name is a null value...
BUT
if I edit my controller code:
->with('userName')->get(array('userId')); //using userId rather than deskId
then i get
[{"userId":"2","user_name":{"id":"2","userName":"antonio"}}]
By this way I still have two problem:
the userId field is twice repeated
I miss the deskId field (that I need...)
hope be clear, thanks for your time!
You need belongsToMany, no need for a model representing that pivot table.
I assume your models are Desk and User:
// Desk model
public function users()
{
return $this->belongsToMany('User', 'desk_user_list', 'deskId', 'userId');
}
// User model
public function desks()
{
return $this->belongsToMany('Desk', 'desk_user_list', 'userId', 'deskId');
}
Then:
$desks = Desk::with('users')->get(); // collection of desks with related users
foreach ($desks as $desk)
{
$desk->users; // collection of users for particular desk
}
// or for single desk with id 5
$desk = Desk::with('users')->find(5);
$desk->users; // collection of users
$desk->users->first(); // single User model

Resources