chobie/jira-api-restclient
PHP client for Jira’s REST API. Provides simple authentication, request handling, and endpoints for issues, projects, users, comments, attachments, workflows, and more—useful for integrating Jira operations into your apps, scripts, or automation jobs.
## Getting Started
### Minimal Setup
1. **Installation**
```bash
composer require chobie/jira-api-restclient:^2.0
Update config/services.php (PHP 5.6+ required):
'jira' => [
'url' => env('JIRA_URL', 'https://your-jira-instance.atlassian.net'),
'username' => env('JIRA_USERNAME'),
'api_token' => env('JIRA_API_TOKEN'), // or 'password'
'timeout' => 30,
'per_page' => 50, // New: Configure issues per page in Walker
],
First Use Case: Fetching Worklogs
use Chobie\JiraApiRestClient\Client;
$client = new Client(config('services.jira'));
$worklogs = $client->issues()->worklogs()->get('PROJ-123');
foreach ($worklogs as $log) {
echo $log->timeSpent . ' spent by ' . $log->author->displayName;
}
Key Files to Review
src/Client.php (Core client logic, now PSR-4 namespaced)src/Resources/Issue.php (Updated model structure)src/Exceptions/ (Enhanced error handling)src/Walker.php (New pagination controls)// Add worklog
$client->issues()->worklogs()->create('PROJ-123', [
'timeSpent' => '1h',
'comment' => 'Fixed login bug',
]);
// Get worklogs with pagination
$worklogs = $client->issues()->worklogs()->get('PROJ-123', [
'startAt' => 0,
'maxResults' => 20,
]);
// Delete worklog
$client->issues()->worklogs()->delete('PROJ-123', 1234); // By worklog ID
// Find version by name
$version = $client->projects()->versions()->findByName('PROJ', '1.0');
// Update version
$client->projects()->versions()->update('PROJ', 1000, [
'name' => 'Updated 1.0',
'description' => 'New description',
]);
// Release version
$client->projects()->versions()->release('PROJ', 1000);
// Get project components
$components = $client->projects()->components()->get('PROJ');
// Get issue types + statuses
$issueTypes = $client->projects()->issueTypes()->get('PROJ');
// Get resolutions
$resolutions = $client->issues()->metadata()->resolutions();
// Create remote link
$client->issues()->remoteLinks()->create('PROJ-123', [
'globalId' => 'EXT-123',
'application' => ['name' => 'External System'],
]);
// Upload with custom filename
$client->issues()->attachments()->create('PROJ-123', 'file.pdf', [
'name' => 'custom_filename.pdf',
]);
// Get metadata
$meta = $client->issues()->attachments()->meta('PROJ-123');
// app/Providers/JiraServiceProvider.php
public function register()
{
$this->app->singleton(Client::class, function ($app) {
$config = $app['config']['services.jira'];
$client = new Client($config);
// Enable debug if needed
if ($app->environment('local')) {
$client->setDebug(true);
}
return $client;
});
}
// Configure default per-page in config
'jira' => [
'per_page' => 100, // Default for all queries
],
// Override per query
$issues = $client->issues()->search('project=PROJ', [
'maxResults' => 200,
]);
// Get total count (NEW)
$issues = $client->issues()->search('project=PROJ', [
'maxResults' => 50,
'getTotal' => true, // Returns count in ->total property
]);
// Cache resolutions (now with local cache)
$resolutions = Cache::remember('jira.resolutions', now()->addHours(1), function() {
return $client->issues()->metadata()->resolutions();
});
// Cache issue types
$issueTypes = Cache::remember("jira.issue.types.{$projectKey}", now()->addHours(1), function() use ($projectKey) {
return $client->projects()->issueTypes()->get($projectKey);
});
try {
$issue = $client->issues()->get('PROJ-123');
} catch (JiraApiException $e) {
// Access detailed error info
$error = $e->getError();
$response = $e->getResponse();
// Log full error details
\Log::error('Jira API Error', [
'error' => $error,
'response' => $response->getBody(),
'status' => $response->getStatusCode(),
]);
}
Breaking Changes
$return_as_json → $return_as_array).Pagination Quirks
per_page may exceed Jira limits (100 max).'per_page' => 50 in config and handle pagination manually:
$startAt = 0;
do {
$issues = $client->issues()->search('project=PROJ', [
'startAt' => $startAt,
'maxResults' => 50,
]);
$startAt += 50;
} while (!$issues->isLast());
Attachment Issues
name parameter to override filenames:
$client->issues()->attachments()->create('PROJ-123', 'file.pdf', [
'name' => 'visible_name.pdf',
]);
Worklog Time Formats
Xh Ym format (e.g., 1h 30m).if (!preg_match('/^\d+h\s*\d*m?$/', $timeSpent)) {
throw new \InvalidArgumentException('Invalid time format. Use "Xh Ym".');
}
Version Name Lookups
findVersionByName is case-sensitive.$version = $client->projects()->versions()->findByName('PROJ', strtoupper('1.0'));
SSL Connection Issues (macOS)
CurlClient configuration:
$client->setHttpClient(new CurlClient([
'curl_options' => [
CURLOPT_SSL_VERIFYPEER => false, // Temporary workaround
],
]));
Enable Verbose Debugging
$client = new Client($config);
$client->setDebug(true); // Logs to storage/logs/jira.log
$client->setDebugLevel(2); // Higher verbosity (0-2)
Inspect Raw API Calls
$client->getHttpClient()->getEmitter()->add(
new \Monolog\Handler\StreamHandler(storage_path('logs/jira_raw.log'))
);
Common HTTP Errors (Updated)
| Error Code | Cause | Solution |
|---|---|---|
| 400 | Invalid time format (e.g., "1h30") | Use "1h 30m" format. |
| 403 | Missing permissions | Check Jira user permissions for the project. |
| 404 | Version not found | Verify version name/ID exists. |
| 429 | Rate |
How can I help you explore Laravel packages today?