Skip to content

[12.x] Introduce ComputesOnceableHashInterface #56009

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jun 12, 2025

Conversation

Jacobs63
Copy link
Contributor

@Jacobs63 Jacobs63 commented Jun 12, 2025

When using the once helper and using object used variables in the callable, the spl_object_hash function is used.
This becomes an issue when using value objects, as each value object would very likely be unique, therefore trying to utilize the Onceable cache doesn't work, even if those value objects carry the same value inside.

Imagine a scenario, where we have a value object named PositiveInteger, which self-validates that the carried value is an integer of value higher than zero:

class PositiveInteger
{
    public function __construct(
        public readonly int $value,
    )
    {
        if ($value <= 0) {
            throw new \InvalidArgumentException('Value must be a positive integer.');
        }
    }
}

Now imagine we're trying to utilize the onceable helper for caching some database queries during the request/job:

    public function getTagFromId(PositiveInteger $id): ?string
    {
        return once(fn () => DB::table('xy')->where('id', $id->value)->soleValue('tag'));
    }

Calling the same method twice, passing a value object which carries the same value (and therefore returns the same result) would still make the callable execute twice, even though that would be undesired:

$id = new PositiveInteger(1);

// Query 1
$tag = $this->getTagFromId($id);

$id = new PositiveInteger(1);

// Query 2
$tag = $this->getTagFromId($id);

Instead now, we could tell our value object to specify it's hash, allowing the onceable helper to call a method on the used object dependency.

Now, we can do this instead:

class PositiveInteger implements ComputesOnceableHashInterface
{
    // ...

    public function computeOnceableHash()
    {
        return 'positive-integer' . ':' . $this->value;
    }
}

We've now effectively ensured that the database would only be called once.

@taylorotwell taylorotwell merged commit feccc98 into laravel:12.x Jun 12, 2025
60 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants