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

t0berius's avatar

code review / idea to solve problem

I'm using some conversion rates inside my application. They are fetched every n minutes and stored inside a "config" table.

Each product has an accessor like this:

public function getPriceEUR()
{
    return intval($this->usd_price / SystemConfig::find(1)->value * 100);
}

I'm using this way to make sure I don't overload a webAPI. I figured out a problem, when displaying many products in a listing.

Every product listing will result in 1 database call to load SystemConfig::find(1)->value. This is for sure not a good way to go, using eager loading all the time and now this...any suggestions?

0 likes
9 replies
Cronix's avatar

Are those values something you can put in a config file instead of the database?

Another option is to cache the query, and then get the value from cache so you're not hitting the db constantly.

t0berius's avatar

Storing them inside the redis was an idea of me too...unsure about this, but the idea of @snapey to use a file to store them doesn't sound that bad.

Snapey's avatar

If you don't want to refactor a lot, an alternative is to just cache the row.

public function getPriceEUR()
{
    $factor = Cache::remember('factor', 5, function () {
            return SystemConfig::find(1)->value;
    });

    return intval($this->usd_price / $factor * 100);
}


Snapey's avatar

Don't just put it in a file, thats not what I am saying.

It needs to be in memory so that if you iterate over 100 products you are not accessing the file 100 times.

In a service provider, or AppServiceProvider, load it from the file and store it in the app object or config element

t0berius's avatar

@snapey

Would you suggest to use redis to store the value (redis is in use for sessions already) or what way do you suggest (I appreciate your replys that much, since they are very helpful)?

Using:

https://github.com/spatie/valuestore/#usage is storing them inside a file, so from my point of view, this would result in opening the file n times (as much as listings are generated), so the problem would just be moved from database to "file read I/O".

Snapey's avatar
Snapey
Best Answer
Level 122

How about;

Install Valuestore composer require spatie/valuestore

In AppServiceProvider register method;

    public function register()
    {
        $this->app->singleton('valuestore', function () {
            return \Spatie\Valuestore\Valuestore::make(storage_path('app/settings.json'));
        });

        $values = $this->app->valuestore->all();

        $this->app->bind('settings', function () use($values) {
            return $values;
        });
    }

What we have in the app container is a singleton that points to the valuestore class. When you use that, you are directly interacting with the settings stored in the file.

When you use the settings bound to the app container, you are using a cached version of the values as they were at the start of the request cycle (as an associated array).

So instead of writing the current Euro rate to a database row, put it in the valuestore instead;

app('valuestore')->put('EUR', $rate)

and in your model when you want to apply this;

public function getPriceEUR()
{
    return intval($this->usd_price / app('settings')['EUR'] * 100);
}

By using settings and not valuestore the file will only be accessed once and not each time you iterate over the products.

Of course you now have a place where you can store other currencies or any other application settings.

1 like
t0berius's avatar

@snapey rules.

Very clever way to get this done. Just of interested, why not using redis, your solution works fine.

Snapey's avatar

If you have a redis server then use it as a cache, but it seems an overkill if you are not using it for anything else.

Please or to participate in this conversation.