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';
Workout- Model voor database (find, findById, create)mongoose- VoorisValidObjectId()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 });
}
};
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 = OKcatch (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 });
}
};
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 errorWorkout.findById(id)- Zoek workout met dit IDif (!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 });
}
};
const { title, reps, load }- Haal data uit POST requestWorkout.create()- Maak nieuwe workoutres.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;
- 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 Workout → import Workout from '...'
• export const getAllWorkouts → import { 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 getAllWorkoutsin controller? - Import correct?
import { getAllWorkouts } from '...' - Gebruik je
{ }bij import? - Staat
.jsaan 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
.jsaan 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.
Voltooi CRUD met PATCH en DELETE routes