You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel能否为任意对象添加->when()或->unless()条件方法?

在Laravel中为任意对象添加when()/unless()方法的实现方案

当然可以实现这个需求。Laravel的集合类本身自带when()和unless()方法,但要让任意类型的对象都支持这两个条件方法,你可以通过自定义一个对象包裹类来实现,同时完全保留原对象的所有功能。

具体实现步骤

1. 创建对象包裹类

在app/Support目录下创建ObjectWrapper.php:

<?php

namespace App\Support;

class ObjectWrapper
{
    protected $object;

    public function __construct($object)
    {
        $this->object = $object;
    }

    // 实现when条件方法:条件为true时执行回调
    public function when($condition, callable $callback)
    {
        if ($condition) {
            $result = $callback($this->object);
            // 若回调返回新对象,更新内部实例
            if ($result !== null) {
                $this->object = $result;
            }
        }
        return $this;
    }

    // 实现unless条件方法:条件为false时执行回调
    public function unless($condition, callable $callback)
    {
        return $this->when(!$condition, $callback);
    }

    // 魔术方法:转发所有未定义的方法调用到原对象
    public function __call($method, $parameters)
    {
        $result = call_user_func_array([$this->object, $method], $parameters);
        // 若原方法返回自身(支持链式调用),返回包裹类保持链式
        if ($result === $this->object) {
            return $this;
        }
        // 否则返回方法实际结果
        return $result;
    }

    // 魔术方法:获取原对象属性
    public function __get($property)
    {
        return $this->object->$property;
    }

    // 魔术方法:设置原对象属性
    public function __set($property, $value)
    {
        $this->object->$property = $value;
    }

    // 提供方法获取原对象
    public function unwrap()
    {
        return $this->object;
    }
}

2. 创建全局wrap()辅助函数

在项目根目录创建app/helpers.php(如果已有则直接添加):

<?php

if (!function_exists('wrap')) {
    function wrap($object)
    {
        return new \App\Support\ObjectWrapper($object);
    }
}

然后更新Composer自动加载,让辅助函数生效:

composer dump-autoload

3. 使用示例

完全按照你期望的方式调用即可:

// 示例自定义对象
$myObject = new class {
    public function changeSomething()
    {
        // 执行修改逻辑
        return $this;
    }

    public function doOtherAction()
    {
        // 执行其他操作
        return $this;
    }
};

// 包裹对象后链式调用
$object = wrap($myObject)
    ->when(true, function ($obj) {
        return $obj->changeSomething();
    })
    ->doOtherAction() // 直接调用原对象方法,不影响链式
    ->unless(false, function ($obj) {
        return $obj->changeSomething();
    });

// 如需获取原对象,调用unwrap()
$originalObject = $object->unwrap();

关键说明

  • 包裹类通过魔术方法实现了对原对象的完全转发,原对象的所有方法、属性都能正常使用。
  • when()/unless()方法支持回调返回新对象,包裹类会自动更新内部实例,保证链式调用的连贯性。
  • 这个实现完全兼容Laravel的生态,不会和框架现有功能冲突。

内容的提问来源于stack exchange,提问作者Pejman

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 06:05:24