Select specific columns from specific model morph relationships - laravel

I need to select only some columns from specifics morph models.
The withdrawal model:
public function product()
{
return $this->morphTo('product', 'product_type', 'product_id');
}
The Product1, Product2, and Product3 models has an ID and a name column. The Product4 and Product5 does not have the name column, so when I use the next code ->with('product:id,name') it give me the error SQLSTATE[42S22]: Column not found
¿How can I select some specific column from specific models?

You may add a scope to the product models.
public function scopeFilter($query)
{
return $query->select(['id', 'name', 'slug']);
}
Replace the array with your columns.
Then, in your withdrawal model, add the scope to the product relationship. Please make sure you have added the scope to all the potential product models.
public function product()
{
return $this->morphTo('product', 'product_type', 'product_id')->filter();
}

Related

Model file name changes the table name in database

Hello i have a table called order_product that i want to get values from it and the model for that table called order_product with values:
public $timestamps = false;
protected $fillable = [
'order_id',
'product_id',
'amount',
];
This is the code of the model Order :
public $timestamps = true;
protected $fillable = [
'order_number',
'client_id',
'description',
];
public function client()
{
return $this->belongsTo(Client::class);
}
public function products()
{
return $this->belongsToMany(Product::class);
}
public function orders()
{
return $this->belongsToMany(order_product::class);
}
A professional guy helped me and explained to me how the relation worked so the client and products work very good but the orders makes error in the sql.
This is the code im executing in the controller:
$orders = Order::where('id', $id)->firstOrFail();
$orders->load('client', 'products','orders');
The error that i get is:
SQLSTATE[42S02]: Base table or view not found: 1146 Table 'user_project_db.order_products' doesn't exist
What should be the name of the file order_product so the query can execute properly?
I change my answer after reading your answers below.
Your table relationship is orders - order_product - products.
https://webdevetc.com/blog/laravel-naming-conventions/
under Pivot tables
The way you named your pivot table is already correct.
order_product is to connect orders to products in a many-to-many.
So i think you can try to do the following.
Inside model Product add this relationship.
public function orders()
{
return $this->belongsToMany(Order::class, 'order_product');
}
And in model Order add the other connection
public function products()
{
return $this->belongsToMany(Product::class, 'order_product');
}
belongsToMany accepts 2 parameter, 1st is model destination, and 2nd is table pivot name, in your case order_product.
With this , an extra model OrderProduct is optional.
To add a product into order , you can use attach
$order = Order::find($order_id);
$order->products()->attach($product_id);
Or if you have extra fields within pivot table
// first implement this change inside Order model
return $this->belongsToMany(Product::class, 'order_product')
->withPivot('price', 'qty');
// to attach for example price and qty
$order->products()->attach($product_id, ['price' => 200', 'qty'=> 1]);
To query the price
$order_product = $order->products()
->where('product_id', $product_id)
->first()->pivot;
$price = $order_product->price;
$qty = $order_product->qty;
And back to your own query.
No need to add orders() inside Order model.
And load only the first 2 relationship should be enough.
$order->load('clients', 'products');
protected $table = 'order_products; in the model will tell Laravel that the Order model's data is stored in a table by that name.
However, typically you'd have an Order model, a Products model, and a pivot table (potentially with a pivot model, if you need it) titled order_products. https://laravel.com/docs/9.x/eloquent-relationships#defining-custom-intermediate-table-models

Relationship invoices between 5 tables

I have table called invoices, orders, games, products, users
This is my invoices table structure
id name order_id
This is my orders table structure
id name game_id product_id user_id
This is my games table structure
id name display_name
This is my products table structure
id product_sku name price profit
As you see in this case I'm trying to make an order that generate an invoices after you place an order. In the invoices, I wanted to show the games name, products name, price, and user who make the order.
What relationship should I use? is it hasMany, or belongsToMany? or should I make another table called invoice_order?
Updated!
I forgot to show my table game_product, I already make a belongsToMany relationship between games and products table.
id game_id product_id
Cmiiw
I think you should have the following table structure:
Orders (renamed from invoice)
id name user_id
order_product (pivot)
order_id product_id
games
id name display_name
products
id product_sku name price profit game_id
These should be the relationships:
Order model
public function products() {
return $this->belongsToMany(Product::class);
}
public function user() {
return $this->belongsTo(User::class);
}
Game model
public function product() {
return $this->hasMany(Product::class);
}
public function orders() {
return $this->hasManyThrough(Order::class, Product::class);
}
Product model
public function game() {
return $this->belongsTo(Game::class);
}
public function orders() {
return $this->belongsToMany(Order::class);
}
This way you can generate an invoice:
$invoiceData = Order::with([ 'user', 'products', 'products.game' ])->find($id);
This will have all necessary information of the order within the $invoiceData object e.g. $invoiceData->user will be the user placing the order and $invoiceData->products will be a collection of ordered products.
Note that it's usually good practice to put the price in the order_product pivot as an extra pivot field since the price people buy an item for is not always the price that the item goes for at all times so that way you can have information on the price the item was sold for rather than what item was sold and how much it costs today.
A simple belongs to relation is good enough for your case scenario
Invoice.php
public function order(){
return $this->belongsTo(Order::class);
}
Order.php
public function game(){
return $this->belongsTo(Game::class)->select('id', 'name')
}
public function product(){
return $this->belongsTo(Product::class)->select('id', 'name')
}
Controller.php
Invoice::with(['order' => function($q) {
return $q->with('game', 'product');
})->get();

How to get data from three models that are related to each other in Laravel 5.8

So I have this model Order which has one to many relation with ProductOrder model. And also Product model which has the same one to many relation with ProductOrder model. I can get the PorductOrder data with Product or with Order. Like this:
Order::with('product_orders')->get();
Now this is returning my orders with the associated ProductOrder data. How can I include the Products of each ProductOrder data in this collection?
Make changes of function name, field name, model name as per you requirements
Step 1:
In you ProductOrder Model use this function:
public function products()
{
return $this->hasOne('App\Product', 'id', 'product_id');
}
Step 2:
After this in you query you can use as:
Order::with('product_orders.products')->get();
It sounds like ProductOrder is just a joining table/model, is that right? If that is the case, you should change to a ManyToMany relationship to of the Products model to
public function orders()
{
return $this->belongsToMany('App\Orders', 'product_order');
}
and the Orders to
public function products()
{
return $this->belongsToMany('App\Products', 'product_order');
}
Then you can access like
Order::find(1)->products()->get();

Laravel how to make Eloquent relationship to find all data from child_category table with related category & subcategory name?

I have three table:
categories table fields id, category_name
subcategories table fields id, category_id, subcategory_name
child_categories table fields id, category_id, subcategory_id, child_category_name
I have three model Category, Subcategory,
1) =>category model code
class Category extends model {
public function subcategory(){
return $this->hasMany(Subcategory::class);
}
public function Child_category(){
return $this->hasMany(Child_category::class);
}
}
2) =>Subcategory model code
class Subcategory extends model {
public function Category(){
return $this->belongsTo(Category::class);
}
}
3) =>Child_category model code
class Child_category extends model {
public function Category(){
return $this->belongsTo(Category::class);
}
}
how to make Eloquent relationship to find all data from child_categories table with related category & subcategory name?
Once the relationships are defined you can get them by simply calling the property that has the same name as the relation you need.
$category = Category::first();
$subcategory = $category->subcategory;
If you wanted to get all the categories with all subcategories and child categories in one line you can use the with() method to eagerload them efficiently.
$categories = Category::with(['subcategory', 'Child_category'])->get();
This will fetch all the categories, then fetch all the related subcategories and child categories and associate them appropriately.

Laravel Eloquent Relation Model

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.

Resources