Laravel cursorPaginate without visible ID field. (InvalidArgumentException Illegal operator and value combination.)

Viewed 559

How can I implement Laravel's cursor paginator without returning the id column in the collection?

The following query:

'users' => User::cursorPaginate(15)

returns the individual users like this:

{
    "id": 1,
    "uuid": "376bec76-9095-4510-a5ba-fea0f234c6cf",
    "username": "alexanderhorner",
    "password": "$2y$12$qMITOdMr2XdAq3EMKwc/WeB/db9IaQdkZ5egqY7CX5WpUwwHLKOLK"
}

Now, lets say I have an API. I want api/v1/user to return the same paginated results using cursorPaginate(), but I don't want to return the id column.

'users' => User::select('uuid', 'username')->cursorPaginate(15)

would return an error though, since cursorPaginate() needs the ID column or something similar:

InvalidArgumentException
Illegal operator and value combination.

What's the best way to fix this? Filter the collection returned by cursorPaginate()?

2 Answers

You can also check the cursorPaginate implementation (and signature) inside Builder.php. There is a parameter columns. Check it out:

/**
 * Get a paginator only supporting simple next and previous links.
 *
 * This is more efficient on larger data-sets, etc.
 *
 * @param  int|null  $perPage
 * @param  array  $columns
 * @param  string  $cursorName
 * @param  \Illuminate\Pagination\Cursor|string|null  $cursor
 * @return \Illuminate\Contracts\Pagination\CursorPaginator
 */
public function cursorPaginate($perPage = 15, $columns = ['*'], $cursorName = 'cursor', $cursor = null)
{
    return $this->paginateUsingCursor($perPage, $columns, $cursorName, $cursor);
}

You can map the Users Collection of Models before return as response.

By doing the following you map the properties you want in a new variable called $users_to_be_returned and you return this in a property in your reponse.

You can do whatever with your structure of response with arrays, stdClass or even better DTO's.

$users = User::cursorPaginate(10);

$users_dtos = collect($users->items())->map(function ($user) {
    $user_dto = new UserDTO(); // or even an stdClass object
    $user_dto->username = $user->username;
    $user_dto->password = $user->password;

    return $user_dto;
})->toArray();

$response = new UserResponseDTO();
$response->users = $users_dtos;

$response->pagination_info = new PaginationInfoDTO();
$response->pagination_info->per_page = $users->perPage();
$response->pagination_info->path = $users->path();
$response->pagination_info->next_cursor = $users->nextCursor()->parameter('users.id');
$response->pagination_info->next_page_url = $users->nextPageUrl() ? $users->nextPageUrl() : null;
$response->pagination_info->previous_cursor = $users->previousCursor() ? $users->previousCursor()->parameter('users.id') : null;
$response->pagination_info->prev_page_url = $users->previousPageUrl() ? $users->previousPageUrl() : null;

return response()->json($response);
Related