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

Core Laravel Package

articulate-orm/core

Core foundation for Articulate ORM, providing model mapping, fluent query building, relationships, and hydration for expressive, Eloquent-style database access in PHP. A lightweight base for maintainable data layers, clean persistence logic, and flexible Laravel/PHP integration.

View on GitHub
Deep Wiki
Context7

Getting Started

  • Start with the README's new storage-vs-domain-boundary section (added in 2.0.0). It is the shortest path to understanding the package's design stance: persistence concerns stay in the storage layer, domain objects stay clean. Read it before writing any mapping code, because it explains why the package pushes certain patterns that look unusual if you're coming from Eloquent.
  • Install the 2.0.0 line explicitly (^2.0). If you are on 1.2.x, treat this as a real migration, not a patch — the optimistic locking rewrite changes the shape of version-guarded models.
  • First use case: take one aggregate with a natural slice boundary (tenant, account, region, document) and wire up per-slice optimistic locking. That single exercise touches the package's core value proposition — concurrent writes confined to a slice shouldn't collide across slices.
  • Verify the version column(s) exist and are configured per slice before you enable guards. The v2 model assumes a slice-scoped version, not a single global row version.
  • Only after locking works should you move on to cursor pagination of large ordered lists, since the 2.0.0 cursor fixes change how ordering keys are interpreted.

Implementation Patterns

  • Per-slice version guards (optimistic locking v2). Model your slice key explicitly and let the version counter be scoped to it. In practice: writes to slice A and slice B no longer contend, so hot-tenant workloads stop producing spurious conflict retries on unrelated rows. For day-to-day use, wrap writes in a retry loop that re-reads the slice and reapplies the change on a version mismatch — conflicts are expected outcomes, not errors to bubble to the user.
  • Keep the boundary honest. Follow the storage-vs-domain split: hydrate domain objects from storage, mutate them, hand them back for persistence. Avoid reaching into storage-layer constructs from domain code; when you need a new query shape, add it on the storage side rather than leaking conditions outward.
  • Cursor pagination on ordered lists. The 2.0.0 normalization means non-scalar order columns (dates, enums, casts, backends that hand back objects instead of scalars) are coerced into a stable, encodable cursor value. Use cursor pagination for any feed or export that has a deterministic ordering, and make sure the ordering columns are part of your index — the package now trusts your ordering instead of quietly producing a broken cursor.
  • Fail loudly, handle deliberately. Cursor-extraction failures are no longer swallowed. Wrap cursor-producing calls where malformed user-supplied cursors are possible (API ?cursor= params) and translate the exception into a 400 rather than a 500. Elsewhere, let it throw — a silently degraded cursor is worse than a visible failure.
  • Integration tips. Keep slice keys and version columns in one place (a base mapping or trait) so you don't drift between aggregates. In tests, assert on conflict behaviour explicitly: two concurrent writers on the same slice should produce exactly one winner and one retryable conflict; two writers on different slices should both succeed.
  • Workflow. Because locking semantics changed, add a CI step that exercises a concurrent-write scenario against a real database, not just mocks — the previous global-version behaviour may still pass trivially in single-threaded unit tests.

Gotchas and Tips

  • 2.0.0 is a breaking release. If you have existing version columns written as a single row-level counter, they will not map cleanly onto per-slice guards. Plan a migration of both the column layout and any in-flight optimistic-locking retry code.
  • Conflict retries need a bound. With slice-scoped versions, contention per slice is higher than a coarse global counter would suggest. Cap retries (and randomise backoff) so a genuinely contended slice doesn't spin indefinitely.
  • Cursor failures are now visible. Logs and error trackers that were previously quiet will start surfacing cursor-extraction errors that were being discarded. Triage them as ordering/typing bugs, not as package regressions.
  • Ordering must be deterministic. Non-scalar normalization makes values encodable, but it can't rescue an order-by that isn't unique. Always include a tiebreaker column (id or similar) in the order clause or you'll get duplicate/skipped rows across pages.
  • Debugging locking. When a write silently no-ops or returns a conflict, log the slice key and the version you expected versus the version found. Almost all "lost update" reports end up being a stale slice key in the caller, not a package bug.
  • Extension points. Keep persistence mapping in the storage layer so you can add guards, cursor behaviour, and custom typecasting per aggregate without touching domain objects. The 2.0.0 docs frame this as the intended extension surface — use it rather than subclassing internals.
  • CI badge / mutation pipeline changed in this release (empty-commit fix). If you mirror upstream's CI setup, re-check that your mutation-report job isn't generating no-op commits.
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.
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
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