【问题标题】:Update a single key value in a Laravel Illuminate collection更新 Laravel Illuminate 集合中的单个键值
【发布时间】:2018-09-27 01:39:35
【问题描述】:

我正在根据 Facebook API 响应构建集合。

$ads = new \Illuminate\Support\Collection;

if (!$ads->has($insight[$key])) {
    $ads->put($insight[$key], [
        'ad_id'                             => $insight[AdsInsightsFields::AD_ID],
        'ad_name'                           => $insight[AdsInsightsFields::AD_NAME],
        'ctr'                               => (float)$insight[AdsInsightsFields::CTR],
        'spend'                             => (float)$insight[AdsInsightsFields::SPEND],
    ]);
} else {
    // Increment spend value here.
}

如果这是一个数组,我会这样做:

$ads[$insight[$key]]['spend'] += $insight[AdsInsightsFields::SPEND];

如何在集合上执行此操作?

【问题讨论】:

    标签: laravel collections laravel-5.5


    【解决方案1】:

    为了解决这个问题,我编写了能够执行所需更新的宏。

    // Set a single value by dot notation key.
    Collection::macro('set', function ($key, $new) {
        $key = explode('.', $key);
        $primary_key = array_shift($key);
        $key = implode('.', $key);
        $current = $this->get($primary_key);
    
        if (!empty($key) && is_array($current)) {
            array_set($current, $key, $new);
        } else {
            $current = $new;
        }
    
        $this->put($primary_key, $current);
    });
    // Increment a single value by dot notation key.
    Collection::macro('increment', function ($key, $amount) {
        $key = explode('.', $key);
        $primary_key = array_shift($key);
        $key = implode('.', $key);
        $current = $this->get($primary_key);
    
        if (!empty($key) && is_array($current)) {
            $new = array_get($current, $key, 0);
            $new += $amount;
    
            array_set($current, $key, $new);
        } else {
            $current += $amount;
        }
    
        $this->put($primary_key, $current);
    });
    // Decrement a single value by dot notation key.
    Collection::macro('decrement', function ($key, $amount) {
        $key = explode('.', $key);
        $primary_key = array_shift($key);
        $key = implode('.', $key);
        $current = $this->get($primary_key);
    
        if (!empty($key) && is_array($current)) {
            $new = array_get($current, $key, 0);
            $new -= $amount;
    
            array_set($current, $key, $new);
        } else {
            $current -= $amount;
        }
    
        $this->put($primary_key, $current);
    });
    

    有了这个,我需要做的就是:

    $ads->increment($insight[$key] . '.spend', $insight[AdsInsightsFields::SPEND]);
    

    如果我想简单地设置一个值,无论键是否存在,我都可以这样做:

    $ads->set($insight[$key] . '.spend', $insight[AdsInsightsFields::SPEND]);
    

    【讨论】:

    • increment() 函数用于“Eloquent Collections”而不是“Collections”。这意味着它直接更新数据库列。除非您想直接更新那里的数据库列,否则不要使用它。跨度>
    • @TharakaDilshan 这是\Illuminate\Support\Collection 不是\Illuminate\Database\Eloquent\Collection 类型的集合,因此我使用宏创建的方法不存在。
    • 哦,很抱歉,我没有看到它是自定义创建的。
    • 在您的 set 宏中,collect(['x' => ['y','z'])->set('x.0', 'A'); 无法工作,因为您测试了 !empty($key)。最好将 int 转换为字符串并检查长度 strlen(trim((string) $key))
    【解决方案2】:
    $ads->{$insight[$key]}['spend'] +=  $insight[AdsInsightsFields::SPEND];
    

    看起来有点奇怪,但是您需要将第一部分作为对象属性->propertyName 访问,该属性名称是您从数组$insight[$key] 中获取的,因此您需要在它周围加上括号,最后您需要要求以 [spend] 结尾的该属性的数组键。

    【讨论】:

    • $ads->{$insight[$key]} 总是抛出错误 Property does not exist on this collection instance. 即使在运行 put() 部分之后。
    • 奇怪,试试 dd($insight[$key], $ads);并检查转储的第一个值是否作为转储集合中的键存在
    • 是的,它存在。创建了一个非常简单的测试场景,以确保代码可以工作但没有 bueno:$ads = new Collection(); $key = 'test'; $ads->put($key, ['spend' => 0]); $ads->{$key}['spend'] += 5;
    • 对不起,不知道从哪里开始,我在自己的项目中使用该语法没有问题
    【解决方案3】:

    首先,这是数组的集合(不是集合的集合)。

    您的问题是如何在集合中获取特定的键值对,

    答案是收集上的“get()”函数。 现在您可以简单地增加“支出”值,如下所示。

    $ads->get($insight[$key])['spend'] += $insight[AdsInsightsFields::SPEND];
    

    注意

    如果您需要将整个东西作为集合,请更新您的代码以制作如下集合的集合

    $ads->put($insight[$key],  collection([
        'add_id'                            => $insight[AdsInsightsFields::AD_ID],
        'ad_name'                           => $insight[AdsInsightsFields::AD_NAME],
        'ctr'                               => (float)$insight[AdsInsightsFields::CTR],
        'spend'                             => (float)$insight[AdsInsightsFields::SPEND],
    ]);
    

    然后您可以按如下方式增加支出值。

    $ads->get($insight[$key])->spend += $insight[AdsInsightsFields::SPEND];
    

    【讨论】:

    • $ads->get($insight[$key])['spend'] 将不起作用,因为 get() 不会通过引用返回,因此该属性永远不会更新。
    • get() 函数通过引用返回,但 ['spend'] 是这里的问题。我为此道歉。这就是为什么我建议您使用第二种方法,将所有内容都收集起来而不是保留数组。 `$ads->get($insight[$key])->spend += $insight[AdsInsigntsFields::SPEND];'工作正常
    猜你喜欢
    • 2018-08-20
    • 2018-03-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-20
    • 2018-01-15
    • 2017-09-27
    相关资源
    最近更新 更多