Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

(regression) Impossilbe to use JsonResource::collection with paginated query (not eloquent) #29916

Closed
LastDragon-ru opened this issue Sep 9, 2019 · 20 comments

Comments

@LastDragon-ru
Copy link
Contributor

LastDragon-ru commented Sep 9, 2019

  • Laravel Version: 5.8.35
  • PHP Version: 7.2.5
  • Database Driver & Version: Mysq 5.7

Description:

Laravel 5.8.34:

function actionWithoutPaginate() {
    $result = DB::query(...difficult query where is not possible to use eloquent...)->get(); 

    return CustomResource::collection($result);
}

function actionWithPaginate() {
    $result = DB::query(...dificult query where is not possible to use eloquent...)->paginate();

    return CustomResource::collection($result);
}

class CustomResource extends Resource {
    /**
     * Transform the resource into an array.
     *
     * @param \Illuminate\Http\Request
     *
     * @return array
     */
    public function toArray($request) {
        $image = get_object_vars($this->resource);

        if (isset($image['last_changed'])) {
            $service = app()->make(MyService::class);
            $format  = $service->getConnection()->getQueryGrammar()->getDateFormat();
            $carbon  = Carbon::createFromFormat($format, $image['last_changed']);

            $image['last_changed'] = $carbon;
        }

        return $image;
    }
}

Since 5.8.35:

  • actionWithoutPaginate - works fine
  • actionWithPaginate - broken
    [2019-09-09 08:08:55] testing.ERROR: Cannot use object of type stdClass as array {"exception":"[object] (Symfony\\Component\\Debug\\Exception\\FatalThrowableError(code: 0): Cannot use object of type stdClass as array at vendor\\laravel\\framework\\src\\Illuminate\\Http\\Resources\\DelegatesToResource.php:53)
    [stacktrace]
    #0 vendor\\laravel\\framework\\src\\Illuminate\\Support\\Arr.php(148): Illuminate\\Http\\Resources\\Json\\JsonResource->offsetExists('resource')
    #1 vendor\\laravel\\framework\\src\\Illuminate\\Support\\helpers.php(524): Illuminate\\Support\\Arr::exists(Object(Yggdrasil\\Http\\Http\\Resources\\ObjectResource), 'resource')
    #2 vendor\\laravel\\framework\\src\\Illuminate\\Support\\Arr.php(387): data_get(Object(Yggdrasil\\Http\\Http\\Resources\\ObjectResource), Array)
    #3 vendor\\laravel\\framework\\src\\Illuminate\\Support\\Collection.php(1107): Illuminate\\Support\\Arr::pluck(Array, Array, NULL)
    #4 vendor\\laravel\\framework\\src\\Illuminate\\Support\\Traits\\ForwardsCalls.php(23): Illuminate\\Support\\Collection->pluck('resource')
    #5 vendor\\laravel\\framework\\src\\Illuminate\\Pagination\\AbstractPaginator.php(647): Illuminate\\Pagination\\AbstractPaginator->forwardCallTo(Object(Illuminate\\Support\\Collection), 'pluck', Array)
    #6 vendor\\laravel\\framework\\src\\Illuminate\\Http\\Resources\\Json\\PaginatedResourceResponse.php(28): Illuminate\\Pagination\\AbstractPaginator->__call('pluck', Array)
    #7 vendor\\laravel\\framework\\src\\Illuminate\\Support\\helpers.php(1124): Illuminate\\Http\\Resources\\Json\\PaginatedResourceResponse->Illuminate\\Http\\Resources\\Json\\{closure}(Object(Illuminate\\Http\\JsonResponse))
    #8 vendor\\laravel\\framework\\src\\Illuminate\\Http\\Resources\\Json\\PaginatedResourceResponse.php(31): tap(Object(Illuminate\\Http\\JsonResponse), Object(Closure))
    #9 vendor\\laravel\\framework\\src\\Illuminate\\Http\\Resources\\Json\\ResourceCollection.php(71): Illuminate\\Http\\Resources\\Json\\PaginatedResourceResponse->toResponse(Object(Illuminate\\Http\\Request))
    #10 vendor\\laravel\\framework\\src\\Illuminate\\Routing\\Router.php(733): Illuminate\\Http\\Resources\\Json\\ResourceCollection->toResponse(Object(Illuminate\\Http\\Request))
    #11 vendor\\laravel\\framework\\src\\Illuminate\\Routing\\Router.php(720): Illuminate\\Routing\\Router::toResponse(Object(Illuminate\\Http\\Request), Object(Yggdrasil\\Http\\Http\\Resources\\ResourceCollection))
    #12 vendor\\laravel\\framework\\src\\Illuminate\\Routing\\Router.php(680): Illuminate\\Routing\\Router->prepareResponse(Object(Illuminate\\Http\\Request), Object(Yggdrasil\\Http\\Http\\Resources\\ResourceCollection))
    #13 vendor\\laravel\\framework\\src\\Illuminate\\Routing\\Pipeline.php(30): Illuminate\\Routing\\Router->Illuminate\\Routing\\{closure}(Object(Illuminate\\Http\\Request))
    #14 app\\Http\\Middleware\\CheckClientCredentials.php(29): Illuminate\\Routing\\Pipeline->Illuminate\\Routing\\{closure}(Object(Illuminate\\Http\\Request))
    #15 vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php(163): App\\Http\\Middleware\\CheckClientCredentials->handle(Object(Illuminate\\Http\\Request), Object(Closure), 'marinexprocurem...')
    #16 vendor\\laravel\\framework\\src\\Illuminate\\Routing\\Pipeline.php(53): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}(Object(Illuminate\\Http\\Request))
    #17 vendor\\laravel\\framework\\src\\Illuminate\\Routing\\Middleware\\SubstituteBindings.php(41): Illuminate\\Routing\\Pipeline->Illuminate\\Routing\\{closure}(Object(Illuminate\\Http\\Request))
    #18 vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php(163): Illuminate\\Routing\\Middleware\\SubstituteBindings->handle(Object(Illuminate\\Http\\Request), Object(Closure))
    #19 vendor\\laravel\\framework\\src\\Illuminate\\Routing\\Pipeline.php(53): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}(Object(Illuminate\\Http\\Request))
    #20 vendor\\laravel\\framework\\src\\Illuminate\\Routing\\Middleware\\ThrottleRequests.php(58): Illuminate\\Routing\\Pipeline->Illuminate\\Routing\\{closure}(Object(Illuminate\\Http\\Request))
    #21 vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php(163): Illuminate\\Routing\\Middleware\\ThrottleRequests->handle(Object(Illuminate\\Http\\Request), Object(Closure), 600, '1')
    #22 vendor\\laravel\\framework\\src\\Illuminate\\Routing\\Pipeline.php(53): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}(Object(Illuminate\\Http\\Request))
    #23 vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php(104): Illuminate\\Routing\\Pipeline->Illuminate\\Routing\\{closure}(Object(Illuminate\\Http\\Request))
    #24 vendor\\laravel\\framework\\src\\Illuminate\\Routing\\Router.php(682): Illuminate\\Pipeline\\Pipeline->then(Object(Closure))
    #25 vendor\\laravel\\framework\\src\\Illuminate\\Routing\\Router.php(657): Illuminate\\Routing\\Router->runRouteWithinStack(Object(Illuminate\\Routing\\Route), Object(Illuminate\\Http\\Request))
    #26 vendor\\laravel\\framework\\src\\Illuminate\\Routing\\Router.php(623): Illuminate\\Routing\\Router->runRoute(Object(Illuminate\\Http\\Request), Object(Illuminate\\Routing\\Route))
    #27 vendor\\laravel\\framework\\src\\Illuminate\\Routing\\Router.php(612): Illuminate\\Routing\\Router->dispatchToRoute(Object(Illuminate\\Http\\Request))
    #28 vendor\\laravel\\framework\\src\\Illuminate\\Foundation\\Http\\Kernel.php(176): Illuminate\\Routing\\Router->dispatch(Object(Illuminate\\Http\\Request))
    #29 vendor\\laravel\\framework\\src\\Illuminate\\Routing\\Pipeline.php(30): Illuminate\\Foundation\\Http\\Kernel->Illuminate\\Foundation\\Http\\{closure}(Object(Illuminate\\Http\\Request))
    #30 vendor\\fideloper\\proxy\\src\\TrustProxies.php(57): Illuminate\\Routing\\Pipeline->Illuminate\\Routing\\{closure}(Object(Illuminate\\Http\\Request))
    #31 vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php(163): Fideloper\\Proxy\\TrustProxies->handle(Object(Illuminate\\Http\\Request), Object(Closure))
    #32 vendor\\laravel\\framework\\src\\Illuminate\\Routing\\Pipeline.php(53): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}(Object(Illuminate\\Http\\Request))
    #33 vendor\\laravel\\framework\\src\\Illuminate\\Foundation\\Http\\Middleware\\TransformsRequest.php(21): Illuminate\\Routing\\Pipeline->Illuminate\\Routing\\{closure}(Object(Illuminate\\Http\\Request))
    #34 vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php(163): Illuminate\\Foundation\\Http\\Middleware\\TransformsRequest->handle(Object(Illuminate\\Http\\Request), Object(Closure))
    #35 vendor\\laravel\\framework\\src\\Illuminate\\Routing\\Pipeline.php(53): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}(Object(Illuminate\\Http\\Request))
    #36 vendor\\laravel\\framework\\src\\Illuminate\\Foundation\\Http\\Middleware\\TransformsRequest.php(21): Illuminate\\Routing\\Pipeline->Illuminate\\Routing\\{closure}(Object(Illuminate\\Http\\Request))
    #37 vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php(163): Illuminate\\Foundation\\Http\\Middleware\\TransformsRequest->handle(Object(Illuminate\\Http\\Request), Object(Closure))
    #38 vendor\\laravel\\framework\\src\\Illuminate\\Routing\\Pipeline.php(53): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}(Object(Illuminate\\Http\\Request))
    #39 vendor\\laravel\\framework\\src\\Illuminate\\Foundation\\Http\\Middleware\\ValidatePostSize.php(27): Illuminate\\Routing\\Pipeline->Illuminate\\Routing\\{closure}(Object(Illuminate\\Http\\Request))
    #40 vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php(163): Illuminate\\Foundation\\Http\\Middleware\\ValidatePostSize->handle(Object(Illuminate\\Http\\Request), Object(Closure))
    #41 vendor\\laravel\\framework\\src\\Illuminate\\Routing\\Pipeline.php(53): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}(Object(Illuminate\\Http\\Request))
    #42 vendor\\laravel\\framework\\src\\Illuminate\\Foundation\\Http\\Middleware\\CheckForMaintenanceMode.php(62): Illuminate\\Routing\\Pipeline->Illuminate\\Routing\\{closure}(Object(Illuminate\\Http\\Request))
    #43 vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php(163): Illuminate\\Foundation\\Http\\Middleware\\CheckForMaintenanceMode->handle(Object(Illuminate\\Http\\Request), Object(Closure))
    #44 vendor\\laravel\\framework\\src\\Illuminate\\Routing\\Pipeline.php(53): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}(Object(Illuminate\\Http\\Request))
    #45 vendor\\laravel\\framework\\src\\Illuminate\\Http\\Middleware\\FrameGuard.php(18): Illuminate\\Routing\\Pipeline->Illuminate\\Routing\\{closure}(Object(Illuminate\\Http\\Request))
    #46 vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php(163): Illuminate\\Http\\Middleware\\FrameGuard->handle(Object(Illuminate\\Http\\Request), Object(Closure))
    #47 vendor\\laravel\\framework\\src\\Illuminate\\Routing\\Pipeline.php(53): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}(Object(Illuminate\\Http\\Request))
    #48 packages\\yggdrasil-core\\src\\Http\\Http\\Middleware\\Cors.php(25): Illuminate\\Routing\\Pipeline->Illuminate\\Routing\\{closure}(Object(Illuminate\\Http\\Request))
    #49 vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php(163): Yggdrasil\\Http\\Http\\Middleware\\Cors->handle(Object(Illuminate\\Http\\Request), Object(Closure))
    #50 vendor\\laravel\\framework\\src\\Illuminate\\Routing\\Pipeline.php(53): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}(Object(Illuminate\\Http\\Request))
    #51 packages\\yggdrasil-core\\src\\Http\\Http\\Middleware\\ForceWantsJson.php(22): Illuminate\\Routing\\Pipeline->Illuminate\\Routing\\{closure}(Object(Illuminate\\Http\\Request))
    #52 vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php(163): Yggdrasil\\Http\\Http\\Middleware\\ForceWantsJson->handle(Object(Illuminate\\Http\\Request), Object(Closure))
    #53 vendor\\laravel\\framework\\src\\Illuminate\\Routing\\Pipeline.php(53): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}(Object(Illuminate\\Http\\Request))
    #54 vendor\\itsgoingd\\clockwork\\Clockwork\\Support\\Laravel\\ClockworkMiddleware.php(27): Illuminate\\Routing\\Pipeline->Illuminate\\Routing\\{closure}(Object(Illuminate\\Http\\Request))
    #55 vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php(163): Clockwork\\Support\\Laravel\\ClockworkMiddleware->handle(Object(Illuminate\\Http\\Request), Object(Closure))
    #56 vendor\\laravel\\framework\\src\\Illuminate\\Routing\\Pipeline.php(53): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}(Object(Illuminate\\Http\\Request))
    #57 vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php(104): Illuminate\\Routing\\Pipeline->Illuminate\\Routing\\{closure}(Object(Illuminate\\Http\\Request))
    #58 vendor\\laravel\\framework\\src\\Illuminate\\Foundation\\Http\\Kernel.php(151): Illuminate\\Pipeline\\Pipeline->then(Object(Closure))
    #59 vendor\\laravel\\framework\\src\\Illuminate\\Foundation\\Http\\Kernel.php(116): Illuminate\\Foundation\\Http\\Kernel->sendRequestThroughRouter(Object(Illuminate\\Http\\Request))
    #60 vendor\\laravel\\framework\\src\\Illuminate\\Foundation\\Testing\\Concerns\\MakesHttpRequests.php(375): Illuminate\\Foundation\\Http\\Kernel->handle(Object(Illuminate\\Http\\Request))
    #61 vendor\\laravel\\framework\\src\\Illuminate\\Foundation\\Testing\\Concerns\\MakesHttpRequests.php(347): Illuminate\\Foundation\\Testing\\TestCase->call('GET', '/api/v1/MarineX...', Array, Array, Array, Array, '[]')
    #62 tests\\Feature\\Api\\v1\\MarineXProcurement\\RecipesControllerTest.php(75): Illuminate\\Foundation\\Testing\\TestCase->json('GET', '/api/v1/MarineX...')
    #63 vendor\\phpunit\\phpunit\\src\\Framework\\TestCase.php(1154): Tests\\Feature\\Api\\v1\\MarineXProcurement\\RecipesControllerTest->testIndex()
    #64 vendor\\phpunit\\phpunit\\src\\Framework\\TestCase.php(842): PHPUnit\\Framework\\TestCase->runTest()
    #65 vendor\\phpunit\\phpunit\\src\\Framework\\TestResult.php(693): PHPUnit\\Framework\\TestCase->runBare()
    #66 vendor\\phpunit\\phpunit\\src\\Framework\\TestCase.php(796): PHPUnit\\Framework\\TestResult->run(Object(Tests\\Feature\\Api\\v1\\MarineXProcurement\\RecipesControllerTest))
    #67 vendor\\phpunit\\phpunit\\src\\Framework\\TestSuite.php(746): PHPUnit\\Framework\\TestCase->run(Object(PHPUnit\\Framework\\TestResult))
    #68 vendor\\phpunit\\phpunit\\src\\TextUI\\TestRunner.php(652): PHPUnit\\Framework\\TestSuite->run(Object(PHPUnit\\Framework\\TestResult))
    #69 vendor\\phpunit\\phpunit\\src\\TextUI\\Command.php(206): PHPUnit\\TextUI\\TestRunner->doRun(Object(PHPUnit\\Framework\\TestSuite), Array, true)
    #70 vendor\\phpunit\\phpunit\\src\\TextUI\\Command.php(162): PHPUnit\\TextUI\\Command->run(Array, true)
    #71 vendor\\phpunit\\phpunit\\phpunit(61): PHPUnit\\TextUI\\Command::main()
    #72 {main}
    "} 
    

Related to #29858, #29860

@stsepelin
Copy link

stsepelin commented Sep 11, 2019

Laravel Version: 6.0.3
PHP Version: 7.3.4
Database Driver & Version: Mysq 8.0.15

Same error with DB::table()->selectRaw()->paginate() and JsonResource::collection().

@Lloople
Copy link
Contributor

Lloople commented Sep 12, 2019

Yes, I'm experiencing the same problem.

Any workaround? I can't update to Laravel 6 because of this. Is there any simple way of returning the same payload as the JsonResource would?

@LastDragon-ru
Copy link
Contributor Author

Any workaround?

For php 7.2/7.3 you can just copy offsetExists from v5.8.34:

class CustomResource extends Resource {
    public function toArray(...) {}

    public function offsetExists($offset) {
        return array_key_exists($offset, $this->resource);
    }
}

@Lloople
Copy link
Contributor

Lloople commented Sep 12, 2019

Thanks I’ll give it a try. Why only PHP 7.2 & 7.3 though?

Implementing ArrayAccess was not an option as suggested in other issues since I’m returning a LengthAwarePaginator of a raw query, I don’t want to iterate over them just to create a new object 😅

@LastDragon-ru
Copy link
Contributor Author

Why only PHP 7.2 & 7.3 though?

Seems array_key_exists deprecated for objects in 7.4 (but I'm on 7.2 now and not 100% sure...)

@ppeinsold
Copy link

Have the same issue after upgrading from 5.7 to 5.8
I use a ResourceCollection and tried the fix of @LastDragon-ru but it did not work.
I followed the stack trace and ended up in the illuminate/Support/helpers.php at line 1124
$callback($value);

I do not really know what to do now. Has anyone a workaround for this? Will this be fixed in future laravel solutions?
Thx

@ppeinsold
Copy link

ppeinsold commented Sep 16, 2019

Ok, I found the solution to my problem.
In my Controller I did the following return:
return new LeaderboardResourceCollection($paginatedData);
$paginatedData is a LengthAwarePaginator. I changed the return into:
return response(new LeaderboardResourceCollection($paginatedData));
and now it works.
Don't ask me why it did work prior the update to 5.8...

@driesvints
Copy link
Member

driesvints commented Oct 4, 2019

This works for me on a fresh Laravel 5.8 installation:

<?php

namespace App\Http\Resources;

use Illuminate\Http\Resources\Json\JsonResource;

class CustomResource extends JsonResource
{
    /**
     * Transform the resource into an array.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return array
     */
    public function toArray($request)
    {
        return parent::toArray($request);
    }
}
Route::get('/', function () {
    $result = \DB::table('users')->paginate();

    return \App\Http\Resources\CustomResource::collection($result);
});

Since this has been fixed as well in Laravel 6.0 I want to ask you all to upgrade please. Thanks.

@LastDragon-ru
Copy link
Contributor Author

This works for me on a fresh Laravel 5.8 installation:

@driesvints , I guess your users table is empty - just add few records and it will fail. In 5.8.35 and 6.0.2. Could you please reopen this issue?

use Illuminate\Http\Resources\Json\JsonResource;
use Illuminate\Support\Facades\DB;

class CustomResource extends JsonResource
{
    /**
     * Transform the resource into an array.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return array
     */
    public function toArray($request)
    {
        return get_object_vars($this->resource);
    }

//    Uncomment to fix
//    public function offsetExists($offset) {
//        return array_key_exists($offset, $this->resource);
//    }
}

Route::get('/', function () {
    DB::table('users')->insert([
        'name'  => 'test',
        'email' => "test-".Str::random(10)."@example.com",
        'password' => '',
    ]);

    $result = DB::table('users')->paginate();

    return CustomResource::collection($result);
});

image

@driesvints
Copy link
Member

@LastDragon-ru it wasn't empty

@LastDragon-ru
Copy link
Contributor Author

@driesvints , mmmm... maybe related to fetch mode and/or database? Because JsonResource::toArray() should fails if resource is stdClass (this is why I used get_object_vars).

public function toArray($request)
{
if (is_null($this->resource)) {
return [];
}
return is_array($this->resource)
? $this->resource
: $this->resource->toArray();
}

image

@stsepelin
Copy link

PHP 7.3.9
MySql 8.0.15
Laravel 6.1.0

@driesvints Problem still exists

@Lloople
Copy link
Contributor

Lloople commented Oct 7, 2019

I can confirm this issue is still present.

PHP 7.2
Mysql 5.7
Laravel 6.1.0

return SearchUserResource::collection(
    DB::table(DB::raw("weird query with unions"))->paginate(10)
);

We ended up adding this lines to our Resource

/**
 * This method is necessary just to preserve backward compatibility with non-Eloquent resources.
 * The objects inside a JsonResource now must implement ArrayAccess. This means you cannot create a Resource
 * of a Collection of plain objects like we're doing here with a RAW Query.
 * 
 * We're applying the changes suggested by Graham Campbell in #29860.
 * 
 * More information 
 *      https://github.com/laravel/framework/issues/29916
 *      https://github.com/laravel/framework/issues/29858
 *      https://github.com/laravel/framework/pull/29860 
 */
public function offsetExists($offset) 
{
    return (is_array($offset) || $offset instanceof ArrayAccess) && isset($this->resource[$offset]);
}

@driesvints
Copy link
Member

@LastDragon-ru I just realized this can't possible work because resources are eloquent specific. We don't support using it with the query builder. Because stdClass doesn't implements array access it doesn't work like that. See https://laravel.com/docs/6.x/eloquent-resources

@stsepelin @Lloople Please see the above note.

@Lloople
Copy link
Contributor

Lloople commented Oct 7, 2019

It's good for me, I just found a solution in minutes thanks to @GrahamCampbell, but I would appreciate a warning about this in the upgrade guide at the time or a clarification in the documentation 😅.

Another inoffensive and naive question: If they were compatible with non-eloquent objects before, why removing that compatibility?

@driesvints
Copy link
Member

@Lloople we didn't add an notice to the upgrade guide because there weren't breaking changes.

If they were compatible with non-eloquent objects before, why removing that compatibility?

We had to make some adjustments for PHP 7.4 (see #29842). Unfortunately that removed the accidental support for the query builder.

Btw, nothing says that we can't look into making it compatible again but that's a discussion for the ideas repo.

@Nilanth
Copy link

Nilanth commented Oct 31, 2019

This issue is not fixed
Laravel 6.4
PHP 7.3
psql (PostgreSQL) 9.5.10

@devcircus
Copy link
Contributor

@Nilanth See the comment directly above yours. Nothing to fix but could be discussed in the ideas repo.

kevinpijning added a commit to kevinpijning/framework that referenced this issue Mar 3, 2020
Restores php 7.4 compatibility for paginator resources that receives objects (for example from the query builder) instead of models.

Fixes laravel#31703 and  laravel#29916
@SalemCode8
Copy link

SalemCode8 commented Jun 29, 2020

to fix this issue if faced you for php 7.4 :

public function offsetExists($offset) {
    return property_exists($this->resource, $offset);
}

and i think it must be like this in laravel files:

public function offsetExists($offset){
    return is_array($this->resource) ? isset($this->resource[$offset]) : property_exists($this->resource, $offset);
 }

I'm just saying

rootpd pushed a commit to remp2020/remp that referenced this issue Sep 30, 2020
- bug: laravel/framework#29916
- JSON API paginations were broken, (e.g. /api/banners)
@zarpio
Copy link

zarpio commented Mar 16, 2021

This works for me on a fresh Laravel 5.8 installation:

<?php

namespace App\Http\Resources;

use Illuminate\Http\Resources\Json\JsonResource;

class CustomResource extends JsonResource
{
    /**
     * Transform the resource into an array.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return array
     */
    public function toArray($request)
    {
        return parent::toArray($request);
    }
}
Route::get('/', function () {
    $result = \DB::table('users')->paginate();

    return \App\Http\Resources\CustomResource::collection($result);
});

Since this has been fixed as well in Laravel 6.0 I want to ask you all to upgrade please. Thanks.

Not working in Laravel 7.3 :-(

rootpd pushed a commit to remp2020/laravel-helpers that referenced this issue Jun 23, 2023
- bug: laravel/framework#29916
- JSON API paginations were broken, (e.g. /api/banners)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

9 participants