Common conventions

The shared naming, configuration, model-resolution and data conventions that every OI Laravel package follows

Common conventions

Every package is generated from — and audited against — the same standard. This page summarises the parts you'll notice as a consumer of the packages. (The full authoring standard lives in the internal package-creator skill.)

Naming

Names are derived mechanically from the package slug, so once you know one, you can predict the rest:

ItemRuleExample (oi-laravel-insee)
Composer nameoi-lab/oi-laravel-<thing>oi-lab/oi-laravel-insee
Root namespaceOiLab\OiLaravel<Thing>OiLab\OiLaravelInsee
Service providerOiLaravel<Thing>ServiceProviderOiLaravelInseeServiceProvider
Config file & key<slug>.php / '<slug>'oi-laravel-insee
Publish tags<slug>-config, <slug>-migrations, <slug>-skill, <slug>-stubsoi-laravel-insee-config
AI skill dir<slug> with oi-laravel-oilab-laravel-oilab-laravel-insee
Command prefixone namespace per packagedoc:, seed:, metadata:, publish:

Installation & publishing

Because every package mergeConfigFroms its config in the service provider, sensible defaults exist without publishing anything. Publish only what you want to customise, using the predictable tags:

bash
# Publish a package's config
php artisan vendor:publish --tag=oi-laravel-insee-config

# Database packages also expose a migrations tag
php artisan vendor:publish --tag=oi-laravel-<slug>-migrations

All publishable groups are console-only and tagged <slug>-*. Database packages auto-load their migrations, so publishing them is optional.

Swapping models through config

Packages that ship Eloquent models never hardcode ::class internally — model class names are configuration strings resolved at runtime through a static resolver. That means you can point a package at your own subclass:

php
// config/oi-laravel-notes.php
'models' => [
    'note' => App\Models\Note::class,   // your implementation
    'user_model' => App\Models\User::class,
],

Resolve model classes through the package's facade/resolver (for example OiNotes, OiLaravelAttachments, Insee) rather than referencing the vendor class directly, so your config overrides always apply.

Typed data with spatie/laravel-data

Structured data never crosses a package boundary as a raw array. As soon as a package exposes a model or a structured response, it uses spatie/laravel-data: Data classes, toData(), prop casts, and API DTOs. So return values are typed value objects, not associative arrays — expect ->toData() and typed properties throughout (for example, oi-laravel-umami returns typed DTOs, oi-laravel-settings exposes value objects).

Configuration shape

Config files are plain return [ ... ] arrays with env() defaults and Laravel-style docblock headers. Recurring sections:

  • models.* — swappable class-name strings (see above); user_model defaults to App\Models\User.
  • route.*enabled, prefix, name, middleware, gate for web-facing packages (routes are registered only when route.enabled is true).
  • Feature flags as <feature>.enabled.
  • Disk selection cascades: env('<PREFIX>_DISK', env('FILESYSTEM_DISK', 'local')).

Testing & quality

Every package ships the same quality tooling, so contributions run identically:

  • Pest on top of Orchestra Testbench, with an in-memory SQLite testing connection and RefreshDatabase for database packages.
  • Strict phpunit.xml (failOnRisky, failOnWarning) with split tests/Unit and tests/Feature suites.
  • Laravel Pint ({"preset": "laravel"}) via composer lint.
  • A GitHub Actions matrix — PHP 8.2/8.3/8.4 × Laravel 11/12/13 — on every push.
bash
composer test   # vendor/bin/pest
composer lint   # vendor/bin/pint
Project under MIT License.
Design by