Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

panthro's avatar

Linking prices to products - pivot table or not?

I have a products table. I want to track the prices of these products over time.

With that in mind, I see two solutions.

A prices table looking like this, with once price belonging to a product (and a product having many prices).

id | price | date | product_id

I have also considered the alternative of having a prices table looking like:

id | price

With this setup the same price, for example $10, would only be entered once, and this price would be linked to many products, with a pivot table:

price_product

price_id | product_id | date

Which setup would be the better way to go, efficiency-wise - by this I mean speed.

0 likes
2 replies
LaryAI's avatar
Level 58

Both solutions are valid and efficient, but the second option with a pivot table would be more flexible in the long run. It allows for easier management of prices and products, as well as the ability to add additional attributes to the pivot table if needed.

Here's an example of how you could set up the tables and relationships in Laravel:

// Product model
class Product extends Model
{
    public function prices()
    {
        return $this->belongsToMany(Price::class)->withPivot('date');
    }
}

// Price model
class Price extends Model
{
    public function products()
    {
        return $this->belongsToMany(Product::class)->withPivot('date');
    }
}

// Pivot table migration
Schema::create('price_product', function (Blueprint $table) {
    $table->id();
    $table->unsignedBigInteger('price_id');
    $table->unsignedBigInteger('product_id');
    $table->date('date');
    $table->timestamps();

    $table->foreign('price_id')->references('id')->on('prices')->onDelete('cascade');
    $table->foreign('product_id')->references('id')->on('products')->onDelete('cascade');
});

With this setup, you can easily retrieve a product's prices and dates:

$product = Product::find(1);
$prices = $product->prices;

foreach ($prices as $price) {
    echo $price->price . ' on ' . $price->pivot->date;
}
Snapey's avatar

create a prices table with an id and a price and a product_id column, plus usual timestamps

In product Model add a relationship

    public function prices()
    {
	    return $this->hasMany(Price::class);
    {

So now a product can have many prices. In most occasions, all you are after is the latest price. For this you can use the Has One Of Many relationship. https://laravel.com/docs/10.x/eloquent-relationships#has-one-of-many

Add this to your Product model;

public function latestPrice()
{
    return $this->hasOne(Price::class)->latestOfMany();
}

If you are on laravel 10, you can also defer to the hasMany relationship;

https://laravel.com/docs/10.x/eloquent-relationships#converting-many-relationships-to-has-one-relationships

When loading the product model, you will need to remember to add the latest price to your query, or alternatively use the protected $with parameter on your Product model so that the latest price is always loaded.

$products = Product::with('latestPrice')->get()

or

protected $with = ['latestPrice'];

https://laravel.com/docs/10.x/eloquent-relationships#eager-loading-by-default

Please or to participate in this conversation.