Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Php Conditional Proxy Laravel Package

astrotomic/php-conditional-proxy

A lightweight conditional proxy for PHP that lets you chain method calls on any object and execute them only when your conditions pass. Use when/unless-style checks to keep optional logic clean, fluent, and free of scattered if statements.

View on GitHub
Deep Wiki
Context7

Getting Started

Install the package with Composer:

composer require astrotomic/php-conditional-proxy

There is no meaningful Laravel configuration step: this is a small, framework-agnostic utility. Look first at the ConditionalProxy class and the HasConditionalProxy trait in the package source. The core idea is simple: wrap a target object, provide a boolean condition, and every proxied method call is either forwarded to the target or silently skipped while still returning the proxy so the chain continues.

The fastest first use case is conditionally mutating a fluent builder without scattering if statements:

use Astrotomic\ConditionalProxy\ConditionalProxy;

$query = Post::query();

(new ConditionalProxy($request->user()->isAdmin(), $query))
    ->withTrashed()
    ->whereNotNull('published_at');

return $query->latest()->get();

The important point in that example is that the underlying $query is mutated when the condition is true, while the terminal get() is called on the real query object, not on the proxy. That pattern avoids most of the proxy’s sharp edges and is the best default for day-to-day Laravel work.

You can also add the package’s HasConditionalProxy trait to a class that owns fluent methods, which gives you a when($condition) entry point:

use Astrotomic\ConditionalProxy\ConditionalProxy;

$this->when($user->isAdmin())
    ->audit('post.deleted', $post)
    ->flushCache();

Implementation Patterns

Mutate a shared fluent object, then call the terminal method normally. This is the safest pattern for Eloquent, the query builder, migrations, HTTP clients, and custom builders:

$query = Invoice::query();

(new ConditionalProxy($includeDrafts, $query))
    ->where('status', 'draft')
    ->orWhereNull('sent_at');

$invoices = $query->paginate();

The proxy only handles conditional calls; the real object remains available for return values, pagination, get(), first(), and so on.

Use the trait for service/action classes. If a class exposes a fluent API of its own, the trait keeps call sites clean:

class PublishPost
{
    use HasConditionalProxy;

    public function handle(Post $post, bool $notify): void
    {
        $post->publish();

        $this->when($notify)
            ->sendNewsletter($post)
            ->pingSearchIndex($post);
    }
}

Drive behavior from configuration and feature flags. Conditional proxies are a good fit for optional side effects where the fluent chain reads better than nested conditionals:

$this->when(config('features.audit_log'))
    ->record('post.published', $post)
    ->tag('publishing');

Combine with dependency injection at the call site. Resolve the real service from the container, then wrap only where the condition is known:

$mailer = app(NewsletterMailer::class);

(new ConditionalProxy($shouldSend, $mailer))
    ->to($user->email)
    ->subject($subject);

Use it for conditional cross-cutting calls, not for branches whose return value matters. The proxy is strongest when the called methods are fluent, mutating, or side-effect-oriented. If you need to branch on a returned value, use a normal if or Laravel’s native when() with a callback.

Gotchas and Tips

  • The condition is captured once. If state changes mid-chain, the proxy will not re-evaluate the boolean. Create a new proxy for a new condition.
  • Terminal methods are swallowed when the condition is false. Calling ->get(), ->first(), ->save(), or any method that should return a meaningful value through a false-condition proxy returns the proxy rather than a result. Keep a reference to the underlying object and run terminal operations against it.
  • Return values get wrapped. When the condition is true, method results may be wrapped in a new proxy so chaining can continue. This is convenient for fluent APIs but surprising if you expect the exact target type. Unwrap or use the original object before returning from your method.
  • Static analysis and IDEs do not understand __call. Add @method annotations or a @mixin annotation for the wrapped class in your own wrapper types. Without this, PHPStan, Psalm, and IDE completion will treat proxied calls as magic.
  • Type declarations can reject the proxy. A method typed against Post, Builder, or another concrete class will not accept the proxy itself. Pass the real object where a concrete type is required.
  • Public methods on the proxy are not proxied. Only inaccessible or missing methods go through __call. Do not expect proxy-control methods to be forwarded to the target.
  • Trait method conflicts are silent. If your class already has a when() method, for example because it extends a class or uses another trait with that name, the existing method can win over the trait method. Alias the trait method or instantiate ConditionalProxy directly.
  • Exceptions are not suppressed. A false condition skips the call entirely, but a true condition behaves exactly like a normal method call; exceptions propagate as usual.
  • Do not serialize or queue the proxy. Store and serialize the underlying object. The proxy is a transient call-site convenience, not a domain object.
  • Prefer explicit if at public boundaries. Inside a fluent chain the proxy improves readability; at the edge of a method, an explicit conditional is usually clearer and less surprising for the next developer.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
elsayed85/laravel-api-exceptions
ouhssini/laravel-demo-mode
daworks/ncloud-outbound-mailer-driver
gp247/cms
ignibyte/aic-gates
nexa-merchant/blog
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
cgv/localized-resource