33
votes

My Laravel pagination output is like laravel pagination used to be, but I need to change the data array for each object. My output is:

Output

As you can see, the data object has 2 items, which I need to change.

My code is:

$items = $this->items()
        ->where('position', '=', null)
        ->paginate(15);

Which returns the user items with pivot table, but I don't like the way the pivot table is shown in the JSON, so I decided to change the items and organize each item with the pivot before the item.

For this purpose, I tried to use foreach

foreach ($items->data as $item)
        {

        }

which giving my an error, for a reason I don't know:

Undefined property: Illuminate\Pagination\LengthAwarePaginator::$data"
status_code: 500

Any help?

12
Tried $items as $item?Abhishek
A modern approach to this would be to use resources: laravel.com/docs/master/eloquent-resourcesAdrian Lynch

12 Answers

111
votes

The paginator's items is a collection. You can grab it and transform the data like so:

$paginator = $this->items()->where('position', '=', null)->paginate(15);
$paginator->getCollection()->transform(function ($value) {
    // Your code here
    return $value;
});

If you are familiar with tap helper here is the snippet that does exact same.

$paginator = tap($this->items()->where('position', '=', null)->paginate(15),function($paginatedInstance){
    return $paginatedInstance->getCollection()->transform(function ($value) {
        return $value;
    });
});

We can't chain method getCollection to paginator instance because AbstractPaginator will return paginator's underlying collection. so the paginator instance will be transformed to Collection. So fix that we can use tap helper.

40
votes

If you'd like to keep items paginated:

        $itemsPaginated = $this->items()
             ->paginate(15);

        $itemsTransformed = $itemsPaginated
            ->getCollection()
            ->map(function($item) {
                return [
                    'id' => $item->id,
                ];
        })->toArray();

        $itemsTransformedAndPaginated = new \Illuminate\Pagination\LengthAwarePaginator(
            $itemsTransformed,
            $itemsPaginated->total(),
            $itemsPaginated->perPage(),
            $itemsPaginated->currentPage(), [
                'path' => \Request::url(),
                'query' => [
                    'page' => $itemsPaginated->currentPage()
                ]
            ]
        );
26
votes

There is a setCollection method for such purpose.

$items = Model::paginate(10);

$updatedItems = $items->getCollection();

// data manipulation
// ...

$items->setCollection($updateItems);

From the source code of /Illuminate/Pagination/AbstractPaginator.php

/**
* Set the paginator's underlying collection.
*
* @param  \Illuminate\Support\Collection  $collection
* @return $this
*/
public function setCollection(Collection $collection)
{
    $this->items = $collection;

    return $this;
}

Source

7
votes

If you want to change or update Laravel pagination output but don't affect pagination then you should follow these instructions.

$items = Model::paginate(10);

$updatedItems = $items->getCollection();

// data manipulation

// ...

$items->setCollection($updateItems);

you can check this from here

3
votes

I could make shorter way. This returns edited $array instead of simple $paginated. This example modify file names. This doc was useful for me.

    $paginated=$query->paginate(12);
    $array=$paginated->toArray();
    foreach ($array['data'] as $r=>$record) {
        $array['data'][$r]->gif=$array['data'][$r]->gif.".gif";
    }
    return $array;
2
votes
getCollection

is one way to get the items. Another way is to use this For ex- Assuming, user doesn't have name param and only have first_name and last_name

$userPaginatedData = User::paginate(15);
$users = $userPaginatedData->items();

foreach($users as $user) {
   $user->name = $user->first_name . ' ' . $user->last_name;
}


return $userPaginatedData;

Now in the data key, you would see that each user has name param with it.

1
votes

-Laravel 5.4

// example update column "photo" 
// from "/path/to/photo.png" 
// to "abc.com/path/to/photo.png"
foreach ($items as $item)
{
    $path = $item->photo;

  // Remove 
  $item->offsetUnset("photo");

  // Set
  $item->offsetSet("photo", url($path));
}
1
votes

Sample Example :

    $franchiseData=[ 'id'=>1 ,'name'=>'PAnkaj'];
    $models = $bookingsQuery->paginate(10);
    $models->setCollection(collect($franchiseData));
    return  $models;

Note that $models->setCollection(collect($franchiseData)); you have to use collect() else you will get error.

0
votes

Laravel AbstractPaginator has methods setCollection() and getCollection()

<?php

$itemsPaginated = $this->items()->paginate(15);
$itemsPaginated->setCollection(
    $itemsPaginated->getCollection()->transform(function ($item) {
       // Your code here
       return $item;
    })
)
-1
votes
<?php 

$itemsPaginated = $this->items()->paginate(15);

$itemsPaginated = json_encode($itemsPaginated);

foreach ($itemsPaginated->data as $key => $item) {
    $results->data[$key]; //Modify
}

$itemsPaginated = json_encode($results);

-9
votes

you have to use below code in your blade

{!! $items->render() !!}
-9
votes

Ignore the pagination in laravel and hit the normal data

foreach ($items as $item)
{

}