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

Arflow Laravel Package

aurorawebsoftware/arflow

ArFlow is a Laravel/PHP package from Aurora Web Software for defining and managing workflows and approval flows. It helps model states, transitions, and process steps around Eloquent records so applications can automate business processes with a lightweight, configurable workflow engine.

View on GitHub
Deep Wiki
Context7

Getting Started

  1. Install and publish

    composer require aurorawebsoftware/arflow
    php artisan vendor:publish --tag="arflow-config"   # check the tag in the README first
    php artisan vendor:publish --tag="arflow-migrations"
    php artisan migrate
    

    Confirm the exact publish tags/namespaces by reading vendor/aurorawebsoftware/arflow/README.md — small packages like this one often ship the config and migrations under a single combined tag.

  2. Look here first, in this order

    • config/arflow.php — the state column name, transition table/column names, and whether definitions are cached.
    • The package's src/ directory: find the trait you add to models (commonly HasWorkflow / InteractsWithWorkflow), the base Transition class, and the Events/ folder.
    • The migrations — they tell you what's persisted (a state column on your model vs. a separate history/audit table). That distinction drives most of your design decisions later.
  3. Wire up your first model

    use AuroraWebSoftware\ArFlow\Concerns\HasWorkflow; // verify actual namespace
    
    class Order extends Model
    {
        use HasWorkflow;
    }
    

    Add the workflow state column to the model's table (usually a string column, e.g. workflow_state) and give it a sensible default in the migration.

  4. First use case: an approval flow. Model draft → submitted → approved | rejected. This is the sweet spot: a handful of states, human-driven transitions, and side effects (notifications, timestamps) that map cleanly onto events. Get one model working end-to-end before adding a second, because workflow config tends to be global and shared.

Implementation Patterns

Define transitions declaratively, not in controllers. Keep the state graph in one place per model (a workflows() method, a config array, or a dedicated definition class, depending on what the package exposes) so the graph is auditable and testable without hitting HTTP.

Guard transitions with policies. Rather than checking $user->isAdmin() inside a controller, put authorization in a Laravel policy and check canTransitionTo() (or equivalent) in a FormRequest or a small TransitionRequest. This keeps the workflow reusable across web, API, and queue contexts.

Treat side effects as listeners, not inline code.

Event::listen(WorkflowTransitioned::class, function ($event) {
    if ($event->to === 'approved') {
        $event->model->update(['approved_at' => now()]);
    }
});

This keeps transition definitions pure and lets you disable side effects in tests.

Centralise the "attempt a transition" call. Put a single transitionTo() wrapper in a service or action class that wraps the call in a DB transaction, dispatches domain events after commit (DB::afterCommit or ShouldDispatchAfterCommit), and returns a result object instead of throwing raw exceptions. Every controller, command, and job then has one code path to reason about.

Expose available transitions to the UI. A method returning [['to' => 'approved', 'label' => 'Approve', 'allowed' => true], ...] per record lets you render buttons without duplicating the graph in Blade/Vue. Cache the definitions (static) but never the per-record allowed list.

Bulk/background transitions. For imports or scheduled jobs that move many records, chunk the query and dispatch one job per transition rather than looping inside a single transaction — you get retries and per-record audit trails for free.

Audit by default. If the package ships a history table, always render from it rather than from the current state column; the "who moved this to approved and when" question arrives within a week of launch.

Gotchas and Tips

  • Column name collisions. If your model already has status, the package's default state column may shadow or conflict with it. Decide early whether status is your workflow state or a separate business field, and rename one. Mixing them is the most common source of "why is my state wrong" bugs.
  • Publish before you migrate. Running php artisan migrate first and publishing afterwards leaves you editing migration files by hand. Publish, read them, then migrate.
  • Concurrency. Two users clicking "Approve" simultaneously will both pass a naive if ($model->state === 'submitted') guard. Wrap the transition in DB::transaction() with lockForUpdate() on the row, or rely on an optimistic-locking/version column if the package supports it. Don't assume the package handles this for you — check the source.
  • Events inside transactions. If a transition listener sends a notification or hits an external API and the transaction later rolls back, you've lied to a user. Use ShouldDispatchAfterCommit / DB::afterCommit on listeners that have external effects.
  • Stale model instances. After a transition, the in-memory model may or may not reflect the new state depending on whether the package calls save() or refresh(). Call $model->refresh() before rendering or re-checking the state to avoid returning a stale value from an API resource.
  • Config/definition caching. If definitions are cached, editing a workflow in code won't take effect in production until you clear cache. Add a deploy step (php artisan optimize:clear or a package-specific cache command) and document it.
  • Enums are tempting but verify support. Laravel enums are great for states, but confirm the package compares with === against strings — passing an enum where a string is expected can silently fail every guard.
  • Testing. Test the graph (every state has an exit, no unreachable states) in one unit test independent of Eloquent, and test transitions via HTTP for the two or three paths that matter. Add a factory state helper (->inWorkflowState('approved')) so feature tests don't have to walk the whole graph to set up fixtures.
  • Extension points to look for: custom guard/callback classes per transition, a before/after hook on the transition object, and a replaceable event class. Subclassing those is almost always cleaner than forking the package — pin the version and keep your customisations in app/.
  • Small-package risk. With zero dependents and no stars, expect thin docs and API churn. Read src/ directly, pin an exact version in composer.json, and keep a thin internal wrapper (your own service class) around every package call so a future swap only touches one file.
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.
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle
glavweb/extra-bundle
glavweb/api-bundle
glavweb/admin-bundle
adachsoft/api-version-bundle
elsayed85/laravel-api-exceptions
ouhssini/laravel-demo-mode
daworks/ncloud-outbound-mailer-driver
gp247/cms
ignibyte/aic-gates
nexa-merchant/blog
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
cgv/localized-resource