Restaurant Menu Management

Filament 3

Demonstrates how to create nested resources, with restaurant menu categories and dishes. You can reorder Categories and Dishes in the Filament table.

Screenshot 2023-10-24 at 16.03.20

Get the Source Code:

Only This Example

$9

One-time payment

Full source code for Restaurant Menu Management
Downloadable ZIP file with the source code
Lifetime access to this example
GitHub Sign in with GitHub to buy

Sign in first, then complete your $9 checkout.

Best value — all 175 examples

FilamentExamples Membership

$99 /year
or
$199 lifetime
Access to code of all 175 examples
Future new examples and updates included
FilaCheck Pro package licence included
MCP server included
View membership plans

30-day money-back guarantee

How it works

In this project, we have two Models:

  • Category
    • name
    • position (for list ordering)
    • dishes (HasMany relationship)
  • Dish
    • name
    • price (stored as cents)
    • position (for list ordering)
    • category (BelongsTo relationship)

Models

Here are the contents of both models with fields and relationships defined.

app/Models/Category.php

namespace App\Models;
 
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasMany;
 
class Category extends Model
{
use HasFactory;
 
protected $fillable = ['name', 'position'];
 
public function dishes(): HasMany
{
return $this->hasMany(Dish::class);
}
}

app/Models/Dish.php

namespace App\Models;
 
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
 
class Dish extends Model
{
use HasFactory;
 
protected $fillable = [
'category_id',
'name',
'price',
'position',
];
 
public function category(): BelongsTo
{
return $this->belongsTo(Category::class);
}
}

Category Resource And Nested Pages

First, we need a way to abstract this functionality to have nested resources. The main idea is for every child page to have a parent resource. For that reason, we implement this trait.

app/Filament/Traits/HasParentResource.php

namespace App\Filament\Traits;
 
use Exception;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\ModelNotFoundException;
 
trait HasParentResource
{
public Model|int|string|null $parent = null;
 
public function bootHasParentResource(): void
{
if ($parent = (request()->route('parent') ?? request()->input('parent'))) {
$parentResource = $this->getParentResource();
 
$this->parent = $parentResource::resolveRecordRouteBinding($parent);
 
if (! $this->parent) {
throw new ModelNotFoundException();
}
}
}
 
public function getParentResource(): string
{
if (! isset(static::$parentResource)) {
throw new Exception('Parent resource is not set for ' . static::class);
}
 
return static::$parentResource;
}
 
protected function applyFiltersToTableQuery(Builder $query): Builder
{
return $query->where(str($this->parent?->getTable())->singular()->append('_id'), $this->parent->getKey());
}
 
public function ...
The FULL tutorial is available after the purchase: in the Readme file of the official repository you would get invited to.