【问题标题】:Merging two Laravel collections合并两个 Laravel 集合
【发布时间】:2016-06-05 21:05:04
【问题描述】:

使用 Laravel 集合让我头疼。我有两个收藏:

    $dt = Carbon::now();
    $days = new Collection([]);

    /**
     * Create a calender month
     */
    for ($day = 1; $day <= $dt->daysInMonth; $day++) {
        $date = Carbon::create($dt->year, $dt->month, $day)->toDateString();
        $days->push(new Timesheet([
            'date' => $date,
        ]));
    }

    /**
     * Get all timesheets for user
     */
    $timesheets = Timesheet::where('user_id', $this->user->id)
        ->get();

\Illuminate\Database\Eloquent\Collection ($timesheets)

#attributes: array:5 [▼
    "id" => "1"
    "user_id" => "1"
    "date" => "2016-02-22 22:05:01"
    "created_at" => "2016-02-22 22:05:01"
    "updated_at" => "2016-02-22 22:05:01"
  ]
  // ... one or more ...

我有第二个集合,给我一个给定月份的所有天数。

\Illuminate\Support\Collection ($days)

#attributes: array:1 [▼
    "date" => "2016-02-01 00:00:00"
]
// ... and the rest of the month.

我想将$days 集合与$timesheet 集合合并,以保留$timesheet 集合的值并删除$days 集合中存在的任何重复项。例如。如果$timesheets 已经包含'2016-02-24' 我不想从$days 合并'2016-02-24'。我该怎么做?

【问题讨论】:

  • 它们不是碳对象,只是字符串。合并可能是下面的答案。如果你想做一些过滤,请使用集合的过滤方法
  • 如果没有collections,你的头会很痛。
  • @MikeMiller 我的意思是它们被转换为 Carbon 实例。见:laravel.com/docs/5.1/eloquent-mutators#introduction
  • 那么这些系列是什么样子的?
  • 添加了一个可能解决您的问题的答案,但我不知道为什么合并只会合并最后一项。

标签: php laravel laravel-5 laravel-collection


【解决方案1】:

好的,试试这个。逻辑应该可以解决,但 obv 无法访问您的 Timesheet 类..

$days = new Collection([]);

//basically the same structure i think
$timesheets = new Collection([new Collection(['date'=>'2016-02-23','created_at'=>'2016-02-23 14:12:34']),new Collection(['date'=>'2016-02-28','created_at'=>'2016-02-23 14:15:36'])]);

$dt = Carbon::now();

for ($day = 1; $day <= $dt->daysInMonth; $day++) {

    $date = Carbon::create($dt->year, $dt->month, $day)->format('Y-m-d');

    //filter your timesheets and see if there is one for this day
    $timesheet = $timesheets->filter(function($timesheet) use($date){return $timesheet->get('date')==$date;});

    if(!$timesheet->isEmpty()){
        //if there is a timesheet for today then add it to your $days collection
        $days->push($timesheet);
    }else{
        //otherwise just stick in the date
        $days->push(new Collection([
            'date' => $date,
        ]));
   }
}

//voila!
dd($days);

【讨论】:

  • 谢谢,这将工作。现在我无法让get 处理我的模型:FatalThrowableError in Grammar.php line 107: Type error: Argument 1 passed to Illuminate\Database\Grammar::columnize() must be of the type array, string given
  • 由于您的时间表集合是数据库集合,因此获取方式不同。您将不得不更改过滤器中的测试。您可以尝试转换为数组并使用 laravel array_get('date')
  • 啊……我明白了。这在过滤时适用于我的收藏:if (Carbon::parse($timesheet-&gt;date)-&gt;format('Y-m-d') == $date) {return $timesheet;}。非常感谢您的洞察力!
  • 不用担心。您只需要从过滤器中返回将评估为 true 的内容,因此 return Carbon::parse($timesheet-&gt;date)-&gt;format('Y-m-d') == $date 应该可以工作并且更简洁
【解决方案2】:

我不知道为什么$merged = $timesheets-&gt;merge($days); 只合并了最后一项。也许其他人可以对此有所了解。

但除非有更好的解决方案,否则你可以这样做 -

$merged = array_merge($timesheets-&gt;toArray(), $days-&gt;toArray());

希望这会有所帮助。

【讨论】:

  • 这只是将$days的全部内容附加到$timesheets。
  • 那你想要最后的结果如何?
  • 我想将$days 集合与$timesheet 集合合并,保留$timesheet 集合的值并删除$days 集合中存在的任何重复项。例如。如果$timesheet 已经包含'2016-02-24' 我不想从$days 合并'2016-02-24'。如果我不清楚预期的结果,我深表歉意。
【解决方案3】:

使用merge:

$collection1 = Model1::all();
$collection2 = Model2::all();
$mergedCollection = $collection1->merge($collection2);

Documentation

文档讨论了将它与数组一起使用,但查看method signature 它将采用混合参数。在本地安装的 Laravel 4 项目上测试它对我有用。

【讨论】:

  • 我已经尝试过了,但没有得到想要的结果。我再试一次。
  • 这不能正常工作,因为它会将一个集合中的项目替换为另一个其属性包含相同键的项目。
猜你喜欢
  • 1970-01-01
  • 2017-10-05
  • 2018-07-31
  • 1970-01-01
  • 2021-04-16
  • 2019-12-01
  • 1970-01-01
  • 2017-07-21
  • 1970-01-01
相关资源
最近更新 更多