Skip to main content
Lyger’s Admin Dashboard system lets you quickly create fully-featured admin panels with CRUD operations, search, pagination, and a modern UI—all with minimal code.

Quick Start

Create an admin controller by extending AdminController:
use Lyger\Admin\AdminController;
use App\Models\User;

class UserAdminController extends AdminController
{
    protected string $model = User::class;
    
    protected array $columns = [
        ['key' => 'id', 'label' => 'ID'],
        ['key' => 'name', 'label' => 'Name'],
        ['key' => 'email', 'label' => 'Email'],
        ['key' => 'created_at', 'label' => 'Joined']
    ];
    
    protected array $searchable = ['name', 'email'];
    
    protected array $fillable = ['name', 'email', 'password'];
    
    protected array $validationRules = [
        'name' => 'required|min:3',
        'email' => 'required|email',
        'password' => 'required|min:8'
    ];
}
That’s it! The AdminController automatically provides index(), show(), store(), update(), and destroy() methods with proper pagination, search, and validation.

Auto-Generated Features

The admin controller provides these features out of the box:
  • Listing: Paginated table with search and sorting
  • Create: Form with validation
  • Edit: Update records with validation
  • Delete: Soft or hard delete with confirmation
  • Search: Full-text search across defined fields
  • Sorting: Click column headers to sort
  • Pagination: Navigate large datasets easily

Admin Panel Builder

Use AdminPanel to generate a complete admin interface:
use Lyger\Admin\AdminPanel;
use App\Models\Post;

$panel = AdminPanel::for(Post::class)
    ->setTitle('Blog Posts')
    ->setColumns([
        ['key' => 'id', 'label' => 'ID'],
        ['key' => 'title', 'label' => 'Title'],
        ['key' => 'status', 'label' => 'Status'],
        ['key' => 'author', 'label' => 'Author'],
        ['key' => 'created_at', 'label' => 'Published']
    ])
    ->setActions(['create', 'edit', 'delete'])
    ->setSidebar([
        ['label' => 'Dashboard', 'url' => '/admin'],
        ['label' => 'Posts', 'url' => '/admin/posts'],
        ['label' => 'Users', 'url' => '/admin/users'],
        ['label' => 'Settings', 'url' => '/admin/settings']
    ])
    ->setTheme('default');

// Render the admin panel HTML
echo $panel->render();

Admin Methods

Index (List)

Get paginated, searchable, sortable list:
public function index(): array
{
    // GET /admin/users
    // GET /admin/users?page=2
    // GET /admin/users?search=john
    // GET /admin/users?sort=name&dir=ASC
    
    return parent::index();
}
Response:
{
  "data": [
    {
      "id": 1,
      "name": "John Doe",
      "email": "john@example.com",
      "created_at": "2026-01-15"
    }
  ],
  "meta": {
    "current_page": 1,
    "per_page": 15,
    "total": 100,
    "last_page": 7
  }
}

Show (Detail)

Get single record:
public function show(int $id): array
{
    // GET /admin/users/123
    return parent::show($id);
}
Response:
{
  "data": {
    "id": 123,
    "name": "John Doe",
    "email": "john@example.com",
    "created_at": "2026-01-15"
  }
}

Store (Create)

Create new record:
public function store(array $data): array
{
    // POST /admin/users
    // Body: {"name": "Jane", "email": "jane@example.com", "password": "secret123"}
    
    return parent::store($data);
}
Response:
{
  "success": true,
  "data": {
    "id": 124,
    "name": "Jane",
    "email": "jane@example.com"
  },
  "message": "Created successfully"
}

Update (Edit)

Update existing record:
public function update(int $id, array $data): array
{
    // PUT /admin/users/123
    // Body: {"name": "John Smith"}
    
    return parent::update($id, $data);
}
Response:
{
  "success": true,
  "data": {
    "id": 123,
    "name": "John Smith",
    "email": "john@example.com"
  },
  "message": "Updated successfully"
}

Destroy (Delete)

Delete record:
public function destroy(int $id): array
{
    // DELETE /admin/users/123
    
    return parent::destroy($id);
}
Response:
{
  "success": true,
  "message": "Deleted successfully"
}

Customization

Override Methods

Customize behavior by overriding methods:
class UserAdminController extends AdminController
{
    public function index(): array
    {
        // Add custom logic
        $users = User::where('is_active', true)
            ->orderBy('created_at', 'DESC')
            ->get();
        
        return [
            'data' => array_map(fn($u) => $u->toArray(), $users),
            'meta' => ['total' => count($users)]
        ];
    }
}

Add Custom Actions

Extend with custom methods:
class UserAdminController extends AdminController
{
    // ... base configuration ...
    
    public function activate(int $id): array
    {
        $user = User::find($id);
        
        if (!$user) {
            return ['error' => 'Not found', 'code' => 404];
        }
        
        $user->is_active = true;
        $user->save();
        
        return [
            'success' => true,
            'message' => 'User activated',
            'data' => $user->toArray()
        ];
    }
    
    public function ban(int $id): array
    {
        $user = User::find($id);
        
        if (!$user) {
            return ['error' => 'Not found', 'code' => 404];
        }
        
        $user->is_banned = true;
        $user->banned_at = date('Y-m-d H:i:s');
        $user->save();
        
        return [
            'success' => true,
            'message' => 'User banned'
        ];
    }
}

Admin Theme

The default admin theme provides a modern, responsive UI:

Features

  • Dashboard: KPI cards, charts, and metrics
  • Data Table: Sortable columns, search, pagination
  • Forms: Create and edit with validation
  • Responsive: Works on desktop, tablet, and mobile
  • Dark Mode Ready: Easy theme customization

Styling

The theme uses Tailwind CSS and Font Awesome:
AdminTheme::render([
    'title' => 'Admin Panel',
    'model' => User::class,
    'columns' => [
        ['key' => 'id', 'label' => 'ID'],
        ['key' => 'name', 'label' => 'Name']
    ],
    'actions' => ['create', 'edit', 'delete'],
    'sidebar' => [],
    'theme' => 'default'
]);
The default theme generates a full HTML page with inline JavaScript. For SPA applications, use the API endpoints directly and build your own frontend.

Complete Example

Full admin setup for blog management:
// App/Controllers/Admin/PostAdminController.php
use Lyger\Admin\AdminController;
use App\Models\Post;

class PostAdminController extends AdminController
{
    protected string $model = Post::class;
    
    protected array $columns = [
        ['key' => 'id', 'label' => 'ID'],
        ['key' => 'title', 'label' => 'Title'],
        ['key' => 'status', 'label' => 'Status'],
        ['key' => 'views', 'label' => 'Views'],
        ['key' => 'created_at', 'label' => 'Published']
    ];
    
    protected array $searchable = ['title', 'content', 'tags'];
    
    protected array $fillable = [
        'title', 'content', 'excerpt', 
        'status', 'featured_image', 'tags'
    ];
    
    protected array $validationRules = [
        'title' => 'required|min:10|max:200',
        'content' => 'required|min:100',
        'status' => 'required|in:draft,published,archived'
    ];
    
    public function publish(int $id): array
    {
        $post = Post::find($id);
        
        if (!$post) {
            return ['error' => 'Post not found', 'code' => 404];
        }
        
        $post->status = 'published';
        $post->published_at = date('Y-m-d H:i:s');
        $post->save();
        
        return [
            'success' => true,
            'message' => 'Post published',
            'data' => $post->toArray()
        ];
    }
}

Multi-Model Admin

Manage multiple models in one dashboard:
// admin/index.php
$models = [
    'Users' => [
        'controller' => UserAdminController::class,
        'icon' => 'users',
        'count' => User::count()
    ],
    'Posts' => [
        'controller' => PostAdminController::class,
        'icon' => 'file-text',
        'count' => Post::count()
    ],
    'Orders' => [
        'controller' => OrderAdminController::class,
        'icon' => 'shopping-cart',
        'count' => Order::count()
    ]
];

$dashboard = AdminPanel::for(User::class)
    ->setTitle('Admin Dashboard')
    ->setSidebar(array_map(function($name, $config) {
        return [
            'label' => $name,
            'url' => '/admin/' . strtolower($name),
            'icon' => $config['icon'],
            'count' => $config['count']
        ];
    }, array_keys($models), $models));

echo $dashboard->render();

Performance Tips

Load relationships to prevent N+1:
public function index(): array
{
    $query = $this->model::query()
        ->with('user', 'category', 'tags'); // Eager load
    
    return $query->paginate(15);
}
Only fetch needed columns:
public function index(): array
{
    $columns = array_column($this->columns, 'key');
    
    $query = $this->model::query()
        ->select($columns); // Only fetch displayed columns
    
    return $query->paginate(15);
}

Security

Protect admin endpoints with authentication:
// middleware/AdminAuth.php
class AdminAuth
{
    public function handle($request, $next)
    {
        $user = auth()->user();
        
        if (!$user || !$user->is_admin) {
            return Response::json(['error' => 'Unauthorized'], 401);
        }
        
        return $next($request);
    }
}

// Apply to routes
Router::group('/admin', function() {
    // Protected routes
})->middleware(AdminAuth::class);

Next Steps

API Resources

Transform model responses

Authentication

Secure your admin panel