Skip to content

[pull] 12.x from laravel:12.x#254

Merged
pull[bot] merged 11 commits intoziming:12.xfrom
laravel:12.x
Mar 16, 2026
Merged

[pull] 12.x from laravel:12.x#254
pull[bot] merged 11 commits intoziming:12.xfrom
laravel:12.x

Conversation

@pull
Copy link
Copy Markdown

@pull pull bot commented Mar 16, 2026

See Commits and Changes for more details.


Created by pull[bot] (v2.0.0-alpha.4)

Can you help keep this open source service alive? 💖 Please sponsor : )

Jacobs63 and others added 11 commits March 16, 2026 08:23
…#59231)

* Lazily evaluate value for constraints in `HasOneOrManyThrough`

* Move `localValue`
* Introduces the string helper to get the initials for a given string, optionally returning them in uppercase.

* Adding fluent support

* styleCI fixes

* StyleCI fixes

* StyleCI fixes
…59224)

When `zlib.output_compression` is enabled in PHP, the child process
  appends gzip-compressed binary data (magic bytes \x1f\x8b) to stdout
  after the serialized JSON payload. This corrupts `json_decode`, which
  returns null and triggers an "array offset on null" error on the
  parent side.

  Detect the gzip magic bytes in the child process output and truncate
  before decoding. This is non-intrusive — no configuration changes are
  required from the user, and unaffected environments see zero behavior
  change.

  Fixes #59112
…ution (#59220)

When resolving class-typed dependencies, Util::getParameterClassName()
is called in resolveDependencies() to determine if the parameter is a
class type, then called again inside resolveClass() to get the same
class name. This performs redundant reflection work (getType(),
isBuiltin(), getDeclaringClass()) on every class-typed parameter.

Capture the result in resolveDependencies() and pass it to
resolveClass() to avoid the double call.
)

When generating validation error messages, replaceIndexOrPositionPlaceholder
and replaceInputPlaceholder run on every message even when the message does
not contain :index, :position, :ordinal-position, or :input placeholders.

The ordinal-position replacement is particularly expensive as it calls
Number::ordinal() via the intl extension for every numeric segment in
the attribute name.

For large array validation with many errors (e.g. 500 items failing
validation), this adds significant overhead since these placeholders
are rarely used in standard validation messages.

Adding a str_contains check before doing the work skips the unnecessary
processing entirely.

Before: 259ms for 2500 validation errors
After:  104ms for 2500 validation errors (-60%)
Replace array_merge() in a loop with array_push(...$items), reducing
the complexity of MessageBag::all() from O(n²) to O(n).

The current implementation copies the entire accumulated array on every
iteration via array_merge(). For large validation error sets this
compounds quickly:

  500 fields (1000 messages): 0.43ms → 0.05ms (-89%)
  200 fields (400 messages):  0.08ms → 0.02ms (-77%)
  100 fields (200 messages):  0.03ms → 0.01ms (-63%)

No change at small sizes (1-10 fields): 0.0002ms → 0.0002ms.

A previous attempt at this optimization (PR #57406) was rejected due to
a benchmark showing regression at small field counts. That benchmark
was measuring noise at the microsecond level — on current PHP versions,
all approaches are identical at small sizes.
When using cached routes (route:cache), getByName() constructs a new
Route object from the compiled attributes array on every call. This
involves Router::newRoute(), setFallback(), setDefaults(), setWheres(),
setBindingFields(), block(), and withTrashed() — repeated work for the
same route.

This is called on every request during route matching (match() calls
getByName()), and on every route() URL generation call in Blade
templates. A typical page with 20-50 route() calls in the navigation
rebuilds the same Route objects repeatedly.

Caching the constructed Route by name eliminates this redundancy:

  getByName:  26.3ms → 0.5ms per 10K calls (-98%)
  route():    85.6ms → 50.4ms per 10K calls (-41%)
  match():   176.0ms → 82.8ms per 10K calls (-53%)
@pull pull bot locked and limited conversation to collaborators Mar 16, 2026
@pull pull bot added the ⤵️ pull label Mar 16, 2026
@pull pull bot merged commit e0a3f5c into ziming:12.x Mar 16, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants