I have two tables like this:
products:
+----+-----------+
| id | name |
+----+-----------+
| 1 | Product 1 |
| 2 | Product 2
When Laravel eager loads a relationship, it will perform two queries similar to this:
SELECT * FROM products WHERE 1;
SELECT * FROM prices WHERE product_id = 1;
What you want to do is to add a condition to the second query to get the row with most recent price. So you would want something like this:
SELECT * FROM products WHERE 1;
SELECT * FROM prices WHERE product_id = 1 ORDER BY price;
Luckily in Laravel's Eager Load Constraints you can, instead of passing a string into with(), you can pass an array with the relationship name as key and a subquery closure as its value. Like this:
$products = Product::with(array('prices' => function($query)
{
$query->orderBy('created_at', 'desc');
}))->get();
Then in your code you can do:
$product->prices->first();
to get the most recent price of each product.
Note: You may notice that Laravel will still load all the prices for each product. I don't think there's a way around it while still using purely Eloquent because the way eager loading work is fetching all the relationship records in one single query, so there isn't an easy way to say get only the most recent price for each product.
Another solution:
However, if you are strictly needing to know just a value from another table, you could do a sub-select instead:
$products = Product::select('*')
->addSelect(DB::raw('(SELECT price FROM prices WHERE products.id = prices.product_id ORDER BY created_at DESC LIMIT 1) price'))
->get();