Skip to main content

Controller Usage Guide

Use generated controllers as thin Express adapters. Keep persistence, relation loading, cache policy, and soft-delete rules in services and models. Preferred CRUD flow:
  • controllers delegate to service methods
  • services use User.find(...), User.create(...), loaded-instance update(...); save(), and explicit User.deleteById(...) / User.restoreById(...)
  • controllers should not introduce their own persistence logic

Generate a controller

eloquent make:controller User
eloquent make:controller User --soft
eloquent make:controller User --test

Generated methods

  • index()
  • show()
  • store()
  • update()
  • destroy()
  • restore() when generated with --soft

Express route wiring

import express from "express";
import { UserController } from "./app/controllers/UserController";

const app = express();
app.use(express.json());

const controller = new UserController();

app.get("/users", controller.index.bind(controller));
app.get("/users/:id", controller.show.bind(controller));
app.post("/users", controller.store.bind(controller));
app.put("/users/:id", controller.update.bind(controller));
app.delete("/users/:id", controller.destroy.bind(controller));
app.patch("/users/:id/restore", controller.restore.bind(controller));
Only add the restore route when the controller was generated with --soft.

Mixin-aware behavior

Controllers do not own mixins. They consume model/service behavior that comes from the composed model stack.

Soft deletes

If the model supports soft deletes, keep destroy() as soft delete and expose restore() from the controller. Recommended service shape behind the controller:
async destroy(id: number | string) {
  return User.deleteById(id);
}

async restore(id: number | string) {
  return User.restoreById(id);
}
Use one schema declaration, not both:
deleted_at: column("softDeletes")
or:
softDeletes: mixin("SoftDeletes")

Serialization

If the model uses hidden/appended fields, prefer toObject() before res.json(...).

Eager loading and cache

  • Keep relation loading in the service layer.
  • Keep cache logic in the service layer.

Driver note

The controller contract is the same for SQL and Mongo models. Keep driver branching out of route handlers.