PHP code example of zero-to-prod / github-sdk
1. Go to this page and download the library: Download zero-to-prod/github-sdk library . Choose the download type require .
2. Extract the ZIP file and open the index.php.
3. Add this code to the index.php.
<?php
require_once('vendor/autoload.php');
/* Start to develop here. Best regards https://php-download.com/ */
zero-to-prod / github-sdk example snippets
use Zerotoprod\GitHubSdk\GitHubSdk;
use Zerotoprod\GitHubSdk\GitHubSdkConfig;
$api = new GitHubSdk([
GitHubSdkConfig::url => 'https://api.github.com',
GitHubSdkConfig::headers => [
'Authorization' => 'Bearer '.$token,
'Accept' => 'application/vnd.github+json',
],
]);
$repo = $api->getRepo('zero-to-prod', 'github-sdk');
$repo->data->full_name; // 'zero-to-prod/github-sdk'
$repo->data->stargazers_count; // 3
$api->createRepoIssue('zero-to-prod', 'github-sdk', [
'title' => 'Bug',
'body' => 'It broke',
]);
use Zerotoprod\GitHubSdk\Models\CreateRepoIssueRequest;
$api->createRepoIssue('zero-to-prod', 'github-sdk', CreateRepoIssueRequest::from([
CreateRepoIssueRequest::title => 'Bug',
]));
$api->getRepo('zero-to-prod', 'github-sdk', [
Options::headers => ['Authorization' => 'Bearer '.$appToken],
]);
$api = new GitHubSdk($config, new CurlHttpTransport(), [
Hook::before->value => fn (HookContext $ctx) => $ctx->withHeaders([
'Authorization' => 'Bearer '.$tokens->current(),
]),
]);
use Zerotoprod\GitHubSdk\Options;
$api->listRepoIssues('zero-to-prod', 'github-sdk', [
Options::query => ['state' => 'open', 'labels' => 'bug', 'per_page' => 50],
]);
// GET /repos/zero-to-prod/github-sdk/issues?state=open&labels=bug&per_page=50
$issues = $api->listRepoIssues('zero-to-prod', 'github-sdk', [
Options::query => ['per_page' => 100, 'page' => 2],
]);
$issues->response->header('Link'); // '<https://api.github.com/...?page=3>; rel="next"'
$result = $api->getRepo('zero-to-prod', 'nope');
$result->failed(); // true
$result->status(); // 404
$result->errors->message; // 'Not Found'
$result->errors->errors; // GitHub's per-field errors, when it sends them
$result->response->header('x-ratelimit-remaining');
$response = $api->getRepo('zero-to-prod', 'github-sdk', [Options::raw => true]);
$response->json('full_name');
use Zerotoprod\GitHubSdk\{GitHubSdk, CurlHttpTransport, Hook, HookContext};
$api = new GitHubSdk($config, new CurlHttpTransport(), [
Hook::before->value => [
fn (HookContext $ctx) => $ctx->withHeaders(['X-Trace-Id' => bin2hex(random_bytes(8))]),
fn (HookContext $ctx) => logger()->debug('Outgoing', $ctx->redacted()),
],
Hook::after->value => [
fn (HookContext $ctx) => logger()->info("{$ctx->HttpMethod->value} {$ctx->url} → {$ctx->response->status()}"),
],
Hook::onException->value => [
fn (HookContext $ctx, \Throwable $e) => logger()->error("{$ctx->url} failed: {$e->getMessage()}"),
],
]);
$ctx->Hook; // Hook enum (before / after / onException)
$ctx->HttpMethod; // HttpMethod enum — ->value is 'GET', 'POST', ...
$ctx->url; // fully qualified request URL
$ctx->options; // Guzzle-compatible options array (json, headers, query, ...)
$ctx->response; // transport response during `after`; null otherwise
$ctx->withHeaders(['X-Trace-Id' => $id]); // merge headers — per-call headers survive
$ctx->withOptions(['timeout' => 5]); // merge options — other options survive
$ctx->redacted(); // array for logging, credentials masked
use Zerotoprod\GitHubSdk\{RetryingHttpTransport, CurlHttpTransport};
$api = new GitHubSdk($config, new RetryingHttpTransport(new CurlHttpTransport()));
$api = new GitHubSdk($config, new RetryingHttpTransport(
inner: new CurlHttpTransport(),
maxAttempts: 5, // total attempts including the first; default 3, 1 disables retrying
baseDelay: 0.25, // seconds the backoff doubles from; default 0.5
maxDelay: 10.0, // ceiling for one sleep; default 30.0
));
$api->getRepo('zero-to-prod', 'github-sdk', [
'timeout' => 5, // total, seconds (default 30)
'connect_timeout' => 2, // TCP connect only (default 10)
]);
use Zerotoprod\GitHubSdk\{GitHubSdk, CachingHttpTransport, CurlHttpTransport};
use Illuminate\Support\Facades\Cache;
$api = new GitHubSdk($config, new CachingHttpTransport(
new CurlHttpTransport(),
// fn (string $key, Closure $fetch): array — mirrors Cache::remember($key, $ttl, $fetch)
fn (string $key, \Closure $fetch) => Cache::remember($key, 60, $fetch),
));
$api->getRepo('zero-to-prod', 'github-sdk'); // hits the network; result cached
$api->getRepo('zero-to-prod', 'github-sdk'); // served from cache — no HTTP call
$store = [];
$api = new GitHubSdk($config, new CachingHttpTransport(
new CurlHttpTransport(),
function (string $key, \Closure $fetch) use (&$store): array {
return $store[$key] ??= $fetch();
},
));
new CachingHttpTransport(
inner: new LaravelHttpTransport(),
cache: fn (string $key, \Closure $fetch) => Cache::remember($key, 60, $fetch),
normalize: fn (\Illuminate\Http\Client\Response $r): array => [
'status' => $r->status(), 'headers' => $r->headers(), 'body' => $r->body(),
],
rehydrate: fn (array $d) => new \Illuminate\Http\Client\Response(
new \GuzzleHttp\Psr7\Response($d['status'], $d['headers'], $d['body']),
),
);
use Zerotoprod\GitHubSdk\Internal\Fake;
new GitHubSdk($config, new CachingHttpTransport(new Fake(), $cache));
// Cache outermost: a hit costs nothing, and only a miss can retry.
new CachingHttpTransport(new RetryingHttpTransport(new CurlHttpTransport()), $cache);
use Zerotoprod\GitHubSdk\{GitHubSdk, GitHubSdkConfig, Response, ApiRoute};
[$api, $fake] = GitHubSdk::fake([
GitHubSdkConfig::url => 'https://api.github.com',
]);
$fake->queue(
new Response(200, [], json_encode(['full_name' => 'zero-to-prod/github-sdk'])),
new Response(404, [], json_encode(['message' => 'Not Found'])),
);
$found = $api->getRepo('zero-to-prod', 'github-sdk');
$missing = $api->getRepo('zero-to-prod', 'nope');
$fake->assertSent('GET', '/repos/zero-to-prod/github-sdk'); // method + URL substring
$fake->assertNotSent('DELETE');
$fake->assertSentCount(2);
$fake->recorded()[0]['method']; // 'GET'
$fake->recorded()[0]['url']; // 'https://api.github.com/repos/zero-to-prod/github-sdk'
ApiRoute::repo->value; // '/repos/{owner}/{repo}'
ApiRoute::repo_issues->value; // '/repos/{owner}/{repo}/issues'
ApiRoute::repo_issues(['per_page' => 50])->render(); // '/repos/{owner}/{repo}/issues?per_page=50'
use Illuminate\Support\Facades\Http;
use Zerotoprod\GitHubSdk\{GitHubSdk, LaravelHttpTransport, ApiRoute};
Http::fake([
'*/repos/zero-to-prod/github-sdk' => Http::response(['full_name' => 'zero-to-prod/github-sdk'], 200),
]);
$response = (new GitHubSdk([], new LaravelHttpTransport()))->getRepo('zero-to-prod', 'github-sdk');
self::assertTrue($response->ok());
Http::assertSent(fn ($r) => str_ends_with($r->url(), '/repos/zero-to-prod/github-sdk'));
use Zerotoprod\GitHubSdk\Factories\{ErrorsFactory, GitHubSdkConfigFactory};
use Zerotoprod\GitHubSdk\Models\Errors;
[$api, $fake] = GitHubSdk::fake(GitHubSdkConfigFactory::factory()->context());
$fake->queue(new Response(404, [], ErrorsFactory::factory()
->set(Errors::message, 'Not Found')
->json()));
$issues = $api->listRepoIssues('zero-to-prod', 'github-sdk');
foreach ($issues->data as $issue) {
$issue->title;
$issue->user->login;
}
GitHubSdkConfig::model_namespace => 'App\\Models\\GitHub',
// app/Models/GitHub/Repository.php (published)
namespace App\Models\GitHub;
use Zerotoprod\GitHubSdk\Internal\DataModel;
class Repository
{
use DataModel;
// ... generated properties ...
public function isActive(): bool
{
return $this->archived === false && $this->disabled === false;
}
}
use Zerotoprod\GitHubSdk\HttpTransport;
/** @implements HttpTransport<\Psr\Http\Message\ResponseInterface> */
class GuzzleTransport implements HttpTransport
{
public function __construct(private \GuzzleHttp\ClientInterface $client) {}
public function request(string $method, string $url, array $options = []): \Psr\Http\Message\ResponseInterface
{
return $this->client->request($method, $url, $options);
}
}
$api = new GitHubSdk($config, new GuzzleTransport($client));