Reputation: 13
I'm currently struggling with retrieving data towards a parent model. I'll drop my database, classes, and things I've tried before.
I have 4 tables: sales_orders
, products
, work_orders
, and product_sales_order
(pivot table between sales_orders
and products
).
SalesOrder.php
class SalesOrder extends Model
{
public function products()
{
return $this->belongsToMany(Product::class)
->using(ProductSalesOrder::class)
->withPivot(['qty', 'price']);
}
}
ProductSalesOrder.php
class ProductSalesOrder extends Pivot
{
public function work_orders()
{
return $this->hasMany(WorkOrder::class);
}
public function getSubTotalAttribute()
{
return $this->qty* $this->price;
}
}
WorkOrder.php
class WorkOrder extends Model
{
public function product_sales_order()
{
return $this->belongsTo(ProductSalesOrder::class);
}
public function sales_order()
{
return $this->hasManyThrough(
ProductSalesOrder::class,
SalesOrder::class
);
}
}
So, what I want to retrieve sales order data from work order since both tables don't have direct relationship and have to go through pivot table and that is product sales order. I've tried hasOneThrough
and hasManyThrough
but it cast an error unknown column. I understand that error and not possible to use that eloquent function.
Is it possible to retrieve that sales order data using eloquent function from WorkOrder.php
?
Upvotes: 0
Views: 2118
Reputation: 8082
You cannot achieve what you want using hasOneThrough
as it goes from a table that has no ID related to the intermediate model.
In your example you are doing "the inverse" of hasOneThrough
, as you are going from a model that has the ID of the intermediate model in itself, and the intermediate model has the ID of your final model. The documentation shows clearly that hasOneThrough
is used exactly for the inverse.
So you still should be able to fix this, and use a normal relation as you have the sales_orders_id
in your model SuratPerintahKerja
, so you can use a normal relation like belongsTo
to get just one SalesOrder
and define it like this:
public function salesOrder()
{
return $this->belongsTo(SalesOrder::class, 'sale_orders_id');
}
If you want to get many SalesOrder
s (if that makes sense for your logic), then you should just run a simple query like:
public function salesOrders()
{
return $this->query()
->where('sale_orders_id', $this->sale_orders_id)
->get();
}
Have in mind that:
sales_order
to salesOrder
(follow camel case as that is the Laravel standard...).sales_order
to salesOrders
for the second code as it will return more than 1
, hence a collection
, but the first one just works with one model at a time.sale_orders_id
, but it should be sales_order_id
, have that in mind, because any relation will try to use sales_order_id
instead of sale_orders_id
, again, stick to the standards... (this is why the first code needs more parameters instead of just the model).id
as primary and auto incremental, instead of having the id
of each related model as primary... Because in SuratPerintahKerja
you want to reference the pivot table ProdukSalesOrder
but it has to use both produks_id
(should have been produk_id
singular) and sale_orders_id
(should have been sales_order_id
). So if you were able to use something like produk_sales_order_id
, you could be able to have better references for relations.$this->query()
, I am just doing this to only return a new query and not use anything it has as filters on itself. I you still want to use current filters (like where
and stuff), remove ->query()
and directly use the first where
. If you also want to add ->where('produks_id', $this->produks_id)
that is valid and doesn't matter the order. But if you do so, I am not sure if you would get just one result, so ->get()
makes no sense, it should be ->first()
and also the method's name should be salesOrder
.6
tip/step, but super personal recommendation, always write code in English and do not write both languages at the same time like produks
and sales orders
, stick to one language, preferrably English as everyone will understand it out of the box. I had to translate some things so I can understand what is the purpose of each table.If you have any questions or some of my code does not work, please tell me in the comments of this answer so I can help you work it out.
Edit:
After you have followed my steps and changed everything to English and modified the database, this is my new code:
First, edit ProductSalesOrder
and add this method:
public function sales_order()
{
return $this->belongsTo(SalesOrder::class);
}
This will allow us to use relations of relations.
Then, have WorkOrder
as my code:
public function sales_order()
{
return $this->query()->with('product_sales_order.sales_order')->first();
}
first
should get you a ProductSalesOrder
, but then you can access ->sales_order
and that will be a model.
Remember that if any of this does not work, change all the names to camelCase
instead of kebab_case
.
Upvotes: 1