skip to Main Content

I have a model called RealEstate, this model has a relation with another model called TokenPrice, I needed to access the oldest records of token_prices table using by a simple hasOne relation, So I did it and now my relation method is like following:


use IlluminateDatabaseEloquentModel;
use IlluminateDatabaseEloquentRelationsHasOne;

class RealEstate extends Model
{
    public function firstTokenPrice(): HasOne
    {
        return $this->hasOne(TokenPrice::class)->oldestOfMany();
    }
}

By far it’s fine and no complexity. But now, I need to involve another relation into firstTokenPrice.

Let me explain a bit more:

As my project grown, the more complexity was added it, like changing firstTokenPrice using by a third table called opening_prices, so I added a new relation to RealEstate called lastOpeningPrice:

public function lastOpeningPrice(): HasOne
{
    return $this->hasOne(OpeningPrice::class)->latestOfMany();
}

So the deal with simplicity of firstTokenPrice relation is now off the table, I want to do something like following every time a RealEstate object calls for its firstTokenPrice:

Check for lastOpeningPrice, if it was exists, then firstTokenPrice must returns a different record of token_price table, otherwise the firstTokenPrice must returns oldestOfMany of TokenPrice model.

I did something like following but it’s not working:


use IlluminateDatabaseEloquentModel;
use IlluminateDatabaseEloquentRelationsHasOne;

class RealEstate extends Model
{
    public function lastOpeningPrice(): HasOne
    {
        return $this->hasOne(OpeningPrice::class)->latestOfMany();
    }

    public function firstTokenPrice(): HasOne
    {
        $lop = $this->lastOpeningPrice;
        if ($lop) {
            TokenPriceHelper::getOrCreateFirstToken($this, $lop->amount); // this is just a helper function that inserts a new token price into `token_prices` table, if there was none exists already with selected amount
            return $this->hasOne(TokenPrice::class)->where('amount', $lop->amount)->oldestOfMany();
        }
        return $this->hasOne(TokenPrice::class)->oldestOfMany();
    }
}

I have checked the $this->hasOne(TokenPrice::class)->where('amount', $lop->amount)->oldestOfMany() using by ->toSql() method and it returns something unusual.

I need to return a HasOne object inside of firstTokenPrice method.

2

Answers


  1. Chosen as BEST ANSWER

    I used ->oldest() with a custom scope called amounted in TokenPrice model:

    class TokenPrice extends Model
    {
        public function scopeAmounted(Builder $query, OpeningPrice $openingPrice): Builder
        {
            return $query->where('amount', $openingPrice->amount);
        }
    
        /....
    }
    

    And then changed my firstTokenPrice

    public function firstTokenPrice(): HasOne
    {
        $lop = $this->lastOpeningPrice;
        if ($lop) {
            TokenPriceHelper::getOrCreateFirstToken($this, $lop->amount);
            return $this->hasOne(TokenPrice::class)->amounted($lop)->oldest();
        }
        return $this->hasOne(TokenPrice::class)->oldestOfMany();
    }
    

    It's working, but I don't know if it's the best answer or not


  2. You can use ofMany builder for that purpose:

        public function firstTokenPrice(): HasOne
        {
            $lop = $this->lastOpeningPrice;
            if ($lop) {
                TokenPriceHelper::getOrCreateFirstToken($this, $lop->amount); // this is just a helper function that inserts a new token price into `token_prices` table, if there was none exists already with selected amount
                return $this->hasOne(TokenPrice::class)->ofMany([
                    'id' => 'min',
                ], function ($query) use ($lop) {
                    $query->where('amount', $lop->amount);
                });
            }
            return $this->hasOne(TokenPrice::class)->oldestOfMany();
        }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search