You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardexpand all lines: README.md
+26-58
Original file line number
Diff line number
Diff line change
@@ -30,40 +30,11 @@ FetchPHP provides two main functions:
30
30
31
31
---
32
32
33
-
### **Guzzle Client Instantiation and Static Variables**
33
+
### **Guzzle Client Instantiation**
34
34
35
-
By default, FetchPHP uses a **singleton** pattern to create and reuse the Guzzle HTTP client across multiple `fetch` or `fetch_async` function calls. This ensures that a new client is not created for every request, reducing overhead. If you do not pass a custom client, the first time you call `fetch`, a new Guzzle client will be created and stored as a **static variable**. All subsequent requests will reuse this client.
35
+
FetchPHP uses a **singleton** pattern within the `Http` class to manage the Guzzle HTTP client. This ensures that the same client instance is reused across multiple requests unless a custom client is explicitly provided. This refactor resolves the issues with static variables being shared across all requests globally.
36
36
37
-
#### **Static Variables and Potential Risks**
38
-
39
-
While using a static variable for the Guzzle client improves performance by avoiding repeated client instantiation, it introduces some potential issues that you should be aware of:
40
-
41
-
1.**Shared State and Configuration**:
42
-
- Any changes to the static client configuration (e.g., headers, base URI, timeouts) will persist across all subsequent requests. This could lead to unexpected behavior if different configurations are required for different requests.
43
-
-**Mitigation**: Always pass explicit configurations (like `headers`, `auth`, or `timeout`) in the options parameter for every request. This ensures that each request uses the intended configuration.
- If the application is a long-running process (e.g., a worker or daemon), the static Guzzle client will remain in memory. Over time, it could accumulate state (such as cookies or connection pools) and potentially cause memory issues.
54
-
- **Mitigation**: If your application is long-running, consider resetting or replacing the static Guzzle client at regular intervals, especially if there is a risk of accumulated state affecting performance.
55
-
56
-
3. **Concurrency and Thread Safety**:
57
-
- In environments where concurrent requests are made (e.g., using Swoole or ReactPHP), the static client could introduce thread-safety issues. Since PHP is not inherently multi-threaded, this is not a concern for standard PHP web applications. However, in concurrent environments, race conditions could occur.
58
-
- **Mitigation**: In environments with concurrent requests, avoid using static variables for the Guzzle client. Instead, instantiate separate Guzzle clients or use dependency injection for better control over individual request contexts.
59
-
60
-
4. **Global Impact**:
61
-
- Modifying the static Guzzle client affects all subsequent requests globally. If different services or APIs are accessed with different configurations, this could cause unexpected side effects.
62
-
- **Mitigation**: Always pass client-specific configurations in the options, or use separate Guzzle client instances for different services.
63
-
64
-
In applications where more granular control over the client lifecycle is required, or in environments with dependency injection support, consider passing the Guzzle client explicitly via service containers or dependency injection frameworks.
65
-
66
-
#### **Using a Custom Guzzle Client with Middleware Support**
37
+
#### **Custom Guzzle Client Handling**
67
38
68
39
If you want to provide a custom Guzzle client (with custom configurations or middleware), you can pass it through the `options` parameter. This allows you to add middleware for things like logging, retries, caching, etc.
// Pass the Guzzle client into the fetch function via options
65
+
// Pass the custom Guzzle client into the fetch function via options
96
66
$response = fetch('/todos/1', [
97
67
'client' => $client
98
68
]);
99
69
100
-
// The Guzzle client instance will now be reused across multiple fetch calls
70
+
// The custom Guzzle client will only be used for this request
101
71
$response2 = fetch('/todos/2', [
102
72
'client' => $client
103
73
]);
@@ -106,14 +76,11 @@ print_r($response->json());
106
76
print_r($response2->json());
107
77
```
108
78
109
-
### **Why is Singleton Guzzle Client Useful?**
110
-
111
-
Passing a singleton Guzzle client is useful when:
79
+
### **Why is the Singleton Guzzle Client Still Useful?**
112
80
113
-
- You're making many requests and want to avoid the overhead of creating a new client each time.
114
-
- You want to configure specific client-wide options (e.g., base URI, timeouts, headers) and use them across multiple requests.
115
-
- You want to apply custom middleware to every request made by the client (e.g., logging, retries, etc.).
116
-
- If different configurations are needed for different requests, you can pass a new instance of the Guzzle client in the `options` parameter to bypass the singleton behavior.
81
+
- The singleton pattern ensures the client instance is reused across multiple requests to avoid creating new client instances unnecessarily.
82
+
- You can still pass a custom client for specific requests as needed.
83
+
- The client lifecycle is now more controlled, ensuring that the potential issues with static variables and shared state have been resolved.
-**`json(bool $assoc = true)`**: Decodes the response body as JSON. If `$assoc` is `true`, it returns an associative array. If `false`, it returns an object. If the JSON decoding fails, a `RuntimeException` will be thrown. Ensure you handle this exception when working with potentially malformed JSON responses.
110
+
The `Response` class provides various methods to interact with the response data, similar to how Laravel's response works but with FetchPHP-specific enhancements:
111
+
112
+
-**`json(bool $assoc = true)`**: Decodes the response body as JSON. If `$assoc` is `true`, it returns an associative array. If `false`, it returns an object. Throws a `RuntimeException` if JSON decoding fails.
144
113
-**`text()`**: Returns the response body as plain text.
145
-
-**`blob()`**: Returns the response body as a PHP stream resource (like a "blob").
146
-
-**`arrayBuffer()`**: Returns the response body as a binary string.
114
+
-**`blob()`**: Returns the response body as a PHP stream resource, which can be used like a "blob."
115
+
-**`arrayBuffer()`**: Returns the raw binary data from the response body as a string.
116
+
-**`status()`**: Returns the HTTP status code (e.g., `200` for success, `404` for not found). This replaces the old `getStatusCode()` method, but remains backwards compatible.
147
117
-**`statusText()`**: Returns the HTTP status text (e.g., "OK" for `200`).
118
+
-**`header(string $key)`**: Retrieves a specific header from the response.
119
+
-**`headers()`**: Retrieves all headers as an associative array.
120
+
-**`withHeaders(array $headers)`**: Sets new headers for the response and returns a new instance with the headers applied.
121
+
-**`setStatusCode(int $code)`**: Sets a custom status code on the response.
148
122
-**`ok()`**: Returns `true` if the status code is between `200-299`.
149
-
-**`isInformational()`**, **`isRedirection()`**, **`isClientError()`**, **`isServerError()`**: Helpers to check status ranges.
123
+
-**`isInformational()`**: Returns `true` if the status code is between `100-199`.
124
+
-**`isRedirection()`**: Returns `true` if the status code is between `300-399`.
125
+
-**`isClientError()`**: Returns `true` if the status code is between `400-499`.
126
+
-**`isServerError()`**: Returns `true` if the status code is between `500-599`.
150
127
151
128
---
152
129
@@ -337,7 +314,7 @@ FetchPHP gracefully handles errors, returning a `500` status code and error mess
The `Response` class provides convenient methods for interacting with the response body, headers, and status codes.
397
-
398
-
#### **Response Methods Overview**
399
-
400
-
-**`json()`**: Decodes the response body as JSON. If the JSON decoding fails, a `RuntimeException` is thrown.
401
-
-**`text()`**: Returns the raw response body as plain text.
402
-
-**`blob()`**: Returns the body as a PHP stream (useful for file handling).
403
-
-**`arrayBuffer()`**: Returns the body as a binary string.
404
-
-**`statusText()`**: Returns the status text (e.g., "OK").
405
-
-**`ok()`**: Returns `true` if the status is 200–299.
373
+
The `Response` class provides convenient methods for interacting with the response body, headers, and status codes. For a detailed overview of available methods, refer to the **Available Response Methods** section above.
This document provides instructions for upgrading to version **v2.0.0** of FetchPHP.
4
+
5
+
## Upgrading from v1.x to v2.0.0
6
+
7
+
Version 2.0.0 introduces significant changes and refactors to improve the overall structure, maintainability, and performance of the library. This guide will help you transition smoothly from version 1.x to 2.0.0.
8
+
9
+
### Backward Compatibility
10
+
11
+
The following functions and methods remain backward-compatible:
12
+
13
+
-**`fetch()`**, **`fetch_async()`**, and **`fetchAsync()`** remain functional. However, `fetchAsync` is now deprecated.
14
+
- Core methods in the `Response` class, such as `json()`, `text()`, and `blob()`, continue to function as before.
15
+
16
+
**Action Required**: While no immediate changes are required for these functions, it’s recommended to transition from `fetchAsync` to `fetch_async` to future-proof your code.
17
+
18
+
---
19
+
20
+
### Changes to Response Class
21
+
22
+
The `Response` class has been enhanced to align more closely with Laravel’s response object.
23
+
24
+
#### Notable Changes
25
+
26
+
-**`getStatusCode()`** has been renamed to **`status()`**. This aligns with Laravel’s method names for responses. However, for backward compatibility, the old method still works.
27
+
-**New Methods** have been introduced:
28
+
-`header()`
29
+
-`headers()`
30
+
-`content()`
31
+
-`status()`
32
+
33
+
These methods provide additional flexibility and control over the response.
34
+
35
+
**Action Required**: If you are using `getStatusCode()`, no immediate changes are necessary as it remains supported, but transitioning to `status()` is recommended for consistency with Laravel conventions.
36
+
37
+
---
38
+
39
+
### Singleton Guzzle Client
40
+
41
+
The Guzzle client is now managed using a **singleton pattern**, meaning only one instance of the client is reused across requests to reduce overhead.
42
+
43
+
#### Implications
44
+
45
+
- The same Guzzle client will be used across all `fetch()` and `fetch_async()` calls.
46
+
- If you need different Guzzle configurations for specific requests, you will need to pass a custom Guzzle client via the `options` parameter.
47
+
48
+
**Action Required**: If your application depends on multiple Guzzle client configurations, make sure to pass the client explicitly in the `options` when calling `fetch()` or `fetch_async()`.
49
+
50
+
---
51
+
52
+
### Deprecations
53
+
54
+
-**`fetchAsync()`** is deprecated and will be removed in future releases. Please use `fetch_async()` going forward.
55
+
56
+
**Action Required**: Update any usage of `fetchAsync()` to `fetch_async()`.
57
+
58
+
---
59
+
60
+
### Error Handling
61
+
62
+
Error handling has been centralized in the `Http` class, providing more robust and consistent behavior for both synchronous and asynchronous requests.
63
+
64
+
- Request exceptions are now consistently caught and handled, ensuring proper response formatting even in error scenarios.
0 commit comments