Unterschiede

Hier werden die Unterschiede zwischen zwei Versionen angezeigt.

Link zu dieser Vergleichsansicht

Beide Seiten der vorigen Revision Vorhergehende Überarbeitung
Nächste Überarbeitung
Vorhergehende Überarbeitung
modul:m290_guko:learningunits:lu17:theorie:a_intro [2026/01/02 22:30] gkochmodul:m290_guko:learningunits:lu17:theorie:a_intro [2026/01/12 07:43] (aktuell) gkoch
Zeile 3: Zeile 3:
 ===== Lernziele ===== ===== Lernziele =====
   * Sie können Ihre **MySQL-Datenbank** aus einem Express-Server heraus ansprechen.   * Sie können Ihre **MySQL-Datenbank** aus einem Express-Server heraus ansprechen.
-  * Sie können die CRUD-Routen aus LU16 (''GET'', ''POST'', ''PUT'', ''DELETE'') so erweitern, dass sie mit einer **echten Tabelle ''post''** arbeiten.+  * Sie können die CRUD-Routen aus LU16 (''GET'', ''POST'', ''PUT'', ''DELETE'') so erweitern, dass sie mit einer **echten Tabelle ''posts''** arbeiten.
   * Sie setzen einfache **Validierung** ein (Pflichtfelder prüfen).   * Sie setzen einfache **Validierung** ein (Pflichtfelder prüfen).
   * Sie verwenden passende **HTTP-Statuscodes** (200, 201, 400, 404, 500).   * Sie verwenden passende **HTTP-Statuscodes** (200, 201, 400, 404, 500).
Zeile 19: Zeile 19:
 In LU17 ersetzen Sie diese In-Memory-Liste durch eine echte Datenbank: In LU17 ersetzen Sie diese In-Memory-Liste durch eine echte Datenbank:
  
-  * Die Daten kommen aus der **MySQL-Tabelle ''post''**.+  * Die Daten kommen aus der **MySQL-Tabelle ''posts''**.
   * Ihr Express-Server ist die **Brücke** zwischen Client (Postman) und Datenbank.   * Ihr Express-Server ist die **Brücke** zwischen Client (Postman) und Datenbank.
   * Die gleiche Idee bleibt: **HTTP-Anfrage → Route → Logik/SQL → HTTP-Antwort**.   * Die gleiche Idee bleibt: **HTTP-Anfrage → Route → Logik/SQL → HTTP-Antwort**.
Zeile 216: Zeile 216:
 </WRAP> </WRAP>
  
-**Test in Postman**+=== Test in Postman ===
   * Methode: ''GET''   * Methode: ''GET''
   * URL: ''http://localhost:3000/api/posts''   * URL: ''http://localhost:3000/api/posts''
Zeile 307: Zeile 307:
     const newPost = {     const newPost = {
       id: result.insertId,       id: result.insertId,
-      user_id, +      user_id: user_id, 
-      title,+      title: title,
       image_url: image_url || '',       image_url: image_url || '',
       description: description || '',       description: description || '',
Zeile 319: Zeile 319:
 </code> </code>
 </WRAP> </WRAP>
 +
 +=== Test in Postman ===
  
 **Test-Body (Postman → Body → raw → JSON)** **Test-Body (Postman → Body → raw → JSON)**
Zeile 335: Zeile 337:
 ==== UPDATE: Post ändern (PUT /api/posts/:id) ==== ==== UPDATE: Post ändern (PUT /api/posts/:id) ====
  
-In LU16b haben Sie einen Post so aktualisiert: Nur die Felderdie im Body wirklich mitgeschickt werden, werden geändert.+In LU16b haben Sie einen Post so aktualisiert: Der ganze Datensatz wird ersetztwenn wir ein Update machen.
 Genau diese Logik übernehmen wir jetzt – der Unterschied ist nur: statt im Array ändern wir jetzt die MySQL-Tabelle ''posts''. Genau diese Logik übernehmen wir jetzt – der Unterschied ist nur: statt im Array ändern wir jetzt die MySQL-Tabelle ''posts''.
  
Zeile 341: Zeile 343:
 <WRAP box round center 80%> <WRAP box round center 80%>
 <code javascript> <code javascript>
-// UPDATE – vorhandenen Post teilweise aktualisieren (wie in LU16b)+// UPDATE – Post vollständig ersetzen (PUT)
 // Route: PUT http://localhost:3000/api/posts/1 // Route: PUT http://localhost:3000/api/posts/1
- 
 app.put('/api/posts/:id', (req, res) => { app.put('/api/posts/:id', (req, res) => {
  
-// 1) ID aus der URL lesen (Route-Parameter) +  const id = Number(req.params.id);
-const id = Number(req.params.id);+
  
-// ID prüfen: muss eine Zahl sein +  if (Number.isNaN(id)) { 
-if (Number.isNaN(id)) { +    return res.status(400).send('Ungültige ID (muss eine Zahl sein)'); 
-return res.status(400).send('Ungültige ID (muss eine Zahl sein)'); +  }
-}+
  
-// 2) Mögliche neue Werte aus dem Request-Body lesen +  // Alle Felder werden erwartet (PUT ersetzt alles
-// (Postman: Body -> raw -> JSON+  const user_id = req.body.user_id; 
-const user_id = req.body.user_id; +  const title = req.body.title; 
-const title = req.body.title; +  const image_url = req.body.image_url; 
-const image_url = req.body.image_url; +  const description = req.body.description; 
-const description = req.body.description; +  const likes = req.body.likes;
-const likes = req.body.likes;+
  
-// 3) Validierung: mindestens ein Feld muss vorhanden sein +  // Validierung: fehlen Felder? 
-// Wichtig: likes kann 0 sein -> deshalb prüfen wir auf undefined (nicht auf "falsy") +  // likes kann 0 sein -> deshalb auf undefined prüfen 
-if ( +  if ( 
-user_id === undefined && +    user_id === undefined || 
-title === undefined && +    title === undefined || 
-image_url === undefined && +    image_url === undefined || 
-description === undefined && +    description === undefined || 
-likes === undefined +    likes === undefined 
-) { +  ) { 
-return res.status(400).send('Bitte mindestens ein Feld zum Aktualisieren mitsenden.'); +    return res.status(400).send('Bitte user_id, title, image_url, description und likes mitsenden (PUT ersetzt alles).'); 
-}+  }
  
-// 4) SQL-UPDATE dynamisch zusammenbauen: +  const sql = ` 
-// Nur Felderdie wirklich im Body vorhanden sindkommen in das SET. +    UPDATE posts 
-const setParts []; +    SET user_id = ?title = ?image_url ?, description = ?, likes = ? 
-const values [];+    WHERE id 
 +  `;
  
-if (user_id !== undefined) { +  const values [user_idtitleimage_urldescriptionlikes, id];
-setParts.push('user_id = ?'); +
-values.push(user_id); +
-+
-if (title !== undefined) { +
-setParts.push('title = ?'); +
-values.push(title); +
-+
-if (image_url !== undefined) { +
-setParts.push('image_url = ?'); +
-values.push(image_url); +
-+
-if (description !== undefined) { +
-setParts.push('description = ?'); +
-values.push(description); +
-+
-if (likes !== undefined) { +
-setParts.push('likes = ?'); +
-values.push(likes); +
-}+
  
-// id gehört ans Ende -> wird im WHERE eingesetzt +  db.query(sql, values, (err, result) => { 
-values.push(id);+    if (err) { 
 +      console.error('DB-Fehler bei PUT /api/posts/:id:', err); 
 +      return res.status(500).send('Serverfehler beim Aktualisieren des Posts'); 
 +    }
  
-const sql UPDATE posts SET ${setParts.join('')} WHERE id = ? ;+    if (result.affectedRows === 0) { 
 +      return res.status(404).send('Post nicht gefunden'); 
 +    }
  
-// 5) UPDATE ausführen +    // 200 OK + das "neue" Objekt zurückgeben 
-db.query(sql, values, (err, result) => { +    res.status(200).json({ 
- +      id: id, 
-// DB-Fehler -> 500 +      user_id: user_id, 
-if (err) { +      title: title, 
-  console.error('DB-Fehler bei PUT /api/posts/:id:', err); +      image_url: image_url, 
-  return res.status(500).send('Serverfehler beim Aktualisieren des Posts'); +      description: description, 
-+      likes: likes 
- +    }); 
-// affectedRows = 0 -> es gab keinen Post mit dieser ID +  });
-if (result.affectedRows === 0) +
-  return res.status(404).send('Post nicht gefunden'); +
-+
- +
-// 6) Lernfreundlichaktualisierten Datensatz nochmals holen und zurückgeben +
-// Damit der Client (Postman) das "neue" Objekt direkt sieht. +
-const selectSql = ` +
-  SELECT id, user_id, title, image_url, description, likes +
-  FROM posts +
-  WHERE id = ? +
-`; +
- +
-db.query(selectSql, [id], (err2, rows) => { +
-  if (err2) { +
-    console.error('DB-Fehler beim SELECT nach UPDATE:', err2); +
-    return res.status(500).send('Serverfehler beim Laden des aktualisierten Posts'); +
-  +
- +
-  res.status(200).json(rows[0]); +
-}); +
- +
- +
-});+
 }); });
 </code> </code>
 </WRAP> </WRAP>
  
-Test mit Postman (PUT) +=== Test in Postman ===
- +
-Methode: ''PUT'' +
- +
-URL: ''http://localhost:3000/api/posts/+
-'' +
- +
-Body → ''raw'' → ''JSON'' +
- +
-Beispiel-Body:+
  
 +**Test-Body**
 <WRAP box round center 80%> <WRAP box round center 80%>
 <code json> <code json>
 { {
-"title": "Sunset Vibes (updated)", +  "user_id": 1, 
-"likes": 0+  "title": "Titel (replaced)", 
 +  "image_url": "https://example.com/new.jpg", 
 +  "description": "Dieser Post wurde komplett ersetzt.", 
 +  "likes": 5
 } }
 </code> </code>
Zeile 463: Zeile 420:
  
 Erwartung: Erwartung:
 +  * Status ''200 OK''
 +  * JSON-Objekt des aktualisierten Posts (inkl. neuem ''title'' und ''likes'')
  
-Status ''200 OK'' 
- 
-JSON-Objekt des aktualisierten Posts (inkl. neuem ''title'' und ''likes'') 
- 
-DELETE-Section ersetzen durch diese Version 
  
 ==== DELETE: Post löschen (DELETE /api/posts/:id) ==== ==== DELETE: Post löschen (DELETE /api/posts/:id) ====
- 
-In LU16b haben Sie beim Löschen den gelöschten Post zurückgegeben (zur Kontrolle). 
-Das machen wir hier genauso – nur mit MySQL: 
- 
-zuerst den Post mit ''SELECT'' holen, 
- 
-dann mit ''DELETE'' löschen, 
- 
-dann den vorher geholten Post zurückgeben. 
- 
 <WRAP box round center 80%> <WRAP box round center 80%>
 <code javascript> <code javascript>
-// DELETE – Post löschen (wie in LU16b: gelöschtes Objekt zurückgeben) +// DELETE – Post löschen
-// Route: DELETE http://localhost:3000/api/posts/+
 app.delete('/api/posts/:id', (req, res) => { app.delete('/api/posts/:id', (req, res) => {
  
-const id = Number(req.params.id);+  const id = Number(req.params.id);
  
-if (Number.isNaN(id)) { +  if (Number.isNaN(id)) { 
-return res.status(400).send('Ungültige ID (muss eine Zahl sein)'); +    return res.status(400).send('Ungültige ID (muss eine Zahl sein)'); 
-}+  }
  
-// 1) Post zuerst holen (damit wir ihn nach dem Löschen zurückgeben können) +  const sql 'DELETE FROM posts WHERE id = ?';
-const selectSql SELECT id, user_id, title, image_url, description, likes FROM posts WHERE id = ? ;+
  
-db.query(selectSql, [id], (err, rows) => {+  db.query(sql, [id], (err, result) => { 
 +    if (err) { 
 +      console.error('DB-Fehler bei DELETE /api/posts/:id:', err); 
 +      return res.status(500).send('Serverfehler beim Löschen des Posts'); 
 +    }
  
-if (err) { +    if (result.affectedRows === 0) { 
-  console.error('DB-Fehler bei SELECT vor DELETE:', err); +      return res.status(404).send('Post nicht gefunden'); 
-  return res.status(500).send('Serverfehler beim Löschen des Posts'); +    }
-}+
  
-if (rows.length === 0) { +    // Antwort: 200 + Message 
-  return res.status(404).send('Post nicht gefunden'); +    res.status(200).json({ message: `Post mit id=${id} wurde gelöscht.});
-+
- +
-const deletedPost = rows[0]; +
- +
-// 2) Jetzt löschen +
-const deleteSql = 'DELETE FROM posts WHERE id = ?'; +
- +
-db.query(deleteSql, [id], (err2, result) => { +
- +
-  if (err2) { +
-    console.error('DB-Fehler bei DELETE /api/posts/:id:', err2); +
-    return res.status(500).send('Serverfehler beim Löschen des Posts'); +
-  } +
- +
-  // 3) Lernfreundlich: 200 + gelöschtes Objekt (wie LU16b) +
-  res.status(200).json(deletedPost);+
  
-}); +  });
- +
- +
-});+
 }); });
 </code> </code>
 </WRAP> </WRAP>
  
-Test mit Postman (DELETE)+=== Test mit Postman ===
  
-Methode: ''DELETE'' +  * Methode: ''DELETE'' 
- +  URL: ''http://localhost:3000/api/posts/1''
-URL: ''http://localhost:3000/api/posts/1 +
-''+
  
 Erwartung: Erwartung:
- +  * Status ''200 OK'' 
-Status ''200 OK'' +  JSON-Objekt des gelöschten Posts 
- +  Danach ''GET /api/posts/1'' → ''404 Not Found''
-JSON-Objekt des gelöschten Posts +
- +
-Danach ''GET /api/posts/1'' → ''404 Not Found''+
  
  
Zeile 558: Zeile 478:
  
 ===== Transfer auf Ihr Projekt (LB03) ===== ===== Transfer auf Ihr Projekt (LB03) =====
-Für Ihr Projekt ersetzen Sie ''post'' durch Ihre eigenen Tabellen (z.B. ''serie'', ''actor'', ''serie_actor''):+Für Ihr Projekt ersetzen Sie ''posts'' durch Ihre eigenen Tabellen (z.B. ''serie'', ''actor'', ''serie_actor''):
  
   * Ressourcen-Route: z.B. ''/api/serien''   * Ressourcen-Route: z.B. ''/api/serien''
  • modul/m290_guko/learningunits/lu17/theorie/a_intro.1767389435.txt.gz
  • Zuletzt geändert: 2026/01/02 22:30
  • von gkoch