m4tthumphrey/php-gitlab-api
Modern GitLab API v4 client for PHP 8.1–8.5. Provides a clean, feature-rich wrapper around GitLab endpoints with PSR-18 HTTP client and PSR-17 factories support, plus maintained releases, changelog, and strong community tooling.
## Getting Started
### Minimal Steps
1. **Installation**
Add the package via Composer:
```bash
composer require m4tthumphrey/php-gitlab-api:^12.1 guzzlehttp/guzzle:^7.9.2
For Laravel, use the framework-specific package:
composer require graham-campbell/gitlab:^8.1
Basic Setup Initialize the client with authentication:
use Gitlab\Client;
$client = new Client();
$client->authenticate('your_access_token', Client::AUTH_HTTP_TOKEN);
First Use Case Fetch a project or create an issue:
// Fetch a project
$project = $client->projects()->show(123);
// Create an issue
$issue = $client->issues()->create(123, [
'title' => 'Fix bug',
'description' => 'This is a test issue.'
]);
Self-Hosted GitLab Configure the API URL if using a self-hosted instance:
$client->setUrl('https://git.yourdomain.com');
CRUD Operations Use the fluent API for projects, issues, merge requests, etc.:
// Create
$project = $client->projects()->create('My Project', ['description' => 'Test']);
// Read
$project = $client->projects()->show($project->id);
// Update
$updated = $client->projects()->update($project->id, ['description' => 'Updated']);
// Delete
$client->projects()->delete($project->id);
Pagination with ResultPager
Fetch paginated results (e.g., issues, merge requests):
$pager = new Gitlab\ResultPager($client);
$issues = $pager->fetchAll($client->issues(), 'all', [123, ['state' => 'closed']]);
Handling API Responses
Use getResponse() for raw responses or getData() for parsed data:
$response = $client->projects()->show(123);
$data = $response->getData();
Custom HTTP Clients Extend functionality with HTTPlug plugins (e.g., caching, logging):
use Http\Client\Common\Plugin\HeaderSetPlugin;
use Gitlab\HttpClient\Builder;
$plugin = new HeaderSetPlugin(['User-Agent' => 'MyApp/1.0']);
$builder = new Builder();
$builder->addPlugin($plugin);
$client = new Client($builder);
Error Handling Catch exceptions for API errors:
try {
$client->projects()->show(9999); // Non-existent project
} catch (\Gitlab\Exception\GitlabException $e) {
\Log::error($e->getMessage());
}
Authentication Methods
$client->authenticate('token', Client::AUTH_HTTP_TOKEN);
$client->authenticate('oauth_token', Client::AUTH_OAUTH_TOKEN);
$client->authenticate('job_token', Client::AUTH_JOB_TOKEN);
Search Functionality Search across projects, groups, or issues:
$results = $client->search()->all('keyword', ['search' => 'scope:projects']);
Webhooks and Events Listen to project/group events or manage webhooks:
$webhook = $client->projects()->addWebhook(123, [
'url' => 'https://example.com/webhook',
'push_events' => true
]);
Double Encoding in URLs
Repositories::compareCommits) may double-encode query parameters. Use rawurlencode or urlencode manually if needed:
$client->repositories()->compareCommits(123, 'main', 'feature', ['params' => rawurlencode('key=value')]);
Pagination Quirks
ResultPager for pagination. Check the API docs for manual pagination handling:
$page = 1;
do {
$issues = $client->issues()->all(123, ['page' => $page, 'per_page' => 100]);
$page = $issues->nextPage();
} while ($page);
Authentication Scope
api for full access, read_repository for limited access). Use read_api for read-only operations:
$client->authenticate('token_with_read_api_scope', Client::AUTH_HTTP_TOKEN);
Rate Limiting
use Symfony\Component\HttpClient\RetryStrategy;
$client->setHttpClient($httpClient->withOptions([
'timeout' => 30,
'retry_on_status' => [429, 500, 502, 503, 504],
'retry_delay' => RetryStrategy::DELAY_MILLISECONDS * 1000,
]));
Sensitive Data Handling
.env:
$token = env('GITLAB_ACCESS_TOKEN');
$client->authenticate($token, Client::AUTH_HTTP_TOKEN);
Deprecated Methods
Projects::pipelines with date filters) may require time information. Update to use ResultPager for consistency:
// Old (may fail)
$client->projects()->pipelines(123, ['before' => '2023-01-01']);
// New (recommended)
$pager = new ResultPager($client);
$pipelines = $pager->fetchAll($client->projects()->pipelines(123), 'all', [123, ['before' => '2023-01-01T00:00:00Z']]);
Self-Hosted GitLab URL
setUrl() for self-hosted instances will default to https://gitlab.com. Always verify:
$client->setUrl('https://git.yourdomain.com');
Merge Request Conflicts
try {
$client->mergeRequests()->update(123, ['title' => 'Updated Title']);
} catch (\Gitlab\Exception\GitlabException $e) {
if (strpos($e->getMessage(), 'conflict') !== false) {
// Resolve conflicts manually or programmatically
}
}
Enable Debugging Use Guzzle middleware to log requests/responses:
use GuzzleHttp\Middleware;
use Psr\Http\Message\RequestInterface;
$history = [];
$client->setHttpClient($httpClient->withMiddleware([
Middleware::tap(function (RequestInterface $request) use (&$history) {
$history[] = $request;
}),
Middleware::history($history),
]));
Check API Status Verify GitLab API availability before debugging:
try {
$client->system()->info();
} catch (\Gitlab\Exception\GitlabException $e) {
\Log::error('GitLab API unavailable: ' . $e->getMessage());
}
Validate Parameters
Use OptionsResolver for parameter validation (e.g., for Projects::create):
$resolver = new \Symfony\Component\OptionsResolver\OptionsResolver();
$resolver->setDefaults([
'name' => null,
'description' => '',
'visibility' => 'private',
]);
$options = $resolver->resolve($inputParams);
Handle Deprecated Features
How can I help you explore Laravel packages today?