22
33A fluent library for calling OData REST services inspired by and based on the [ Laravel Query Builder] ( https://laravel.com/docs/5.4/queries ) .
44
5- * This library is currently in preview. Please continue to provide [ feedback] ( https://github.com/saintsystems/odata-client-php/issues/new ) as we iterate towards a production-supported library.*
6-
75[ ![ Build Status] ( https://github.com/saintsystems/odata-client-php/actions/workflows/ci.yml/badge.svg )] ( https://github.com/saintsystems/odata-client-php/actions/workflows/ci.yml )
86[ ![ Latest Version on Packagist] ( https://img.shields.io/packagist/v/saintsystems/odata-client.svg?style=flat-square )] ( https://packagist.org/packages/saintsystems/odata-client )
97[ ![ Total Downloads] ( https://img.shields.io/packagist/dt/saintsystems/odata-client.svg?style=flat-square )] ( https://packagist.org/packages/saintsystems/odata-client )
@@ -20,6 +18,8 @@ composer require saintsystems/odata-client
2018
2119Starting from version 0.10.0, the OData Client requires an HTTP provider to be explicitly set. This allows you to use any HTTP client implementation that suits your needs.
2220
21+ As of version 1.0.0, we will be using [ semver] ( https://semver.org/ ) .
22+
2323#### Using Guzzle (recommended for most users)
2424
2525First, install Guzzle:
@@ -156,7 +156,7 @@ $people = $odataClient->from('People')
156156 ->get();
157157// Results in: /People?timeout=30&format=minimal
158158
159- // Method 2: Add custom options using array format
159+ // Method 2: Add custom options using array format
160160$people = $odataClient->from('People')
161161 ->addOption(['timeout' => '30', 'debug' => 'true'])
162162 ->get();
@@ -201,12 +201,12 @@ use SaintSystems\OData\GuzzleHttpProvider;
201201
202202class CustomTimeoutODataClient extends ODataClient {
203203 private $customTimeout;
204-
204+
205205 public function __construct($baseUrl, $authProvider = null, $httpProvider = null, $timeout = 30) {
206206 parent::__construct($baseUrl, $authProvider, $httpProvider);
207207 $this->customTimeout = $timeout;
208208 }
209-
209+
210210 protected function createRequest($method, $requestUri) {
211211 $request = parent::createRequest($method, $requestUri);
212212 $request->setTimeout($this->customTimeout);
@@ -309,15 +309,15 @@ $people = $client->select('UserName,FirstName,LastName,AddressInfo')
309309
310310foreach ($people as $person) {
311311 echo "Person: " . $person->FirstName . " " . $person->LastName . "\n";
312-
312+
313313 // Access nested address info - remains as array for easy filtering
314314 $addresses = $person->AddressInfo;
315-
315+
316316 // Filter addresses by type
317317 $homeAddresses = array_filter($addresses, function($address) {
318318 return isset($address['Type']) && $address['Type'] === 'Home';
319319 });
320-
320+
321321 // Access properties within filtered results
322322 foreach ($homeAddresses as $address) {
323323 // Convert to Entity for object-style access
@@ -341,26 +341,26 @@ $folders = $client->select('Id,Name,CreatorNameShort,Info,Info/IsAHomeFolder,Chi
341341foreach ($folders as $folder) {
342342 echo "Folder: " . $folder->Name . "\n";
343343 echo "Creator: " . $folder->CreatorNameShort . "\n";
344-
344+
345345 // Access nested Info properties
346346 if ($folder->Info) {
347347 echo "Is Home Folder: " . ($folder->Info->IsAHomeFolder ? 'Yes' : 'No') . "\n";
348-
348+
349349 // Safe navigation for optional nested properties
350350 if ($folder->hasProperty('Info.Settings.Theme')) {
351351 echo "Theme: " . $folder->getProperty('Info.Settings.Theme') . "\n";
352352 }
353353 }
354-
354+
355355 // Work with Children collection
356356 if ($folder->Children) {
357357 echo "Children:\n";
358-
358+
359359 // Filter children by type
360360 $subfolders = array_filter($folder->Children, function($child) {
361361 return $child['FileSizeBytes'] == 0; // Folders have 0 file size
362362 });
363-
363+
364364 foreach ($subfolders as $subfolder) {
365365 echo " - " . $subfolder['Name'] . " (ID: " . $subfolder['Id'] . ")\n";
366366 }
@@ -443,7 +443,7 @@ $peopleWithAllHighBudgetTrips = $client->from('People')
443443#### Available Lambda Methods
444444
445445- ` whereAny($navigationProperty, $callback) ` - Returns true if any element matches the condition
446- - ` whereAll($navigationProperty, $callback) ` - Returns true if all elements match the condition
446+ - ` whereAll($navigationProperty, $callback) ` - Returns true if all elements match the condition
447447- ` orWhereAny($navigationProperty, $callback) ` - OR version of whereAny
448448- ` orWhereAll($navigationProperty, $callback) ` - OR version of whereAll
449449
@@ -495,7 +495,7 @@ $client = new ODataClient('https://services.odata.org/V4/TripPinService', null,
495495// Simple batch with multiple GET requests
496496$response = $client->batch()
497497 ->get('People', 'get-people')
498- ->get('Airlines', 'get-airlines')
498+ ->get('Airlines', 'get-airlines')
499499 ->get('Airports', 'get-airports')
500500 ->execute();
501501```
@@ -530,13 +530,13 @@ You can combine individual requests and changesets in a single batch:
530530$response = $client->batch()
531531 // Individual queries (not in changeset)
532532 ->get('People?$top=5', 'get-top-people')
533-
533+
534534 // Atomic operations in changeset
535535 ->startChangeset()
536536 ->post('People', $newPersonData, 'create-person')
537537 ->delete('People(\'obsolete-id\')', 'delete-person')
538538 ->endChangeset()
539-
539+
540540 // More individual queries
541541 ->get('Airlines?$top=3', 'get-airlines')
542542 ->execute();
0 commit comments