FnChain

·

1 min read

FnChain is an experimental helper I came up with when dealing with the following nesting closure:

return $query
    ->where('is_enabled', true)
    ->where('available_from', '<=', DB::raw('NOW()'))
    ->where(
        fn (Builder $q) => $q
            ->whereNull('available_until')
            ->orWhere(
                fn (Builder $q) => $q
                    ->whereNotNull('available_until')
                    ->where('available_until', '>', DB::raw('NOW()'))
            )
    );

I want to avoid fn (Builder $q) => $q. With FnChain, above code can be rewritten to:

return $query
    ->where('is_enabled', true)
    ->where('available_from', '<=', DB::raw('NOW()'))
    ->where(
        FnChain
            ::whereNull('available_until')
            ->orWhere(
                FnChain
                    ::whereNotNull('available_until')
                    ->where('available_until', '>', DB::raw('NOW()'))
                    ->toClosure()
            )
            ->toClosure()
    );

But the toClosure is anoying me, maybe we can use Closure::fromCallable to get ride of it?

return $query
    ->where('is_enabled', true)
    ->where('available_from', '<=', DB::raw('NOW()'))
    ->where(Closure::fromCallable(
        FnChain
            ::whereNull('available_until')
            ->orWhere(Closure::fromCallable(
                FnChain
                    ::whereNotNull('available_until')
                    ->where('available_until', '>', DB::raw('NOW()'))
            ))
    ));

Source code of FnChain is available on this Gist: gist.github.com/binotaliu/5479edace5f1079f9..


P.S.

After a while, I realize that the condition available_until == null or (available_until != null && available_until > NOW()) can be simplified as available_until == null or available_until > NOW(). Anyway, this is just an experiment which tries to find a way in PHP to provide more readable code. (Although I don't think it actually improved readability. It's just a fun experiment.)