Resources
A Resource is the class that connects an Eloquent model to the surfaces SeviaFlow can provide. The model and database schema remain part of your Laravel application; a Resource describes columns, fields, filters and optional behavior for that model.
Smallest Resource
Every Resource must point to an Eloquent model. This minimal class can be resolved after it is registered, but it has no custom table or form yet:
use App\Models\Customer;
use SeviaFlow\Core\Resources\Resource;
final class CustomerResource extends Resource
{
protected static string $model = Customer::class;
}
Model
protected static string $model is required. Resource::model() returns this class and throws if it is missing or empty.
Navigation
These optional properties control how the UI labels and groups the item:
protected static ?string $navigationLabel = 'Customers';
protected static ?string $navigationGroup = 'Operations';
protected static ?string $navigationIcon = 'users';
protected static ?int $navigationSort = 10;
protected static bool $shouldRegisterNavigation = true;
Definition Methods
| Method | Purpose |
|---|---|
table(Table $table): Table | Define index columns and filters. Column methods can enable search and sorting. |
form(Form $form): Form | Define create/edit fields and sections. |
show(Form $form): Form | Define show-page fields. Defaults to form(). |
api(ApiResource $api): ApiResource | Opt a Resource into REST/API exposure and define the allowed fields and operations. |
export(ExportResource $export): ExportResource | Configure export field access. |
import(ImportResource $import): ImportResource | Configure import field access and validation reuse. |
events(ResourceEvents $events): ResourceEvents | Register lifecycle event handlers. |
actions(): array | Return per-record Action instances. |
bulkActions(): array | Return BulkAction instances. |
relations(): array | Return relation definitions for related models. |
workflow(Workflow $workflow): Workflow | Define a state field, states and transitions. |
query(Builder $query): Builder | Customize the base Eloquent query before search, filters, sorting and pagination. Use this for per-tenant row scoping. |
tableQuery() still exists for compatibility but is deprecated. Use query().
Example: how Resource definitions fit together
A Resource is a PHP class that extends Resource. The model is required; the other methods are extension points. Most applications start with table() and form(). show() uses the form definition by default. Add API, import/export, events, actions, relations or workflows only when your application needs them.
<?php
declare(strict_types=1);
namespace App\SeviaFlow\Resources;
use App\Models\Customer;
use SeviaFlow\Core\Resources\ApiResource;
use SeviaFlow\Core\Resources\Columns\TextColumn;
use SeviaFlow\Core\Resources\Fields\EmailField;
use SeviaFlow\Core\Resources\Fields\TextField;
use SeviaFlow\Core\Resources\Form;
use SeviaFlow\Core\Resources\Resource;
use SeviaFlow\Core\Resources\Table;
final class CustomerResource extends Resource
{
protected static string $model = Customer::class;
public static function table(Table $table): Table
{
return $table->columns([
TextColumn::make('name')->label('Name')->searchable()->sortable(),
TextColumn::make('email')->label('Email')->searchable(),
]);
}
public static function form(Form $form): Form
{
return $form->fields([
TextField::make('name')->label('Name')->required(),
EmailField::make('email')->label('Email')->required(),
]);
}
public static function api(ApiResource $api): ApiResource
{
return $api
->enabled()
->readable(['id', 'name', 'email'])
->creatable(['name', 'email'])
->updatable(['name', 'email'])
->requiredOnCreate(['name', 'email'])
->useFormFieldRules();
}
}
Here, name and email refer to Eloquent attributes. The column methods control the index table; the field methods build the create/edit form. The API method is opt-in: it exposes only the listed fields when the API adapter is installed and the request passes authentication and authorization. Follow Your First Resource for the full model, migration, registration and panel setup. See Exposing a Resource for API access, and the dedicated guides for actions, relationships, workflows, events and import/export.
Query Customization
This hook changes the base set of rows before SeviaFlow applies search, filters, sorting and pagination. For example, a tenant-aware application can scope records to the current tenant:
use Illuminate\Database\Eloquent\Builder;
public static function query(Builder $query): Builder
{
return $query->where('tenant_id', auth()->user()->tenant_id);
}
Adapt the tenant relation and guest behavior to your own app. A query scope limits visible rows; it does not replace policies that authorize individual operations.
The complete customer example with its searchable table and status filter is available in Your First Resource.
Get Started