Download the PHP package spawnflow/spawnflow-laravel without Composer

On this page you can find all versions of the php package spawnflow/spawnflow-laravel. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.

FAQ

After the download, you have to make one include require_once('vendor/autoload.php');. After that you have to import the classes with use statements.

Example:
If you use only one package a project is not needed. But if you use more then one package, without a project it is not possible to import the classes with use statements.

In general, it is recommended to use always a project to download your libraries. In an application normally there is more than one library needed.
Some PHP packages are not free to download and because of that hosted in private repositories. In this case some credentials are needed to access such packages. Please use the auth.json textarea to insert credentials, if a package is coming from a private repository. You can look here for more information.

  • Some hosting areas are not accessible by a terminal or SSH. Then it is not possible to use Composer.
  • To use Composer is sometimes complicated. Especially for beginners.
  • Composer needs much resources. Sometimes they are not available on a simple webspace.
  • If you are using private repositories you don't need to share your credentials. You can set up everything on our site and then you provide a simple download link to your team member.
  • Simplify your Composer build process. Use our own command line tool to download the vendor folder as binary. This makes your build process faster and you don't need to expose your credentials for private repositories.
Please rate this library. Is it a good library?

Informations about the package spawnflow-laravel

Spawnflow

Your entire API request lifecycle in one fluent chain.

Authentication, subject resolution, ownership verification, field-level permissions, validation, and persistence — one expression that reads like a sentence.


Why use this?

In conventional Laravel, adding a new API resource means creating a controller, form request, policy, resource, and wiring routes — five or more files that must agree on the same truth. Spawnflow replaces that with a single config entry and an optional context enum.

Trait What it means
Runtime fluent chain The entire request lifecycle is one method chain, not spread across files
Dynamic subject resolution Models resolve from a URL segment via a registry — no per-resource controllers
Inline authorization Ownership and field permissions live in the chain, not in separate policy files
Minimal file surface New resource = one command (spawnflow:resource --generate), or 1 config entry + 1 enum by hand
Reads like a sentence spawn → auth → resolve → ask → fields → validate → save → present

Built for LLM-assisted codebases

Spawnflow is intentionally optimized for codebases where AI writes the majority of code.

Property Why it matters
One pattern to repeat An LLM doesn't need to coordinate 5 file types per resource
~500 lines total surface The entire Flow class + a context enum fits in a single context window
Exhaustive match expressions PHP enums enforce every permission branch is handled — no forgotten cases
Minimal diff surface Adding a resource is mechanical to generate, easy to review
Explicit chain, no magic No middleware, observers, or policies to hallucinate — the chain says exactly what happens

Installation

Publish the config:


Quick Start

The 3-command path

From an existing table to a registered, permission-aware resource:

--generate reads the table's real columns and foreign keys and writes app/Spawnflow/PostFields.php + PostContext.php. The FieldSet carries #[SpawnSubject('posts', ...)], so it registers itself — no config edit. Every additional resource is one more command. Inference is make-time only: the generated files are the canonical, editable declarations.

Deploy-time: php artisan spawnflow:cache freezes attribute discovery (mirroring Laravel's bootstrap caches); spawnflow:clear unfreezes.

Prefer explicit config? Everything below still works — config entries override discovered ones.

1. Register subjects

Map URL segments to Eloquent models in config/spawnflow.php:

2. Use Flow in a controller

3. Add routes


Chain API

Every method returns $this (fluent) unless noted as terminal.

Method Signature Description
spawn spawn(Request $request): static Entry point. Extracts user and request context.
auth auth(?string $role = null): static Verifies authentication. Optionally requires a role.
resolve resolve(string $subject): static Looks up the subject alias in the registry, instantiates the model.
ask ask(string $method, int\|array $ids): static Ownership verification. Loads the instance (single ID) or validates all IDs are owned (array).
fields fields(?string $contextClass = null): static Resolves field-level permissions from a FieldContext enum. Auto-resolves from config if no class given.
validate validate(?array $rules = null): static Validates request data. Uses context rules when active, or accepts explicit rules.
save save(array $data): static Creates or updates. Strips disallowed fields when a context is active.
delete delete(int\|array $ids): JsonResponse Terminal. Deletes record(s) by ID.
gate gate(Closure $callback): static Arbitrary authorization. Callback receives the Flow; should throw on failure.
after after(Closure $callback): static Post-operation hook for side effects (events, jobs, notifications).
present present(?string $resourceClass = null, int $statusCode = 200): JsonResponse Terminal. Returns JSON response. Filters to visible fields when context is active.
list list(?int $perPage = null): JsonResponse Terminal. Paginated listing with ownership scoping and validated sorting.

Accessors

Method Returns
getUser() ?User
getInstance() ?Model — the loaded record (after ask() or save())
getSubject() ?Model — the unhydrated model class instance
getContext() ?FieldContext
getRequest() ?Request

Field-Level Permissions

Field-level permissions use context enums — PHP enums that encode every role+state combination as a case. Each case declares which fields are editable, what validation rules apply, and which fields are visible in responses.

Define a context enum

Scaffold one from the stub:

Then fill in the editableFields(), validation(), and visibleFields() cases:

Register it

How it works

When you call ->fields(PostContext::class):

  1. The enum's resolve() inspects the user and record to pick a case (e.g., OwnerDraft)
  2. ->validate() uses that case's validation() rules
  3. ->save() strips any fields not in editableFields()
  4. ->present() filters the response to visibleFields()

If the resolved case has zero editable fields (e.g., Viewer), the chain throws ForbiddenFieldAccessException immediately.

The discriminated union concept

Each context enum case is a discriminated union variant. The value string (e.g., "owner:draft") acts as the discriminator. This maps directly to TypeScript discriminated unions for frontend type safety:


Generic Controller

SpawnflowController handles CRUD for any registered subject with 4 routes:

Adding a new resource requires zero new controllers and zero new routes — just a config entry and optionally a context enum.


Field Descriptors

Field descriptors make fields type-aware. A FieldSet class per subject declares what each field is — type, widget, label, base validation rules, enum options, relation semantics — so the schema endpoint and the generator can serve frontends everything needed for form rendering and client-side validation, from one declaration.

Register it:

Contexts keep referencing fields by name; the schema layer joins names to descriptors. Subjects without a FieldSet fall back to minimal inferred descriptors.


Eligibility Rules

Context enums answer who may touch a field in what record state. Eligibility rules answer the orthogonal question: given the form's current values, is this field visible/enabled? Rules are declared on descriptors, serialized into the contract, and evaluated identically in PHP and JS — never put role checks in rules.

Groups

Groups are first-class eligibility nodes — sections or wizard steps that accept the same rule envelope. A hidden group hides its members regardless of their own rules (AND-composition):


Centralized Validation

Rules live once — on the field descriptors, with per-context overrides — and every consumer enforces the same thing:

1. The chain. validate() with no arguments sources rules automatically: explicit argument → context validation() per field → field base rules → descriptor-implied rules (type checks, enum in:, relation exists:{table},{key}, nullability).

2. FormRequests. For conventional controllers, bridge into the same rules without adopting the chain:

rules() resolves the caller's context (record loaded from the route's {id}, synthetic record on create) and returns the same effective rules the chain enforces and the schema endpoint serves.

3. Live validation (Precognition). A request with a Precognition header makes validate() run validation only and halt the chain with 204 + Precognition: true (or the standard 422 on failure). Precognition-Validate-Only: title,email scopes the pass to specific fields — Laravel Precognition frontend helpers work against Spawnflow routes without duplicated rules.


Schema Endpoint

Enable the built-in schema routes to serve field schemas to your frontend:

This registers:

Responses follow the versioned schema contract v1 (docs/schema-contract.md). Validation rules are serialized structurally — mechanically compilable to Zod — with rules a client can't evaluate (database checks, closures) flagged serverOnly.

Resolved variant response:

All variants response carries descriptors once plus per-variant editable_fields, visible_fields, and effective structured rules — a discriminated union keyed by context. See docs/schema-contract.md for the full specification.


Frontend Generation

Generate TypeScript types and Zod schemas from the same contract the schema endpoint serves:

Per subject, one module containing:

Plus index.ts and an optional thin fetch client (emit_client) for SpawnflowController + schema routes.

Zod compilation is honest about its limits: rules a client can't check compile to a trailing /* server: unique */ comment, unmapped rules to /* unhandled: ... */ — nothing is silently dropped.

The generator and the live endpoint emit through one serializer — generated artifacts and API responses cannot drift.


Relation Options

Relation fields get a data source for free. When schema routes are enabled, GET /spawnflow/options/{subject}/{field}?q=&page= serves {value, label} pages from the related model's display column — ownership-scoped by default, unscoped() for shared lookups (countries, plans), q search for searchable() fields. Relation descriptors carry the options_url so renderers wire comboboxes automatically.


Live Invalidation (SSE, opt-in)

GET /spawnflow/events streams change signals whenever a subject is written through the Flow chain — invalidation only, never state. Clients refetch through the endpoints they already use, so a dropped stream degrades to non-live, never to wrong data.

since[subject]=n replays missed changes on reconnect. Each open stream holds a PHP worker — set events_max_polls to recycle idle streams (EventSource reconnects automatically).


Livewire Renderer

Server-rendered Laravel apps get the same machinery with zero JavaScript contract: ONE generic schema-interpreting component (no per-form classes), registered automatically when Livewire is installed.

Owning the Form Source (shadcn registry)

The renderer is also distributed as a shadcn registry item, so the presentational source lands in your repo — restyle it, rewrite it, let your LLM edit it. The contract, evaluator, and client stay versioned in @spawnflow-dx/core:

Registry artifacts build from the same source as the npm package (npm run registry:build in js/react-shadcn) — pick whichever distribution fits: dependency (npm) or owned code (registry).

React Renderer (js/react-shadcn)

@spawnflow-dx/react-shadcn renders complete forms from the schema contract — shadcn-styled widgets, react-hook-form + Zod under the hood:

Live demo

Four forms — registration, change password, edit profile, billing details — plus a persona switcher demonstrating one component rendering three different billing forms from owner:active / owner:past_due / viewer contexts. Backed by a mock client serving contract-v1 JSON; swap in createHttpClient to point at a real API.


Escape Hatches

Use the chain for auth and ownership, then break out for custom logic:

Available accessors

Custom gates

Post-operation hooks


The Last Mile

Spawnflow handles ~80-85% of typical API operations. The remaining 15-20% — the "last mile" — is where generic CRUD ends and custom logic begins.

What Spawnflow absorbs

Operations that seem custom but decompose into CRUD with smart validation:

What stays as custom endpoints

Category Why Chain still helps?
Aggregation / analytics GROUP BY, date bucketing, cross-table joins Yes — spawn → auth → resolve → ask for identity + ownership, then break out
External service calls Spotify lookups, payment processing, S3 signed URLs Yes — spawn → auth for identity context
Webhook receivers No authenticated user, no subject No — these are fire-and-forget event handlers
File / binary operations Uploads, zip streams, CSV exports No — response isn't a model

Even for custom endpoints, the chain's escape hatches (getUser(), getInstance(), etc.) let you reuse auth and ownership without reimplementing them.


MCP Server

The contract is queryable and operable by AI agents over the Model Context Protocol. A thin adapter — every tool delegates to an existing owner (registry, serializer, eligibility, the Flow chain, artisan commands):

Dev tools (introspect schemas, evaluate eligibility verdicts, scaffold resources from real tables, regenerate types) register only in the local environment over stdio. Runtime CRUD tools (opt-in mcp.web, behind auth:api) run the full Flow chain — ownership, contexts, eligibility and wire coercion enforced exactly as over HTTP, returning the persisted record. See docs/mcp.md.


Configuration Reference


Testing

Run the package tests:

The test suite uses Orchestra Testbench with an in-memory SQLite database. All fixtures are self-contained — no application models required. DB-introspection tests (--group=mysql-introspection) run against a real MySQL service in CI and skip locally without one.

JS side (js/): npm test runs the eligibility conformance suite (vitest) against the same resources/conformance/eligibility-fixtures.json the Pest suite uses, plus typecheck and demo build.


Roadmap

See docs/roadmap.md — shipped, in flight, and what stays demand-gated (with the exact triggers that unpark each item).


License

MIT. See LICENSE.


All versions of spawnflow-laravel with dependencies

PHP Build Version
Package Version
Requires php Version ^8.2
illuminate/database Version ^11.0|^12.0|^13.0
illuminate/http Version ^11.0|^12.0|^13.0
illuminate/support Version ^11.0|^12.0|^13.0
illuminate/validation Version ^11.0|^12.0|^13.0
Composer command for our command line client (download client) This client runs in each environment. You don't need a specific PHP version etc. The first 20 API calls are free. Standard composer command

The package spawnflow/spawnflow-laravel contains the following files

Loading the files please wait ...