Wat zijn Controllers?

Tot nu toe staat code in workoutRoutes.js. Dat werkt, maar wordt onoverzichtelijk met meer routes.

VOOR controllers (onoverzichtelijk):

Al je logica in routes:

// workoutRoutes.js - 35+ regels voor 3 routes!
router.get('/', async (req, res) => {
  try {
    const workouts = await Workout.find({}).sort({ createdAt: -1 });
    res.status(200).json(workouts);
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});
// ... nog meer routes

NA controllers (overzichtelijk):

Routes kort, logica in controllers:

// workoutRoutes.js - 10 regels, super duidelijk!
import { getAllWorkouts } from '../controllers/workoutController.js';

router.get('/', getAllWorkouts);

Zie je verschil?

Van 35+ regels naar 10 regels! Je ziet in één keer welke routes er zijn.

💡 Restaurant analogie

Routes = ober die bestelling aanneemt
Controllers = kok die eten maakt

Ober zegt niet: "Ik ga nu zelf hamburger bakken". Hij geeft door aan kok. Zo werkt het ook: routes geven werk door aan controllers.

Waarom controllers?

  • Overzichtelijk - Routes blijft klein, ook met 20+ routes
  • Herbruikbaar - Zelfde functie in meerdere routes
  • Makkelijker testen - Test apart zonder server
  • Professioneel - Zo bouwen échte apps

Controller Aanmaken

Maak bestand

Nieuw bestand: src/controllers/workoutController.js

Importeer Workout model

Bovenaan controller:

// src/controllers/workoutController.js
import Workout from '../models/Workout.js';
import mongoose from 'mongoose';
Waarom importeren?
  • Workout - Model voor database (find, findById, create)
  • mongoose - Voor isValidObjectId() om ID's te checken

GET Alle Workouts (READ)

Functie die alle workouts ophaalt uit database.

Controller functie schrijven

In workoutController.js:

// GET alle workouts
export const getAllWorkouts = async (req, res) => {
  try {
    // 1. Haal alle workouts op
    // 2. Sorteer: nieuwste eerst
    const workouts = await Workout.find({}).sort({ createdAt: -1 });
    
    // 3. Stuur terug
    res.status(200).json(workouts);
  } catch (error) {
    // 4. Als fout, stuur error
    res.status(500).json({ error: error.message });
  }
};
Wat gebeurt hier?
  • export const - Maak functie en exporteer (routes kunnen gebruiken)
  • Workout.find({}) - Haal alles op (lege {} = geen filter)
  • .sort({ createdAt: -1 }) - Sorteer nieuwste eerst (-1 = omgekeerd)
  • res.status(200) - Status 200 = OK
  • catch (error) - Bij fout stuur 500 (server error)

💡 Waarom sorteren?

Zo zie je altijd nieuwste workouts bovenaan. Zonder .sort() is volgorde willekeurig.

GET Eén Workout (READ)

Functie die één specifieke workout ophaalt.

Controller functie schrijven

Voeg toe aan workoutController.js:

// GET één workout op basis van ID
export const getWorkoutById = async (req, res) => {
  // 1. Haal ID uit URL
  const { id } = req.params;

  // 2. Check of ID geldig is (24 tekens, juiste format)
  if (!mongoose.isValidObjectId(id)) {
    return res.status(400).json({ error: 'Ongeldige workout ID' });
  }

  try {
    // 3. Zoek workout met dit ID
    const workout = await Workout.findById(id);

    // 4. Bestaat niet? Stuur 404
    if (!workout) {
      return res.status(404).json({ error: 'Workout niet gevonden' });
    }

    // 5. Gevonden? Stuur terug!
    res.status(200).json(workout);
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
};
Stap voor stap:
  • const { id } = req.params - ID uit URL (bijv. /api/workouts/12345)
  • isValidObjectId(id) - Check of ID juiste formaat heeft (24 tekens)
  • return res.status(400) - ID ongeldig? Stop hier, stuur error
  • Workout.findById(id) - Zoek workout met dit ID
  • if (!workout) - Niks gevonden? Stuur 404 (Not Found)

Waarom ID validatie?

MongoDB ID's zijn exact 24 karakters (bijv. 507f1f77bcf86cd799439011).

Zonder check:

GET /api/workouts/123
→ CastError: Cast to ObjectId failed
→ Je hele server crasht! ❌

Met check:

GET /api/workouts/123
→ { "error": "Ongeldige workout ID" }
→ Server blijft draaien ✅

💡 Twee soorten "niet gevonden"

Status 400: ID formaat verkeerd (bijv. "123")
Status 404: ID formaat klopt, maar workout bestaat niet

POST Nieuwe Workout (CREATE)

Deze functie heb je al! Nu verplaatsen naar controller.

💡 Waarom verhuizen als het werkt?

Straks voeg je meer toe (validation, logging, authentication). Dan wordt POST 50+ regels. Door nu in controllers te zetten blijft alles overzichtelijk.

Controller functie

Voeg toe aan workoutController.js:

// POST nieuwe workout
export const createWorkout = async (req, res) => {
  // 1. Haal data uit request
  const { title, reps, load } = req.body;

  try {
    // 2. Maak workout in database
    const workout = await Workout.create({ title, reps, load });
    
    // 3. Stuur terug
    res.status(201).json(workout);
  } catch (error) {
    // 4. Validatie fout? (bijv. title vergeten)
    res.status(400).json({ error: error.message });
  }
};
Wat gebeurt hier?
  • const { title, reps, load } - Haal data uit POST request
  • Workout.create() - Maak nieuwe workout
  • res.status(201) - Status 201 = Created (iets nieuws gemaakt)
  • catch (error) - Validatie fout? Stuur 400

Deze functie ken je al! Nu staat hij in controller i.p.v. route.

Koppelen aan Routes

Je hebt 3 controller functies. Nu gebruiken in routes.

Update workoutRoutes.js

Vervang volledige inhoud van src/routes/workoutRoutes.js:

// src/routes/workoutRoutes.js
import express from 'express';
import { 
  getAllWorkouts, 
  getWorkoutById, 
  createWorkout 
} from '../controllers/workoutController.js';

const router = express.Router();

// GET alle workouts
router.get('/', getAllWorkouts);

// GET één workout
router.get('/:id', getWorkoutById);

// POST nieuwe workout
router.post('/', createWorkout);

export default router;
Wat is veranderd?
  • Import controller functies bovenaan met { }
  • Routes zijn kort: router.get('/', getAllWorkouts)
  • Alle logica in controller, routes wijzen door

💡 Waarom { } bij import?

In controller gebruik je export const (named export).
Bij named exports moet je { } gebruiken.

Verschil:
export default Workoutimport Workout from '...'
export const getAllWorkoutsimport { getAllWorkouts } from '...'

Zie je verschil?

VOOR: workoutRoutes.js = 35+ regels vol code
NA: workoutRoutes.js = 15 regels, alleen routes

Super overzichtelijk! Je ziet meteen welke routes er zijn.

Testen in Postman

Je hebt 3 routes. Tijd om te testen!

1. POST - Maak workouts

Maak eerst paar workouts aan:

POST http://localhost:4000/api/workouts
Body (raw, JSON):
{
  "title": "Squats",
  "reps": 10,
  "load": 50
}

Maak 2-3 workouts. Je krijgt status 201 Created.

2. GET - Alle workouts

GET http://localhost:4000/api/workouts

Je ziet array met workouts, gesorteerd nieuw → oud:

[
  {
    "_id": "abc123...",
    "title": "Push ups",
    "reps": 20,
    "load": 0
  },
  {
    "_id": "def456...",
    "title": "Squats",
    "reps": 10,
    "load": 50
  }
]

3. GET - Eén workout

Kopieer een _id en gebruik:

GET http://localhost:4000/api/workouts/abc123...

Je krijgt één workout (geen array).

4. Test ongeldige ID

GET http://localhost:4000/api/workouts/123

Resultaat:

{
  "error": "Ongeldige workout ID"
}

Status: 400 Bad Request

💡 Wat betekent dit?

ID "123" heeft verkeerd formaat. MongoDB ID's zijn 24 tekens. Dit is isValidObjectId() check!

5. Test niet-bestaande ID

Probeer ID met goed formaat, maar bestaat niet:

GET http://localhost:4000/api/workouts/507f1f77bcf86cd799439011

Resultaat:

{
  "error": "Workout niet gevonden"
}

Status: 404 Not Found

💡 Verschil 400 vs 404

400: "Je vraag klopt niet" (ID formaat verkeerd)
404: "Ik snap vraag, maar bestaat niet" (ID klopt, maar geen match)

Problemen oplossen

❌ "getAllWorkouts is not a function"

Probleem: Controller functie niet gevonden

Check:

  • Staat export const getAllWorkouts in controller?
  • Import correct? import { getAllWorkouts } from '...'
  • Gebruik je { } bij import?
  • Staat .js aan eind van pad?

❌ "Cannot find module"

Probleem: Controller bestand bestaat niet

Check:

  • Bestaat src/controllers/workoutController.js?
  • Pad klopt? Van routes naar controllers is ../controllers/
  • Staat .js aan eind?

❌ GET geeft lege array []

Probleem: Database is leeg

Check:

  • Doe eerst POST requests om workouts te maken
  • Check MongoDB Atlas → Browse Collections
  • Check .env: klopt database naam in MONGO_URI?

❌ Workouts niet gesorteerd

Probleem: .sort() vergeten

Check controller:

const workouts = await Workout.find({}).sort({ createdAt: -1 });

Let op: -1 = omgekeerd (nieuwste eerst)

Checklist

✅ Check of je hebt:

  • src/controllers/workoutController.js gemaakt
  • Workout model en mongoose geïmporteerd
  • getAllWorkouts met .sort()
  • getWorkoutById met ID validatie
  • createWorkout geschreven
  • Alle 3 geëxporteerd met export const
  • workoutRoutes.js update - importeert controllers
  • Routes zijn kort (10-15 regels)
  • GET /api/workouts werkt en sorteert
  • GET /api/workouts/:id werkt
  • POST /api/workouts werkt
  • Ongeldig ID geeft 400

CRUD Status:

  • Create - POST workout
  • Read - GET alle + GET één
  • Update - Komt volgende stap
  • Delete - Komt volgende stap

Volgende Stap

CREATE en READ zijn af! Nu nog UPDATE en DELETE om CRUD compleet te maken.

UPDATE & DELETE →

Voltooi CRUD met PATCH en DELETE routes