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

jimmy.puckett's avatar

Time specific settings?

I have an application that has the concept of a "Period". It is a CTE model with monthly, quarterly & yearly periods. Our application has transactional data that accrual on specific dates. We do a bunch of math & such to the data in background jobs to build reports & such. I would like to come up with a nice model for settings that are used by the calculations. Does anyone have any patterns or links to good articles on time series settings? I wish that Laravel had the concept of a related model using time frames as "foreign keys".

I have the following scopes

/**
 * Scope accrued between using a period.
 *
 * @param Builder $query
 * @param Period|iterable|int $period
 *
 * @return Builder
 *
 * @throws InvalidArgumentException
 * @throws InvalidFormatException
 * @throws ModelNotFoundException
 */
public function scopeForPeriod(Builder $query, Period|iterable|int $period): Builder
{
    // If given an array/collection, then loop them all to apply
    if (is_iterable($period)) {
        // Group all of them in a where so that they become orWhere unless inverse, then where
        return $query->where(
            fn(Builder $q) => Collection::wrap($period)->each(
                fn($n) => $q->orWhere->forPeriod($n),
            ),
        );
    }

    if (is_int($period)) {
        $period = Period::findOrFail($period);
    }

    return $this->scopeAccruedBetween($query, $period->start_at, $period->end_at);
}
/**
 * Scope BetweenDates to a specific value.
 *
 * @param Builder $query
 * @param Carbon|CarbonImmutable|DateTime|int|string|null $start_at
 * @param Carbon|CarbonImmutable|DateTime|int|string|null $end_at
 *
 * @return Builder
 */
public function scopeAccruedBetween(
    Builder $query,
    Carbon|CarbonImmutable|DateTime|int|string|null $start_at = null,
    Carbon|CarbonImmutable|DateTime|int|string|null $end_at = null,
): Builder {
    return match (true) {
        is_null($start_at) && is_null($end_at) => $query,
        is_null($start_at) => $query->where('accrual_date', '<=', carbonize($end_at)),
        is_null($end_at) => $query->where('accrual_date', '>=', carbonize($start_at)),
        default => $query->whereBetween('accrual_date', [
            carbonize($start_at),
            carbonize($end_at),
        ])
    };
}

That allows me to get access to the "related" models from the Period via accessor...

/**
 * Accessor for Compensations.
 *
 * @return Collection
 */
public function getCompensationsAttribute(): Collection
{
    return $this->compensationsQuery->get();
}

/**
 * Accessor for Compensations Query.
 *
 * @return Builder
 */
public function getCompensationsQueryAttribute(): Builder
{
    return Compensation::forPeriod($this);
}

I am thinking of doing something simular for Settings, but I just think that there might be a better way.

Anyhow, hoping that one of you may have a good suggestion.

0 likes
0 replies

Please or to participate in this conversation.