1
+ <?php
2
+
3
+ /**
4
+ * OData Batch Operations Examples
5
+ *
6
+ * This example demonstrates how to use batch operations with the OData Client for PHP.
7
+ * Batch operations allow you to send multiple requests in a single HTTP request,
8
+ * which can significantly improve performance when making multiple OData operations.
9
+ */
10
+
11
+ require_once '../vendor/autoload.php ' ;
12
+
13
+ use SaintSystems \OData \ODataClient ;
14
+ use SaintSystems \OData \GuzzleHttpProvider ;
15
+
16
+ // Initialize the OData client
17
+ $ httpProvider = new GuzzleHttpProvider ();
18
+ $ client = new ODataClient ('https://services.odata.org/V4/TripPinService ' , null , $ httpProvider );
19
+
20
+ echo "=== OData Batch Operations Examples === \n\n" ;
21
+
22
+ // Example 1: Simple Batch with Multiple GET Requests
23
+ echo "1. Simple Batch with Multiple GET Requests \n" ;
24
+ echo "-------------------------------------------- \n" ;
25
+
26
+ try {
27
+ $ response = $ client ->batch ()
28
+ ->get ('People ' , 'get-people ' )
29
+ ->get ('Airlines ' , 'get-airlines ' )
30
+ ->get ('Airports ' , 'get-airports ' )
31
+ ->execute ();
32
+
33
+ echo "✓ Batch with multiple GET requests executed successfully \n" ;
34
+ echo "Response contains multiple parts for different entity sets \n\n" ;
35
+ } catch (Exception $ e ) {
36
+ echo "✗ Error in simple batch: " . $ e ->getMessage () . "\n\n" ;
37
+ }
38
+
39
+ // Example 2: Batch with Changeset (Atomic Operations)
40
+ echo "2. Batch with Changeset for Atomic Operations \n" ;
41
+ echo "---------------------------------------------- \n" ;
42
+
43
+ try {
44
+ $ newPerson = [
45
+ 'FirstName ' => 'John ' ,
46
+ 'LastName ' => 'Doe ' ,
47
+ 'UserName ' => 'johndoe ' . time (),
48
+
49
+ ];
50
+
51
+ $ updatedPerson = [
52
+ 'FirstName ' => 'Jane ' ,
53
+ 'LastName ' => 'Smith '
54
+ ];
55
+
56
+ $ response = $ client ->batch ()
57
+ ->startChangeset ()
58
+ ->post ('People ' , $ newPerson , 'create-person ' )
59
+ ->patch ('People( \'russellwhyte \') ' , $ updatedPerson , 'update-person ' )
60
+ ->endChangeset ()
61
+ ->execute ();
62
+
63
+ echo "✓ Batch with changeset executed successfully \n" ;
64
+ echo "All operations in changeset will be committed atomically \n\n" ;
65
+ } catch (Exception $ e ) {
66
+ echo "✗ Error in changeset batch: " . $ e ->getMessage () . "\n\n" ;
67
+ }
68
+
69
+ // Example 3: Mixed Batch - Queries and Changesets Combined
70
+ echo "3. Mixed Batch - Queries and Changesets Combined \n" ;
71
+ echo "------------------------------------------------ \n" ;
72
+
73
+ try {
74
+ $ response = $ client ->batch ()
75
+ // First, get some data (not in changeset)
76
+ ->get ('People?$top=5 ' , 'get-top-people ' )
77
+
78
+ // Then perform atomic operations
79
+ ->startChangeset ()
80
+ ->post ('People ' , [
81
+ 'FirstName ' => 'Alice ' ,
82
+ 'LastName ' => 'Johnson ' ,
83
+ 'UserName ' => 'alicejohnson ' . time (),
84
+
85
+ ], 'create-alice ' )
86
+ ->post ('People ' , [
87
+ 'FirstName ' => 'Bob ' ,
88
+ 'LastName ' => 'Wilson ' ,
89
+ 'UserName ' => 'bobwilson ' . time (),
90
+
91
+ ], 'create-bob ' )
92
+ ->endChangeset ()
93
+
94
+ // More queries outside changeset
95
+ ->get ('Airlines?$top=3 ' , 'get-top-airlines ' )
96
+ ->execute ();
97
+
98
+ echo "✓ Mixed batch with queries and changesets executed successfully \n" ;
99
+ echo "Queries executed independently, changesets executed atomically \n\n" ;
100
+ } catch (Exception $ e ) {
101
+ echo "✗ Error in mixed batch: " . $ e ->getMessage () . "\n\n" ;
102
+ }
103
+
104
+ // Example 4: Batch with Different HTTP Methods
105
+ echo "4. Batch with Different HTTP Methods \n" ;
106
+ echo "------------------------------------ \n" ;
107
+
108
+ try {
109
+ $ response = $ client ->batch ()
110
+ ->get ('People?$filter=FirstName eq \'Russell \'' , 'find-russell ' )
111
+ ->startChangeset ()
112
+ ->put ('People( \'russellwhyte \') ' , [
113
+ 'FirstName ' => 'Russell ' ,
114
+ 'LastName ' => 'Whyte ' ,
115
+ 'UserName ' => 'russellwhyte ' ,
116
+ 'Emails ' => [
'[email protected] ' ],
117
+ 'AddressInfo ' => []
118
+ ], 'replace-russell ' )
119
+ ->delete ('People( \'vincentcalabrese \') ' , 'delete-vincent ' )
120
+ ->endChangeset ()
121
+ ->execute ();
122
+
123
+ echo "✓ Batch with mixed HTTP methods executed successfully \n" ;
124
+ echo "Demonstrated GET, PUT, and DELETE operations \n\n" ;
125
+ } catch (Exception $ e ) {
126
+ echo "✗ Error in mixed methods batch: " . $ e ->getMessage () . "\n\n" ;
127
+ }
128
+
129
+ // Example 5: Error Handling in Batch Operations
130
+ echo "5. Error Handling in Batch Operations \n" ;
131
+ echo "-------------------------------------- \n" ;
132
+
133
+ try {
134
+ // This batch intentionally includes operations that might fail
135
+ $ response = $ client ->batch ()
136
+ ->get ('People ' , 'valid-request ' )
137
+ ->get ('NonExistentEntitySet ' , 'invalid-request ' ) // This will likely fail
138
+ ->startChangeset ()
139
+ ->post ('People ' , [
140
+ 'FirstName ' => 'Test ' ,
141
+ 'UserName ' => 'test ' . time ()
142
+ // Missing required fields - might cause validation errors
143
+ ], 'potentially-failing-create ' )
144
+ ->endChangeset ()
145
+ ->execute ();
146
+
147
+ echo "✓ Batch with potential errors handled gracefully \n" ;
148
+ echo "Check response for individual operation status codes \n\n" ;
149
+ } catch (Exception $ e ) {
150
+ echo "✗ Expected error in batch with invalid operations: " . $ e ->getMessage () . "\n" ;
151
+ echo "This demonstrates how batch errors are handled \n\n" ;
152
+ }
153
+
154
+ // Example 6: Advanced Batch with Content-ID References
155
+ echo "6. Advanced Batch with Content-ID References \n" ;
156
+ echo "--------------------------------------------- \n" ;
157
+
158
+ try {
159
+ $ response = $ client ->batch ()
160
+ ->startChangeset ()
161
+ ->post ('People ' , [
162
+ 'FirstName ' => 'Reference ' ,
163
+ 'LastName ' => 'Example ' ,
164
+ 'UserName ' => 'refexample ' . time (),
165
+
166
+ ], 'new-person ' )
167
+ // Note: In a real scenario, you might reference the created person
168
+ // in subsequent operations using the Content-ID
169
+ ->endChangeset ()
170
+ ->get ('People?$orderby=FirstName desc&$top=1 ' , 'get-latest-person ' )
171
+ ->execute ();
172
+
173
+ echo "✓ Advanced batch with Content-ID references executed \n" ;
174
+ echo "Content-IDs allow referencing results from one operation in another \n\n" ;
175
+ } catch (Exception $ e ) {
176
+ echo "✗ Error in advanced batch: " . $ e ->getMessage () . "\n\n" ;
177
+ }
178
+
179
+ echo "=== Batch Operations Examples Complete === \n\n" ;
180
+
181
+ echo "Key Concepts Demonstrated: \n" ;
182
+ echo "- Simple batching of multiple GET requests \n" ;
183
+ echo "- Changesets for atomic operations (all succeed or all fail) \n" ;
184
+ echo "- Mixing queries and changesets in a single batch \n" ;
185
+ echo "- Using different HTTP methods (GET, POST, PUT, PATCH, DELETE) \n" ;
186
+ echo "- Error handling in batch operations \n" ;
187
+ echo "- Content-ID references for operation dependencies \n\n" ;
188
+
189
+ echo "Benefits of Batch Operations: \n" ;
190
+ echo "- Reduced network overhead (single HTTP request) \n" ;
191
+ echo "- Atomic transactions for related operations \n" ;
192
+ echo "- Better performance for multiple operations \n" ;
193
+ echo "- Simplified error handling for grouped operations \n\n" ;
194
+
195
+ echo "Best Practices: \n" ;
196
+ echo "- Use changesets for operations that should be atomic \n" ;
197
+ echo "- Keep batch sizes reasonable (typically 10-100 operations) \n" ;
198
+ echo "- Use Content-IDs for operations that depend on each other \n" ;
199
+ echo "- Handle both individual operation errors and batch-level errors \n" ;
0 commit comments