Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Redmine Api Laravel Package

kbsali/redmine-api

PHP client for the Redmine REST API that simplifies integrating Redmine into your applications. Access projects, issues, users, time entries, versions, and more through a clean, object-oriented interface with straightforward authentication and response handling.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture fit. Unchanged, and marginally reinforced. kbsali/php-redmine-api remains a framework-agnostic PHP SDK over the Redmine REST API with no Laravel coupling — no service provider, facade, config publishing, or Eloquent models. It belongs behind a domain-owned interface (RedmineGateway / IssueRepository) as an infrastructure adapter, injected via the container and consumed by application services and queued jobs. v2.9.1 adds a fromHttpClient construction path (via ClientApiTrait), which means the SDK can be built around a client instance the application already owns rather than one it constructs internally — a meaningful architectural improvement because transport concerns (middleware, retry, logging, stubbing) can now be centralized in the app's container binding instead of duplicated around the SDK. Fit verdict is unchanged: good for a bounded Redmine integration, poor if the team expects a batteries-included Laravel package.

Integration feasibility. Slightly better than assessed. Installation is still composer require plus config plus a singleton binding plus a thin wrapper, and the SDK still performs its own HTTP transport, so Http::fake() will not intercept it. The change is that tests and production wiring can now share a single injected client: a mock/stub handler stack for adapter tests, and middleware for structured logging and retries at the transport layer rather than wrapped around every call site. The one-time design cost (mock at the wrapper interface, or inject a mock client) is unchanged in kind but now cheaper to pay. v2.9.1 is patch-level with no breaking changes and no deprecations, so the bump itself carries no integration work.

Technical risk. Medium, with two exposures reduced and one clarified:

  • Transport/dependency coupling — reduced. Because the SDK can now be constructed from an app-resolved PSR-18/Guzzle client, the app can standardize on one Guzzle version and pass it in, rather than depending on the SDK's internal resolution. Confirm the fromHttpClient signature and the SDK's minimum client contract during the spike; Guzzle version skew remains the most likely install-time failure but is now one version decision instead of two.
  • Data-shape fidelity — partly addressed. Issue::update() can now unset fixed_version_id (fixes #466). This closes a real write-path defect: previously a partial update could not distinguish "leave field unchanged" from "clear the field," so optional assignments silently stuck. Treat this as evidence of a bug class rather than a one-off — verify whether other optional fields (assignee, category, parent, due date) have the same null-vs-absent problem before designing write-back flows around them.
  • Redmine version surface — unchanged. Custom fields, status transitions, and endpoint behavior still vary by Redmine major version; behavior must be pinned against a known server version.
  • Bus factor and maintenance signal — improved. This release shows a maintainer (Art4) driving cadence, an outside contributor merged (@martinvonwittich, first contribution), a bugfix accepted from the community, and an explicit housekeeping PR staged "for v2.10.0." That is a healthier signal than a lone-maintainer project coasting on a single release, and it answers the previously open question about commit cadence. Treat the star/follower data-quality caveat as unchanged; it was never the verdict.
  • No native webhooks/push — unchanged. Redmine does not reliably push events, so sync remains polling-based and must be designed for it.

Key questions. Which Redmine version(s) must be supported, and who owns the server side? Read-only or write-back (issue creation, status transitions, time logging)? Which auth model is permitted by the Redmine admins? Is Redmine a system of record or transitional? What data volume and latency tolerance? Are custom fields in scope, and is their schema stable? Two additions: does the write path need to clear optional fields (now supported for fixed_version_id only — what else)? And does upstream's stated "housekeeping for v2.10.0" signal deprecations we should plan around?

Integration Approach

Stack fit. Laravel 9+ on PHP 8.1+ remains a clean fit. Register a single bound instance as a singleton in a dedicated service provider, configured from config/redmine.php reading services.redmine.* env vars. Prefer the fromHttpClient path: resolve the app's own PSR-18/Guzzle client from the container and hand it to the SDK, so retry policy, timeouts, and structured logging live in one transport configuration. Wrap the instance in an application-owned interface so controllers, jobs, and console commands never touch the SDK directly. Writes through queued jobs; reads behind a cached repository where data is not time-critical.

Migration path. Unchanged, and the v2.9.1 bump does not perturb it. Do not rewrite call sites: introduce the interface plus a legacy adapter delegating to existing code, get tests green, then implement the new adapter and swap the container binding. If Redmine is a retirement candidate, the interface boundary is what makes that a later, cheaper decision. The fixed_version_id fix means any existing workaround (direct API calls or post-update cleanup) can be retired and consolidated into the adapter.

Compatibility. v2.9.1 is a patch release — no breaking changes, no deprecations, drop-in. Pin to 2.9.1 and treat it as the settled baseline for the integration. The real compatibility gate now sits one release ahead: upstream has already landed a housekeeping PR "for v2.10.0," so read that changelog carefully for deprecations before bumping, and re-run the dependency dry-run (composer update --dry-run resolving SDK, Guzzle, and existing app HTTP dependencies together) at that point rather than at every patch. Confirm PHP constraint coverage against the runtime matrix and PSR-3 logging alignment.

Sequencing. Six steps, roughly one to two sprints:

  1. Bump and smoke test (half a day). Move to 2.9.1, run the existing adapter test suite, confirm fromHttpClient behaves as expected against a non-production Redmine.
  2. Spike (1–2 days). Authenticate, list and fetch one issue, and prove the injected-client path with a mock handler; confirm Guzzle/PSR-18 compatibility.
  3. Adapter and config. Interface, wrapper implementation using the injected client, service provider binding, secrets in env/secret manager, transport middleware for logging and retries, error mapping.
  4. Read vertical slice. One real use case end-to-end (issue dashboard or sync job) with pagination and caching, plus tests against a mocked adapter or stubbed client.
  5. Write path. Creation/update behind a queue with rate limiting, retry policy, and deduplication; include explicit tests for clearing optional fields, not just setting them.
  6. Hardening and rollout. Observability, alerting on auth failure and error-rate spikes, runbook, staged environment rollout.

Operational Impact

Maintenance. Low and slightly improved. The library is thin, MIT-licensed, and this release shows a maintainer actively triaging and merging community fixes rather than letting the project drift — which raises confidence in the "review upstream releases" allocation to something genuinely routine. The recurring burden remains the wrapper and the schema assumptions, both owned internally. Keep a fork-and-patch contingency, but the urgency is lower than a dormant single-maintainer project would justify. Schedule one calendar review at the v2.10.0 release rather than tracking every patch.

Support. Unchanged. No vendor SLA, no commercial support path, community issues best-effort. Internal ownership remains mandatory: a named directly responsible engineer, a documented runbook, and no tribal knowledge. Escalation for Redmine-side problems runs through whoever operates the Redmine instance, identified up front. The visible external-contributor activity slightly raises the odds that an upstream issue gets a response, but that is not a commitment to plan against.

Scaling. Unchanged. Redmine is the bottleneck, not PHP. Each call is a synchronous round trip, and issue lists with associations are slow under load. Design for explicit page sizes, aggressive caching of slow-moving reference data (projects, users, trackers, statuses), batching where allowed, and queue workers with a concurrency cap so a backfill does not degrade the instance for human users. Never call the API in a user-facing request path where a cached or precomputed result would do.

Failure modes. Plan explicitly for: credential rotation and 401s; 403 on insufficient permissions; 404 on deleted or inaccessible records; 422 on validation and required custom fields; 5xx and timeouts under load; partial writes where a create succeeds and a later update fails; duplicate records on retry, since Redmine offers no idempotency keys — dedupe on your side using a natural key or stored external ID; pagination drift when records are created mid-sync; attachment size limits; and timezone mismatch between application and Redmine configuration. One item can be closed: "cannot clear an optional field" is fixed for fixed_version_id as of v2.9.1. Do not generalize it — the null-vs-absent semantics of other optional fields are unverified and should be treated as a live failure mode until tested. Each of these needs a defined behavior and an alert, not an unhandled exception.

Ramp-up. Unchanged. A mid-level Laravel developer with no Redmine exposure should be productive in one to two days; the API concepts are conventional and the SDK's method names are self-describing. The genuine learning curve is Redmine's permission and workflow model, not the PHP library. The TPM's leverage is unchanged: insist on the adapter boundary, the dependency-compatibility spike, and the deduplication strategy before the first write path ships. Add one item — require explicit test coverage for field-clearing behavior on every optional field the write path touches, since v2.9.1 demonstrates that this class of bug ships silently and surfaces as stale data in production rather than as an error.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource