【问题标题】:Laravel modify Collection dataLaravel 修改 Collection 数据
【发布时间】:2016-09-28 15:26:47
【问题描述】:

我想知道 Laravel 是否有任何帮助来修改集合。

我需要做的是使用paginate() 进行查询,然后检查登录的用户 ID 是否与发送者或接收者匹配,并在此基础上为输出添加一个新值:

$userId = Auth::guard('api')->user()->user_id;
$allMessages = Conversation::join('users as sender', 'conversations.sender_id', '=', 'sender.user_id')
                               ->join('users as reciver', 'conversations.recipient_id', '=', 'reciver.user_id')
                               ->where('sender_id',$userId)->orWhere('recipient_id',$userId)
                               ->orderBy('last_updated', 'desc')
                               ->select('subject','sender_id','recipient_id', 'sender_unread', 'recipient_unread', 'last_updated', 'reciver.username as receivername', 'sender.username as sendername')
                               ->paginate(20);

现在我想做这样的事情:

if ($allMessages->sender_id == $userId) {
    // add new value to output
    newField = $allMessages->sendername
} else {
    // add new value to output
    newField = $allMessages->receivername
}

然后发送添加了新值的数据

return response()->json(['messages' => $allMessages], 200);

这可能吗?

【问题讨论】:

标签: php laravel mutators


【解决方案1】:

为此,您最好使用 Collection 类的内置函数。例如,map 函数将是完美的。

https://laravel.com/docs/5.3/collections#method-map

$allMessages = $allMessages->map(function ($message, $key) use($userId) {
    if ($message->sender_id == $userId) {
        $message->display_name = $message->receivername;
    } else {
        $message->display_name = $message->sendername;
    }

    return $message;
});

【讨论】:

  • 您也可以考虑通过an accessor进行此操作。
  • transform function 会更好,因为它不会返回新的集合实例,而是修改原始集合。
【解决方案2】:

通过添加解决:

foreach ($allMessages as $message) {
        if ($message->sender_id == $userId) {
            $message->display_name = $message->receivername;
        } else {
            $message->display_name = $message->sendername;
        }
      }

【讨论】:

    【解决方案3】:

    你肯定可以使用laravel的LengthAwarePaginator

    除了集合的总数之外,您还需要传递需要在每个页面上显示的集合数据片段。

    $total_count = $allMessages->count();
    $per_page = 2;
    $current_page = request()->get('page') ?? 1;
    $options = [
        'path' => request()->url(),
        'query' => request()->query(),
    ];
    

    假设您希望每页有 2 个结果,然后先计算偏移量

    $offset = ($current_page - 1) * $per_page;
    

    现在对集合进行切片以获取每页数据

    $per_page_data = $collection->slice($offset, $per_page);
    
    $paginated_data = new LengthAwarePaginator($per_page_data, $total_count, $per_page, $current_page, $options);
    

    $paginated_data 将只有有限数量的由 $per_page 变量声明的项目。

    如果您想要接下来的两个数据片段,则将api_request?page="2" 作为您的网址传递。

    【讨论】:

      【解决方案4】:

      由于我不知道您使用的是哪个 Laravel 版本,所以使用 Laravel 5.2 让我给您一个更聪明的方法来处理这个问题(如果我正确地解决了您的问题)。

      你可以使用 Laravel 的 LengthAwarePaginatior(API Docs)。

      在构建查询时不要使用 paginate 方法,而是使用简单的 get 方法来获取简单的集合。

      $userId = Auth::guard('api')->user()->user_id;
        $allMessages = Conversation::join('users as sender', 'conversations.sender_id', '=', 'sender.user_id')
                                     ->join('users as reciver', 'conversations.recipient_id', '=', 'reciver.user_id')
                                     ->where('sender_id',$userId)->orWhere('recipient_id',$userId)
                                     ->orderBy('last_updated', 'desc')
                                     ->select('subject','sender_id','recipient_id','sender_unread','recipient_unread','last_updated','reciver.username as receivername','sender.username as sendername')
                                     ->get();
      

      现在您可以像这样根据您的特定条件将额外的项目填充到该集合中。

      if ($allMessages->sender_id == $userId ) {
        // add new value to collection
      } else {
        // add new value to collection
      }
      

      现在使用 LengthAwarePaginator 将填充的集合转换为分页集合。

      $total_count = $allMessages->count();
      $limit = 20;
      $current_page = request()->get('page');
      $options = [
          'path' => request()->url(),
          'query' => request()->query(),
      ];
      $paginated_collection = new LengthAwarePaginator($allMessages, $total_count, $limit, $current_page, $options);
      

      变量$paginated_collection 现在可用于发送响应。希望这可以帮助您解决问题。

      【讨论】:

      • 在构建查询时我不应该使用分页的任何原因?
      • 它不起作用,“total”:22,“per_page”:20,“from”:1,“to”:22,它应该将结果限制为 20,但我仍然得到 22从结果
      • @user2636197 paginate() 方法返回类型为 \Illuminate\Contracts\Pagination\LengthAwarePaginator 的结果,您不能在该结果上使用某些收集方法来处理结果数据。这就是为什么让数据处理更容易我采取的结果是 Laravel 集合的形式而不是 LengthAwarePaginator。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-08-18
      • 1970-01-01
      • 2018-03-20
      • 2021-07-23
      • 2017-06-02
      • 1970-01-01
      • 2021-11-24
      相关资源
      最近更新 更多