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

Schema Laravel Package

krak/schema

krak/schema is a lightweight Laravel/PHP package for defining, validating, and managing application schemas. It provides a simple, framework-friendly API to keep schema logic organized, reusable, and easy to integrate into your project.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture fit. krak/schema positions itself as a declarative data-schema layer — defining shape, then processing (validating, hydrating, or transforming) data against that shape. Architecturally, that places it in the application/domain boundary: the seam between transport (HTTP requests, queue payloads, webhooks, config files) and domain logic. In a Laravel codebase this is a crowded space already served natively by FormRequests, validation rules, casts, and API Resources, and by mature third-party options like spatie/laravel-data or Symfony Serializer.

What v0.2.0 changes about that assessment. Two things. First, the release formalises a struct vs. dict node distinction — a fixed, named-shape node versus an open map/dictionary node. That is the single most important modelling primitive for real payloads (a typed object versus a keyed collection, a record versus a lookup table), and its absence was a plausible reason the abstraction would have collapsed under nested and repeated structures. Its presence, plus the fact that dict usage was replaced by struct rather than coexisting, suggests the author is converging on a coherent type model rather than bolting on features. Second, the release references feature tests for Symfony config, which implies the schema layer can describe and round-trip Symfony Config component trees — i.e. the same declaration can drive configuration validation, not just request validation.

That second point is the differentiated use case the previous assessment could not identify. Laravel validation, FormRequests, and spatie/laravel-data are all request/payload-oriented; none of them give you a portable declaration that validates application or package configuration. If the package genuinely models config trees, it competes in a space with far weaker native coverage (raw config/*.php arrays validated by hand, or Symfony's TreeBuilder). The pitch becomes: one schema formalism for inbound payloads and config, with the Symfony config integration as proof the formalism is general. That is a real gap — but it is currently evidenced only by test code, not by documentation or a stated public API.

Integration feasibility. Mechanically still low-friction: Composer package, PSR-4, installable and exercisable in isolation. The Symfony config signal adds a caveat — if the package depends on symfony/config (or the dumper classes referenced in the release notes), we inherit a version-alignment constraint against whatever Symfony components Laravel already pulls in. That is usually benign but must be checked in composer why, not assumed. There is still no first-party Laravel service provider implied; wiring remains ours.

Technical risk. Still high, and the release cuts both ways.

Positive: the project is not dead. There is a maintainer actively reshaping the type model, writing feature tests, and fixing fidelity bugs. That is materially better than a frozen 2020 artifact.

Negative, and decisive for planning:

  • The release is an explicit BC break at 0.2.0. No BC policy, no deprecation shim, and the break is in the core type vocabulary (dict → struct), which means every existing schema declaration would need rewriting. We would be adopting a package whose author has demonstrated willingness to break the model at minor versions. That is defensible pre-1.0 and normal for a young library — but it means we must budget for it.
  • A release is not a maintenance track record. One release after a long dormancy does not establish cadence, responsiveness to issues, or downstream compatibility pressure. Dependents are still ~zero, so there is no community bug-finding.
  • Runtime compatibility is still unverified. Nothing in the notes establishes PHP 8.1–8.3 or Laravel 10–12 support; the test changes described are about assertion fidelity, not a version matrix.
  • The config integration is test-only evidence. "Updated feature test for Symfony config" tells us the capability exists; it does not tell us it is a supported, documented, stable API. The bug it fixed — the dumper reference failing to capture certain option types on config nodes — is exactly the kind of round-trip fidelity gap that bites a config-generation use case, and its presence confirms the surface is still settling.
  • Security surface unchanged: if it deserialises arbitrary input, review it explicitly.

Key questions to resolve before any commitment.

  1. Is the struct/dict model now stable, or is a further reshaping (unions/variants, nullable/optional semantics, collections of structs) planned for 0.3.0?
  2. Does the Symfony config integration form part of the supported public API, and is it documented — or is it incidental test coverage?
  3. Which PHP, Laravel, and Symfony component versions are actually CI-tested?
  4. Is the package standalone, or coupled to the broader KrakPHP framework?
  5. What is the license, and are we permitted to fork and maintain internally? (Now more important: fork may be needed to survive the next 0.x break.)
  6. What is the measurable gap versus spatie/laravel-data, Laravel validation, hand-written DTOs, and hand-rolled config validation? The config angle is the strongest candidate — verify it before falling back to the payload angle, where the gap is thinner.
  7. Test coverage and static-analysis cleanliness — can we get it green on PHPStan at a level we accept?

Integration Approach

Stack fit. PHP/Laravel, Composer-managed — no infrastructure, no runtime services, no data store. A pure library, so fit is entirely about whether its abstraction matches our domain modelling style. Best fit remains as an internal anti-corruption layer: schemas describe our contracts and configuration, domain objects stay free of it.

Reframed pilot target. The config-schema capability changes where I would trial it. The highest-value, lowest-blast-radius pilot is now configuration validation — a package-level or service-level config tree declared once, validated on boot and in CI — rather than inbound HTTP payloads, where native tooling is strong and the package must beat it on merit. Config validation is a genuine gap, is not on the request hot path, and fails loudly in tests rather than in production.

Migration path. Do not adopt horizontally. Introduce it behind a thin internal interface (e.g., SchemaProcessor with parse(), validate(), hydrate(), and a describeConfig() surface) so the concrete implementation is swappable. That wrapper is the real deliverable; the package is an implementation detail. v0.2.0 is the concrete argument for this: a dict→struct rename should have been a one-file change in our codebase, not a sweep. Pin the dependency to an exact version, not a caret range, until the type model stabilises.

Compatibility. Build the compatibility matrix in a disposable branch before any product code: PHP 8.2/8.3, our Laravel support window, aligned Symfony component versions (composer why symfony/config), PHPUnit alignment, and a static-analysis pass. Treat red as a fork-and-patch decision point, not something to work around in application code.

Sequencing.

  1. Upgrade rehearsal (half a day). Re-run the 0.1.0 spike against 0.2.0 specifically to size the BC break and diff the type model. The cost of this exercise is the data we need on future breakage cost.
  2. Spike (1–2 days). Model three real schemas — one flat struct, one nested struct, one dict/map with variant values — plus one real config tree. Exercise validation and hydration on the payloads and validation plus round-trip on the config.
  3. Gap analysis. Side-by-side against native validation, spatie/laravel-data, and hand-rolled config validation. Score on expressiveness, error quality, and boilerplate removed. Decide which of the two use cases (payload vs. config) is the wedge.
  4. Compatibility gate. Version matrix plus static analysis; adopt vs. fork vs. reject.
  5. Pilot. One bounded, non-critical context behind the internal interface — config schema for a non-critical package is the preferred first target.
  6. Review gate. Measure defect rate, developer feedback, and upgrade friction over one release cycle, and specifically watch whether 0.3.0 breaks the model again.

Operational Impact

Maintenance. The upstream-maintenance assumption needs revising but not reversing. Move from "assume zero" to "assume sporadic, uncommitted maintenance" — a release exists, a cadence does not. With no dependents and no published BC policy, the default planning assumption is still that breakage arrives without warning. Budget a named owner for a fork or a patch backlog. The hidden cost is not bug-fixing; it is the recurring tax of an unpinned dependency in every framework upgrade, now compounded by 0.x type-model churn.

Support. Still no vendor, no SLA, no community to escalate to. Internal documentation and a runbook remain mandatory. The v0.2.0 break adds a specific obligation: a written migration guide for our own schema declarations, since the package will not provide deprecation paths.

Scaling. As an in-process library it scales with the application; no separate capacity to plan. The scaling question is per-request cost on large or deeply nested payloads, and whether struct/dict nodes are compiled once or walked per validation — the 0.2.0 rewiring makes it worth re-benchmarking rather than trusting prior assumptions. The config use case is boot-time and therefore low-risk on throughput.

Failure modes to design against.

  • Minor-version BC break — now an observed, not hypothetical, failure mode. A 0.3.0 type-model change invalidates existing schemas. Mitigate with exact version pins, a wrapper with a single implementation point, and a scheduled upgrade-rehearsal step.
  • Config round-trip fidelity — the fixed dumper bug shows the config path can silently misdescribe option types. Treat generated/validated config output as a contract with snapshot tests, not as trusted output.
  • Silent coercion — type juggling that accepts malformed input instead of rejecting it. Test with adversarial payloads early, especially across the new struct/dict boundary.
  • Schema drift — declarations diverge from actual contracts with no generated artifacts to catch it. Contract tests.
  • Upgrade breakage — a PHP or Laravel bump surfaces a fatal in an unpinned, low-activity dependency mid-upgrade. Mitigate by pinning and by keeping the wrapper thin enough to swap.
  • Abandoned-dependency lock — the package blocks a framework upgrade and no one can patch it quickly. Make the fork decision pre-emptively, not during an incident.
  • Symfony component version conflict — dependency resolution friction against Laravel's own Symfony pins. Verify at install time.

Ramp-up. The API surface is likely small enough for a senior engineer to become productive in one to two days, most of that reading tests rather than docs — and now specifically reading the struct/dict tests, since that distinction is the concept most likely to be misapplied (a struct used where a dict belongs produces subtly wrong validation rather than an error). Team-wide fluency is a separate cost: without official documentation, expect tribal knowledge to concentrate in one or two people unless we write the guide ourselves. Net position after v0.2.0: slightly more favourable than before — the project is alive and the type model is converging, and the config-validation use case gives us a differentiated reason to look — but the BC break confirms the package is not yet a foundation. Run the spike, lead with the config use case, and continue to weight the decision toward our internal abstraction rather than the package itself.

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.
se7enxweb/flysystem
lampwick/laravel
jeslage/statamic-emojis
micahdshackelford/rmap-laravel
draftsmaninc/draftsman
square-bit/laravel-volition
himito/laravel-mailman
htinlynn/genius-helper
maco-studios/hephaestus
elmogy/larafast
xeviant/laravel-paystack
gorilladash/laravel-website-sdk
martialbe/flysystem-oss
chondal/3312client
jeroen-g/flickr
opscale-co/nova-genbi
itsjustvita/laravel-retention
tequilarapido/trackit
gregsphotography/site-builder-filament
cabaoctavio/laravel-query-log