saintsystems / odata-client-php

OData Client Library for PHP
MIT License
142 stars 101 forks source link

Messed up return types #83

Open mcinp opened 3 years ago

mcinp commented 3 years ago

ODataClient::get() is described in phpdoc as returning IODataRequest object. This method further calls ODataClient::request() (the same @return IODataRequest object description).

What gets called in the end is \SaintSystems\OData\ODataRequest::execute() which is described as @return mixed object or array of objects of class $returnType

So when I want to iterate over the results with foreach, I get proper code execution, but phpstan correctly complains:

Argument of an invalid type SaintSystems\OData\IODataRequest supplied for foreach, only iterables are supported.

Please provide consistent return type hinting...

hesa2020 commented 2 years ago

+1 on this, I am also having this issue using version ^0.6.0.

My request returns me an array so I am unable to retrieve the SkipToken to take more than 1000 results.

EDIT: Adding self::$odataClient->setEntityReturnType(false); before my ->get allowed me to get the full 'SaintSystems\OData\ODataResponse' object.

anderly commented 1 year ago

@hesa2020, @Involture

Please take a look at PR142 and feel free to pull down the source branch feature/paging-with-lazycollection which adds support for native paging over the paginated OData response using LazyCollection via new cursor methods on the Builder and ODataClient.

Using the new cursor method on the Builder, you can page through the paginated response like so:

    // Request 8 records per page (library default is 25)
    $odataClient = new ODataClient('https://services.odata.org/V4/TripPinService', function($request) {
        $request->headers[RequestHeader::PREFER] = Constants::ODATA_MAX_PAGE_SIZE . '=' . 8;
    })

    // Or, using the new 'pageSize' method on the Builder
    $data = $odataClient->from('People')->pageSize(8)->cursor();

    $totalRecordCount = $data->count(); // Will return 20, which is the total number of 'Person' records in the Person EntitySet

    $firstPerson = $data->first(); // Will return the first person in the EntitySet (Russell Whyte)
    $lastPerson = $data->last(); // Will return the last person in the EntitySet (Krista Kemp, from page 3 of the paginated results)

    // Skip the first 8 records (page 1) and get the first person on page 2 (the 9th Person)
    // This will issue a request to the second page in order to obtain the 9th person in the EntitySet (Marshall Garay)
    $ninthPerson = $data->skip(8)->first();

Still doing some additional review and testing, but wanted to get some feedback before merging.