Download the PHP package ozankurt/laravel-modules-core without Composer
On this page you can find all versions of the php package ozankurt/laravel-modules-core. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.
Download ozankurt/laravel-modules-core
More information about ozankurt/laravel-modules-core
Files in ozankurt/laravel-modules-core
Package laravel-modules-core
Short Description Shared bootstrap kit for KurtModules Laravel packages.
License MIT
Informations about the package laravel-modules-core
laravel-modules-core
Shared bootstrap kit for KurtModules Laravel packages.
Requirements
- PHP
^8.4 - Laravel
^13.0 - (Optional) Filament 3, 4, or 5
Installation
What it provides
Kurt\Modules\Core\Providers\PackageServiceProvider— abstract base every kurtmodules service provider extends. Wrapsspatie/laravel-package-toolsand dispatches toregisterFilamentV{3,4,5}based on the installed Filament major.Kurt\Modules\Core\Contracts\UserResolver(+ConfigUserResolver) — resolves the consumer's user model viakurtmodules.user_modelconfig orauth.providers.users.modelfallback.Kurt\Modules\Core\Concerns\ResolvesUser— trait that gives module models auserBelongsTo()helper.Kurt\Modules\Core\Concerns\InteractsWithModuleConfig— sugar forconfig("{module}.key")access.Kurt\Modules\Core\Concerns\AbortsInProduction— trait for Artisan commands;abortIfProduction()blocks demo/destructive commands in production unless--forceis passed. Lets*:democommands drop their hand-rolled guards.Kurt\Modules\Core\Concerns\HasEnumLabels— trait giving string-backed enums a Title-CasegetLabel()and a nullgetColor()default, so downstream enums can satisfy Filament'sHasLabel/HasColorwithout Core requiring Filament.Kurt\Modules\Core\Support\FilamentVersion—::major(),::isAtLeast(),::isExactly().Kurt\Modules\Core\Enums\{Approval,MediaKind,Visibility}— generic cross-module enums.Kurt\Modules\Core\Testing\PackageTestCase— Testbench-backed base test case with an in-memoryuserstable.- API kit —
Http\HttpMode,Http\ApiRouteGroup,Http\Controllers\ApiController,Http\Concerns\HandlesApiQuery,Support\ApiRateLimiter, plus thePackageServiceProvider::registerModuleApi()hook. The config-convention-driven REST foundation every module inherits (see API kit).
Configuration
Publish the config file:
Command & enum helpers
Guard demo/destructive Artisan commands so they cannot run in production without --force:
Give a string-backed enum Filament-ready labels/colors without Core depending on Filament (the enum declares the contracts, the trait supplies the bodies):
API kit
A config-convention-driven foundation for a module's out-of-the-box REST API.
It generalises the loyalty.http.mode pattern so every module exposes a JSON
API the same way, safe-by-default: nothing is registered until a consumer
opts in, and write routes require auth + a Policy.
Config convention
Every consuming module reads these per-module keys (module slug = the value
returned by the provider's module()):
| Key | Default | Purpose |
|---|---|---|
{slug}.http.mode |
headless |
headless | api | ui. API routes register only for api/ui. |
{slug}.http.prefix |
api/{slug} |
URL prefix for the route group. |
{slug}.http.middleware |
['api'] |
Base middleware for every API route. |
{slug}.http.auth_middleware |
['auth'] |
Appended to write (authenticated) routes. |
{slug}.http.rate_limit |
'60,1' |
maxAttempts,decayMinutes for the {slug}-api throttle. |
Every group is throttled by a named limiter {slug}-api (keyed by user id, or
client IP for guests). A module's config/{slug}.php therefore ships:
Base classes
Http\HttpMode—HttpMode::forModule($slug)resolves{slug}.http.mode(unknown →Headless);->apiEnabled(),->is(...).Http\ApiRouteGroup—ApiRouteGroup::attributes($slug, $authenticated = false)returns theRoute::group()array (prefix, mergedmiddleware+ throttle [+auth_middlewarewhen$authenticated],as="{slug}.api.").Http\Controllers\ApiController— abstract base (addsAuthorizesRequests,ValidatesRequests) with a consistent envelope:respond($data, array $meta = [], int $status = 200)→{ "data": …, "meta": … }(metaomitted when empty).respondCreated($data)(201),respondNoContent()(204, empty body).respondPaginated(LengthAwarePaginator $p, ?string $resourceClass = null)→ items asdata(mapped through the resource class when given) +meta.pagination(current_page,per_page,total,last_page).fail(string $message, int $status = 422, array $errors = [])→{ "message": …, "errors": … }.
Http\Concerns\HandlesApiQuery— allow-list-driven query helpers (never interpolate raw input as SQL identifiers):applyApiSorts($q, $r, array $allowed)—?sort=field,-other(leading-= desc); non-allowed fields dropped.applyApiFilters($q, $r, array $allowed)—?filter[field]=value;$allowedis a list of exact fields (['name']) or a mode map (['name' => 'like', 'status' => 'exact']).like→%value%.apiPaginate($q, $r, int $default = 15, int $max = 100)—?per_page=clamped to[1, $max], standard?page=.
Support\ApiRateLimiter—ApiRateLimiter::register($slug)registers the{slug}-apilimiter from{slug}.http.rate_limit.
Resources vs envelope helpers
The envelope's top-level key is data, matching Laravel API Resources. Use
Laravel resources directly (Core ships no resource base) and hand the result
of a resource to the envelope helpers so the payload is wrapped exactly once:
Do not return a bare JsonResource from a route and also call respond()
— that double-wraps as {"data":{"data":…}}.
How a module exposes an API
- Config — add the
httpblock above toconfig/{slug}.php; keepmodedefaulting toheadless. - Resources — define
App-styleJsonResourceclasses for your models. - Controller — extend
ApiController; keep controllers thin over domain services.use HandlesApiQueryon index controllers for sort/filter/paginate. Enforce a Policy on every write ($this->authorize(...)). -
Routes —
routes/api.php, read vs write split viaApiRouteGroup::attributes(): - Provider — wire it in
packageBooted(); it is a no-op in headless mode and registers the rate limiter + route group otherwise:
The outer group (prefix, base middleware, throttle, "{slug}.api." name prefix)
is applied by registerModuleApi(); the route file only distinguishes read vs
write.
Testing
CI runs the same checks on every push and pull request
(.github/workflows/tests.yml), against PHP 8.4 / Laravel 13. Static analysis
is held at PHPStan level 8; the suite runs on Pest 5.
License
MIT © Ozan Kurt
All versions of laravel-modules-core with dependencies
illuminate/contracts Version ^13.0
illuminate/database Version ^13.0
illuminate/support Version ^13.0
spatie/laravel-package-tools Version ^1.93