Laravel how to load specific column of related table? - laravel

I have the following code, what I want is to take specific columns of related tables.
auth()->user()->load(['business', 'passwordSecurity']);

To select only specific columns from a relationship you should be able to do it like this:
auth()->user()->load([
'business' => function ( $query ) {
$query->select('id', 'title');
},
'passwordSecurity',
]);
Or like this:
auth()->user()->load(['business:id,name', 'passwordSecurity']);
Please note that you have to select IDs and foreign key constraints that are needed to form this relationship.

Related

How to select specific column from parent and child in laravel

Please see my code below.
Controller
$orders = Order::with('product:id,name')
->select([
'id',
'order_number',
'ordered_on',
'status',
'total'
])
->where('customer_id', session('customer_id'))
->orderBy('ordered_on', 'DESC')
->paginate(6);
dd($orders);
Order model
public function product()
{
return $this->belongsTo(Product::class);
}
The result above returns null when you check the product relationship data.
What I need
Select specific columns from Order model, then select specific columns from product relationship.
You need to add the foreign key that you are referencing:
->select([
'product_id'
...
])
...
When using this feature, you should always include the id column and any relevant foreign key columns in the list of columns you wish to retrieve.
Docs: https://laravel.com/docs/9.x/eloquent-relationships#eager-loading-specific-columns

can i get a value from the main table inside a function of a relation table? laravel with

$main->with(['relation' => function ($query) {
$query->orderByRaw("main.colunm + relation.colunm DESC");
}]);
something like this, where I would like to order by a value from the main table with one from the relation table
You need to add join in order to get parent table columns.
$main->with(['relation' => function ($query) {
$query->join('main', 'main.pk', '=', 'relation.fk')->orderByRaw("main.colunm + relation.colunm DESC");
}]);
It's also better to add aliases for table names so they don't conflict with relation columns.
Hopefully, This will work.

Laravel Eloquent with() selecting specific column doesn't return results

Say I have 2 models, Category and POI where 1 Category can have many POIs.
$categoryDetails = Category::with([
'pois' => function ($query) {
$query->where('is_poi_enabled', true);
},
])->findOrFail($id);
The above query returns results from the specific Category as well as its POIs.
However, with the query below:
$query->select('id', 'name')->where('is_poi_enabled', true);
The POIs become empty in the collection.
Any idea why this is happening? When added a select clause to the Eloquent ORM?
While doing a select it's required to fetch the Relationship local or Primary key.
For an example POIs table contains category_id then it's required to select it
Try this:
$categoryDetails = Category::with([
'pois' => function ($query) {
$query->select(['id', 'category_id', 'is_poi_enabled'])
->where('is_poi_enabled', true);
},
])->findOrFail($id);
Good luck!

How to order by eager loaded relationship in Laravel 5.5?

The code below works perfectly and displays all products with discounts in JSON Format for my API. But I want the result ordered by id in the discounts table. Something like orderBy('discount.id', 'desc'). Can anyone provide a solution for this? How it is possible to use orderBy with id column in discount table using has()?
public function promotions()
{
return $this->prepareResult(true, Product::has('discount')->where([
'company_id' => 1, 'is_active' => 1
])->with('category')->with('discount')->get(), [], "All Promotions");
}
You can use a function within your with statement:
public function promotions()
{
return $this->prepareResult(true, Product::has('discount')
->where(['company_id'=> 1, 'is_active'=>1])
->with('category')
->with(['discount' => function ($query) {
return $query->orderBy('id','DESC');
}])->get(), [],"All Promotions");
}
You can read about this here in the documentation.
If you want to go the collection method route instead of Alex's answer (which is also valid), you can just continue to chain collection methods after get. Since you included the with(), you can do
->get()->sortBy('discount.id')
https://laravel.com/docs/5.6/collections#method-sortby
Not related to your question, but wanted to point out that you can pass multiple arguments to with() so that you don't call it twice.
Product::has('discount')->where(['company_id'=> 1, 'is_active'=>1])->with('discount', 'category')->get()
As DevK mentioned, you need to do a join and then you can sort your products by that. The trick here is that you join the discounts table to your products table, but only select the id column (named as discount_id) from your discounts table so you can sort by those records.
In the below example, I assumed that your
Category model's table is categories
Product model's table is products
Discount model's table is discounts
products table references a discount.id as discount_id
This code will return every column from the products table plus a discount_id column, which you can ignore, it's only there for the sorting. It will also keep it as a collection with the relationships that you stated above.
public function promotions()
{
return $this->prepareResult(
true,
Product::has('discount')
->where(['company_id' => 1, 'is_active' => 1])
->with('category')
->with('discount')
->selectRaw('products.*, discounts.id as discount_id')
->join('discount', 'products.discount_id', '=', 'discounts.id')
->orderBy('discount_id', 'DESC')
->get(),
[],
"All Promotions"
);
}

Laravel - Eloquent "Has", "With", "WhereHas" - What do they mean?

I've found the concept and meaning behind these methods to be a little confusing, is it possible for somebody to explain to me what the difference between has and with is, in the context of an example (if possible)?
With
with() is for eager loading. That basically means, along the main model, Laravel will preload the relationship(s) you specify. This is especially helpful if you have a collection of models and you want to load a relation for all of them. Because with eager loading you run only one additional DB query instead of one for every model in the collection.
Example:
User > hasMany > Post
$users = User::with('posts')->get();
foreach($users as $user){
$users->posts; // posts is already loaded and no additional DB query is run
}
Has
has() is to filter the selecting model based on a relationship. So it acts very similarly to a normal WHERE condition. If you just use has('relation') that means you only want to get the models that have at least one related model in this relation.
Example:
User > hasMany > Post
$users = User::has('posts')->get();
// only users that have at least one post are contained in the collection
WhereHas
whereHas() works basically the same as has() but allows you to specify additional filters for the related model to check.
Example:
User > hasMany > Post
$users = User::whereHas('posts', function($q){
$q->where('created_at', '>=', '2015-01-01 00:00:00');
})->get();
// only users that have posts from 2015 on forward are returned
The documentation has already explained the usage, so I will use SQL to explain the methods.
Example:
Assuming there is an Order (orders) has many OrderItem (order_items) and you already built the relationship between them:
// App\Models\Order:
public function orderItems() {
return $this->hasMany('App\Models\OrderItem', 'order_id', 'id');
}
These three methods are all based on a relationship.
with
Result: with() return the model object and its related results.
Advantage: It is eager-loading which can prevent the N+1 problem.
When you are using the following Eloquent Builder:
Order::with('orderItems')->get();
Laravel change this code to only two SQL:
// get all orders:
SELECT * FROM orders;
// get the order_items based on the orders' id above
SELECT * FROM order_items WHERE order_items.order_id IN (1,2,3,4...);
And then Laravel merges the results of the second SQL query with the results of the first SQL by foreign key, finally returning the collection results.
So if you selected columns without the foreign_key in a closure, the relationship result will be empty:
Order::with(['orderItems' => function($query) {
// $query->sum('quantity');
$query->select('quantity'); // without `order_id`
}
])->get();
#=> result:
[{ id: 1,
code: '00001',
orderItems: [], // <== is empty
},{
id: 2,
code: '00002',
orderItems: [], // <== is empty
}...
}]
has
Has will return the model's object when its relationship is not empty.
Order::has('orderItems')->get();
Laravel changes this code to one SQL query:
select * from `orders` where exists (
select * from `order_items` where `orders`.`id` = `order_items`.`order_id`
)
whereHas
The methods whereHas and orWhereHas put where conditions on your has queries. These methods allow you to add customized constraints to a relationship constraint.
Order::whereHas('orderItems', function($query) {
$query->where('status', 1);
})->get();
Laravel changes this code to one SQL query:
select * from `orders` where exists (
select *
from `order_items`
where `orders`.`id` = `order_items`.`order_id` and `status` = 1
)

Resources