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
A framework for building simple to use SDKs in PHP 8.0 and above.
18
+
A framework for building SDKs in PHP.
25
19
26
20
## Installation
27
21
@@ -35,203 +29,150 @@ The purpose of this package is to provide a consistent and interoperable way to
35
29
36
30
## Usage
37
31
38
-
Working with this library is relatively simple, and an example can be found in the [demo](./demo) and [examples](./examples) directories.
39
-
40
-
The basic concept is that you will need to provide:
41
-
42
-
- PSR-17 Request and Response Factory.
43
-
- PSR-7 Messages
44
-
45
-
Inside this library we are using a PSR-18 implementation allowing you to connect the pieces together under the hood and provide SDK functionality using a replaceable set of components.
To handle the Http PSRs as they are lightweight and designed to be simple and PSR compliant.
55
-
56
-
### Building the SDK
57
-
58
-
To begin with we need to be able to build our SDK, to do this we can either use the `constructor` or use the static `build` method.:
59
-
60
-
#### SDK constructor
61
-
62
-
To create an SDK instance; simply pass through a uri, a Http Client that uses auto-discovery to find the available PSR-18 client, an authentication strategy, and an instance of the `Container`.
63
-
64
-
```php
65
-
use JustSteveKing\HttpAuth\Strategies\BasicStrategy;
66
-
use JustSteveKing\HttpSlim\HttpClient;
67
-
use JustSteveKing\UriBuilder\Uri;
68
-
use JustSteveKing\PhpSdk\SDK;
69
-
use PHPFox\Container\Container;
70
-
71
-
$sdk = new SDK(
72
-
uri: Uri::fromString('https://www.domain.com'),
73
-
client: HttpClient::build(),
74
-
strategy: new BasicStrategy(
75
-
authString: base64_encode("username:password")
76
-
),
77
-
container: Container::getInstance(),
78
-
);
79
-
```
80
-
81
-
#### SDK build
32
+
To get started with this library, you need to start by extending the `Client` class. Let's walk through building an SDK.
82
33
83
-
To use the static build method, the only requirement is to pass through a uri. If you want to set a custom Authentication Strategy you can also pass this through otherwise it will default to a Null Strategy.
34
+
### Create your SDK class
84
35
85
36
```php
86
-
use JustSteveKing\UriBuilder\Uri;
87
-
use JustSteveKing\PhpSdk\SDK;
37
+
use JustSteveKing\Sdk\Client;
88
38
89
-
$sdk = SDK::build(
90
-
uri: 'https://www.domain.com',
91
-
);
39
+
final class YourSDK extends Client
40
+
{
41
+
//
42
+
}
92
43
```
93
44
94
-
### Adding Resources to our SDK
95
-
96
-
Each Resource you add to your SDK requires 2 things:
97
-
98
-
- Implements `ResourceContract`
99
-
- Extends `AbstractResource`
100
-
101
-
Your resource should look like this:
45
+
Once this is in place, you can start adding your resources to the class. Let's add a `projects` method for a projects resource.
102
46
103
47
```php
104
-
use JustSteveKing\PhpSdk\Contracts\ResourceContract;
105
-
use JustSteveKing\PhpSdk\Resources\AbstractResource;
48
+
use JustSteveKing\Sdk\Client;
49
+
use JustSteveKing\Sdk\Tests\Stubs\Resources\ProjectResource;
106
50
107
-
class TestResource extends AbstractResource implements ResourceContract
51
+
final class YourSDK extends Client
108
52
{
109
-
protected string $path = '/test';
110
-
111
-
public static function name(): string
53
+
public function projects()
112
54
{
113
-
return 'tests';
55
+
return new ProjectResource(
56
+
client: $this,
57
+
);
114
58
}
115
59
}
116
-
117
60
```
118
61
119
-
The Path property allows you to set the uri path for this resource, and the static name method is how this resource is stored on the container.
62
+
We return a new instance of our resource classes, passing through your SDK as a `client`. This is so that each resource is able to talk through the client to send requests.
120
63
121
-
To add this resource to the SDK, you can use the add method:
64
+
Now, let's look at how to structure a resource.
122
65
123
66
```php
124
-
$sdk->add(
125
-
name: TestResource::name(),
126
-
resource: TestResource::class,
127
-
);
67
+
final class ProjectResource
68
+
{
69
+
//
70
+
}
128
71
```
129
72
130
-
Internally this will add the resource onto container and inject the SDK into the constructor, allowing you to access the Http Client and other aspects of the SDK.
73
+
To save time, there are a collection of traits that you can use on your resources.
131
74
132
-
### Calling a Resource
75
+
-`CanAccessClient` - which will add the default constructor required for a resource.
76
+
-`CanCreateDataObjects` - which will allow you to create DataObjects from API responses.
77
+
-`CanCreateRequests` - which will allow you to create HTTP requests and payloads using PSR-17 Factories.
133
78
134
-
Now that you have added a resource to the SDK, you are able to call it using the PHP magic __get method:
79
+
Let's look at an example of a full resource class.
135
80
136
81
```php
137
-
$response = $sdk->tests->get();
138
-
```
139
-
140
-
This will return a nice PSR-7 response for you to work with inside your SDK code.
141
-
142
-
### API
82
+
use Exception;
83
+
use JustSteveKing\Sdk\Concerns\Resources;
84
+
use JustSteveKing\Tools\Http\Enums\Method;
85
+
use Ramsey\Collection\Collection;
86
+
use Throwable;
143
87
144
-
The below documents the API of the PHP-SDK:
88
+
final class ProjectResource
89
+
{
90
+
use Resources\CanAccessClient;
91
+
use Resources\CanCreateDataObjects;
92
+
use Resources\CanCreateRequests;
145
93
146
-
#### SDK class
94
+
public function all(): Collection
95
+
{
96
+
$request = $this->request(
97
+
method: Method::GET,
98
+
uri: '/projects',
99
+
);
147
100
148
-
Your own SDK class should extend the base SDK class for easier integration.
-`static build(string $uri, null|StrategyInterface $strategy = null, null|Container = null): SDK`**This static build method allows the defaults to be set for you to get an SDK quickly.**
152
-
-`add(string $name, string $resource): self`**The add method allows you to add resources onto the SDK container, and checks that the resource being passed extends the AbstractResource and implements the ResourceContract.**
153
-
-`uri(): Uri`**Return the setup instance of UriBuilder that is being used, to allow you to manipulate the URI string.**
154
-
-`client(): HttpClient`**Return the setup instance of the HttpClient that is being used, to allow you to enforce any changes that are required.**
155
-
-`strategy(): StrategyInterface`**Returns the setup instance of the Authentication Strategy that is being used, to allow you to export the auth header array.**
156
-
-`container(): Container`**Returns the setup instance of the Container, to allow you to bind make and work with the container directly should it be required.**
157
-
-`__get(string $name): ResourceContract`**Returns a build instance of the called Resource if it has been added to the container.**
130
+
We start by creating a request, and then try to get a response by sending it through the client.
158
131
159
-
#### AbstractResource class
132
+
Once we have a response, we create a `Collection` thanks to a package by Ben Ramsey. We pass through the type of each item we expect it to be,
133
+
then the data as an array. To create the data we map over the response content and statically create a new Data Object.
160
134
161
-
Your resources must all extend the Abstract Resource class.
135
+
This allows us to keep our code clean, concise, and testable.
-`sdk(): SDK`**Return the setup instance of the SDK that has been passed through to the resource.**
165
-
-`getWith(): array`**Return an array of relations to sideload onto the request.**
166
-
-`getLoad(): string|null`**Return a string or null if a specific resource identifier has been passed in.**
167
-
-`load(string|int $identifier): self`**The load method allows you to set a specific resource identifier to look for on an API.**
168
-
-`uri(Uri $uri): self`**The uri method allows you to completely override the URI Builder on the SDK.**
169
-
-`client(HttpClient $http): self`**The client method allows you to completely override the Http Client on the SDK.**
170
-
-`strategy(StrategyInterface $strategy): self`**The strategy method allows you to completely override the Authentication Strategy on the SDK.**
171
-
-`loadPath(): self`**Loads the path from the resource into to URI builder on the SDK.**
172
-
-`get(): ResponseInterface`**Performs a GET request to the resource path, to return a list of resources.**
173
-
-`find(string|int $identifier): ResponseInterface`**Performs a GET request to the resource path with an identifier appended to it, to return a single resource.**
174
-
-`create(array $data): ResponseInterface`**Performs a POST request to the resource path, to create a new single resource.**
175
-
-`update($identifier, array $data, string $method = 'patch'): ResponseInterface`**Performs either a PATCH or PUT request to the resource path with an identifier appended to it, to update a single resource.**
176
-
-`delete(string|int $identifier): ResponseInterface`**Performs a DELETE request to the resource path with an identifier appended to it, to remove a resource.**
177
-
-`where(string $key, $value): self`**Builds the query parameters in a famility query builder style syntax.**
137
+
## Testing
178
138
179
-
#### ResourceContract Interface
139
+
To run the test:
180
140
181
-
Your resources must implement the ResourceContract interface.
141
+
```bash
142
+
composer run test
143
+
```
182
144
183
-
-`static name(): string`**Returns a string representation of the resource name, to allow it to be bound the the SDK container.**
145
+
## Static analysis
184
146
147
+
To run the static analysis checks:
185
148
186
-
It is highly recommended that you use all of these internally in your API to give you the ability to control the process.
149
+
```bash
150
+
composer run stan
151
+
```
187
152
188
-
### Building an SDK
153
+
##Code Style
189
154
190
-
To build an SDK, you can simply extend the SDK like so:
155
+
To run the code style fixer:
191
156
192
-
```php
193
-
use Demo\Resources\Server;
194
-
use JustSteveKing\HttpAuth\Strategies\NullStrategy;
195
-
use JustSteveKing\HttpSlim\HttpClient;
196
-
use JustSteveKing\PhpSdk\SDK;
197
-
use JustSteveKing\UriBuilder\Uri;
198
-
use PHPFox\Container\Container;
199
-
200
-
class MySDK extends SDK
201
-
{
202
-
public function __construct()
203
-
{
204
-
parent::__construct(
205
-
uri: Uri::fromString(
206
-
uri: 'https://www.domain.tld',
207
-
),
208
-
client: HttpClient::build(),
209
-
container: Container::getInstance(),
210
-
strategy: new NullStrategy()),
211
-
);
212
-
}
157
+
```bash
158
+
composer run pint
159
+
```
213
160
214
-
public static function boot(): MySDK
215
-
{
216
-
$client = new MySDK();
161
+
## Refactoring
217
162
218
-
$client->add(
219
-
name: TestResource::name(),
220
-
resource: TestResource::class,
221
-
);
163
+
To run the rector code refactoring:
222
164
223
-
return $client;
224
-
}
225
-
}
165
+
```bash
166
+
composer run refactor
226
167
```
227
168
228
-
## Testing
169
+
## Special Thanks
229
170
230
-
TO run the test:
171
+
Without the following packages and people, this framework would have been a lot harder to build.
231
172
232
-
```bash
233
-
composer run test
234
-
```
173
+
-[The PHP League - Object Mapper](https://github.com/thephpleague/object-mapper)
0 commit comments