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

Php Request Class Laravel Package

carsdotcom/php-request-class

carsdotcom/php-request-class adds structured request objects to Laravel, letting you wrap input parsing, validation, and typed access in dedicated classes instead of cluttering controllers. Keeps request handling clean, explicit, and easy to test.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture fit. The package sits at the HTTP boundary of the application: it wraps Guzzle transfers, owns response parsing/post-processing, and writes structured log entries per request. v2.0.0 does not change that architectural position or the public shape of the log entry — writeLog() still builds [$this->toGuzzle(), $this->response, $outcome, $this->requestStats]. The change is to when log() is invoked and what is appended to that array. That is a narrow architectural blast radius, but it lands squarely on the observability layer, which is the component teams tend to understand least and depend on most during incidents.

Integration feasibility. Feasible with a bounded audit. The release notes are unusually explicit about the migration surface and provide four concrete greps/checks:

  1. every function log( override that does not call parent::log();
  2. the contents of parseResponseString()/postProcess() exception messages and getExtendedData(), now written to the same log entry as the response body;
  3. postProcess() implementations that reject with anything other than a Throwable;
  4. tooling/tests that parse log files structurally (blank-line-delimited sections).

The responseFromCache() pattern used by PreQualifyStrangerRequest continues to work unchanged with no double-write, which materially reduces migration risk for consumers who solved cache-hit logging the older way.

Technical risk. Two items are high severity, and both are silent failure modes rather than crashes:

  • Logging failure masks the real failure. LogFile::put()'s array_map(stringify_body, $contents) runs outside its own try/catch and aborts entirely on the first exception. If postProcess() rejects with a non-Throwable, non-serializable value (resource, closure, circular structure), nothing is written — including the Request/Response section that would otherwise have succeeded — and the logging exception becomes the promise's rejection reason instead of the actual error. This converts a formatting defect into lost diagnostics and a misleading error surface. Prior to this release that code path was only ever exercised with Guzzle's own Response/Throwable types, so existing test coverage is unlikely to catch it.
  • New content in existing log entries. Exception messages and getExtendedData()/->errors() now land in the same entry as the response body. Any payload or PII that was previously confined to exception handling now sits in the log sink. This is a data-handling review, not a code review, and may engage compliance.

Medium risk: overrides of log() that replace base logic without parent::log() will now fire on cache hits, which can inflate log volume on high-cache-hit endpoints and, if the override emits its own entry, change file counts despite the note's reassurance that cache-miss counts are unchanged. Low risk (cosmetic): response body appearing twice in transfer-level exception entries, which breaks naive section-count assertions.

Key questions.

  • What are the PHP and Guzzle version requirements for v2.0.0, and is there a documented upgrade guide beyond these notes?
  • Is postProcess() rejecting with a non-Throwable a supported contract we should harden against, or is it "undefined behavior, don't do that"? This determines whether we need a defensive wrapper or just a lint rule.
  • Can stringify_body() be made non-fatal (per-section try/catch) in a follow-up, so a single unserializable section cannot suppress the whole entry? This is the single highest-value hardening ask.
  • Is responseIsFromCache publicly readable, so our overrides can add the guard without relying on an internal property?
  • What is the expected log volume delta for our highest-cache-hit endpoint?
  • Does the package pin a semver major that will auto-resolve? If a ^1 constraint exists, we are unaffected until we opt in; if anything floats to * or dev, treat as urgent.

Integration Approach

Stack fit. Nothing in the release notes indicates Laravel-specific coupling — the affected seams are AbstractRequest::log(), responseFromCache(), writeResponseToCache(), parseResponseString(), postProcess(), and LogFile::put(), all plain PHP with Guzzle types. In a Laravel service this layer is typically reached through a service class or a queued job, so the integration work is confined to whichever application classes extend the package's base request. Those classes are the audit surface; count them first, as that number sizes the whole effort.

Migration path. Sequence for reversibility:

  1. Inventory before touching versions. Grep the application for function log(, responseFromCache(, writeResponseToCache(, postProcess(, and parseResponseString( overrides. Produce a list with owner per file.
  2. Pre-apply the forward-compatible guards under v1. Add if ($this->responseIsFromCache) { return; } to any log() override that does not call parent::log(). This is a no-op under v1 and correct under v2, so it can ship independently and de-risks the version bump.
  3. Harden postProcess() rejections to throw only Throwable instances. Also beneficial under v1.
  4. Sensitive-data review of every exception message and getExtendedData() payload that reaches a log entry, with sign-off.
  5. Bump to v2.0.0 in a branch, run the suite, diff a golden log sample from a cache hit, a cache miss, a parse failure, and a transport-level failure.
  6. Update tests and log-parsing tooling — anything asserting empty log directories after deliberate parse failures, or an exact count of blank-line-delimited sections.
  7. Simplify opportunistically: migrate responseFromCache() manual-logging classes to overriding log() directly, per the AbstractRequest::log() docblock. Do this after the bump, not as part of it, so the diff stays reviewable.

Compatibility. getLogFolder()-only consumers see no behavioral change — that is likely the majority of the codebase and can be verified quickly. The PreQualifyStrangerRequest cache-hit pattern is explicitly preserved with no double-write. The genuine incompatibilities are all in the override layer described above. Confirm the composer constraint is exact or caret-pinned to ^1 before merge so the bump cannot arrive unscheduled via a transitive resolve.

Sequencing. Steps 1–4 are safe, independently shippable, and reversible; steps 5–6 are the atomic cutover and should land together with the parser changes. Step 7 is cleanup. If the override inventory comes back empty or limited to getLogFolder(), this collapses to a version bump plus a log-sample diff and can be done in a single change.

Operational Impact

Maintenance. Low ongoing cost once migrated, but the migration itself creates a durable obligation: the log() contract is now a documented extension point with a guard the base class provides and subclasses can accidentally defeat. Add a code-review checklist item — "does this log() override call parent::log() or replicate the cache guard?" — and, if the codebase supports it, a static-analysis rule. Without that, the same defect will be reintroduced by the next developer who overrides log().

Support. Expect a short tail of confusing reports immediately after adoption: log entries that look different (extra appended section, duplicated body on transport errors), and — worse — endpoints where errors stopped producing log entries at all because a postProcess() rejection poisoned stringify_body(). Support and on-call runbooks that key off log shape should be updated before the bump, not after.

Scaling. File count for cache-miss traffic is unchanged, so steady-state log volume is roughly flat. The scaling risk is concentrated in two places: (a) log() overrides that now fire on cache hits, which puts volume on the cache-hit path that scales with traffic rather than with upstream calls, and (b) the deferred log() call now runs after parsing and post-processing, so it sits later in the request lifecycle — the log write lands closer to response time and includes heavier content (getExtendedData(), ->errors()), increasing per-entry size. Neither is a throughput cliff, but both shift cost from "log per upstream call" toward "log per request."

Failure modes. Ranked:

  • Silent log suppression with error masking (high). Unserializable postProcess() rejection → array_map aborts → zero bytes written → logging exception replaces the real rejection reason. The observable symptom is absence of logs plus a wrong error message, which is the hardest class of incident to diagnose. Mitigation: enforce Throwable-only rejections; press upstream for per-section fault isolation in LogFile::put().
  • Sensitive data exposure (high). Exception messages and extended data now co-located with the response body. Mitigation: data review and sign-off before the bump.
  • Cache-hit log amplification (medium). Unguarded log() overrides firing on every cache hit. Mitigation: the guard from step 2 above.
  • Downstream parser breakage (medium). Tooling asserting section counts or empty log dirs. Mitigation: update parsers and tests in the same change as the bump.
  • Duplicate response body in transport-exception entries (low). Cosmetic; matters only for log-size budgeting and exact-match assertions.

Ramp-up. Small and well-scoped. The release notes effectively serve as the upgrade guide and are precise enough to hand to an engineer as a task list. Budget roughly half a day for the audit and guard work on a codebase with a handful of request classes, plus review time for the sensitive-data pass, plus whatever the log-parser and test updates cost. The main ramp-up cost is conceptual rather than technical: the team needs to internalize that log() is now invoked on every outcome and that the base-class guard is inherited only if you call parent::log(). That single sentence is the whole upgrade.

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.
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core