Mysql
 sql >> Datenbank >  >> RDS >> Mysql

So verwenden Sie MySQL mit Deno und Oak

Ich habe kürzlich darüber geschrieben, wie man eine Todo-API in Deno + Oak erstellt (ohne eine Datenbank zu verwenden) . Sie finden das Repo unter chapter_1:oak auf GitHub.

Dieses Tutorial macht dort weiter, wo das andere aufgehört hat, und ich gehe darauf ein, wie man MySQL in ein Deno- und Oak-Projekt integriert.

Wenn Sie zu irgendeinem Zeitpunkt den gesamten in diesem Tutorial verwendeten Quellcode sehen möchten, ist er unter chapter_2:mysql verfügbar . Fühlen Sie sich frei, ihm einen Stern auf GitHub zu geben, wenn er Ihnen gefällt.

Ich gehe davon aus, dass Sie das letzte oben genannte Tutorial bereits abgeschlossen haben. Wenn nicht, schau es dir hier an und komm wieder, wenn du fertig bist.

Bevor wir beginnen, vergewissern Sie sich, dass Sie einen MySQL-Client installiert haben und ausführen:

  • MySQL-Community-Server [hier herunterladen]
  • MySQL Workbench [hier herunterladen]

Ich habe eine kleine Anleitung für Mac OS-Benutzer zum Einrichten von MySQL geschrieben, weil ich auch damit zu kämpfen hatte. Sieh es dir hier an.

Wenn Sie sich auf einem Windows-Computer befinden, können Sie dieselben Tools verwenden oder Sie können auch XAMPP verwenden, um eine MySQL-Instanz in Ihrem Dashboard auszuführen.

Sobald Sie eine MySQL-Instanz ausgeführt haben, können wir mit unserem Tutorial beginnen.

Fangen wir an

Angenommen, Sie kommen von diesem Artikel, Todo-API in Deno + Oak (ohne Verwendung einer Datenbank) , werden wir Folgendes tun:

  • Erstellen Sie eine MySQL-Datenbankverbindung
  • Schreiben Sie ein kleines Skript, das die Datenbank jedes Mal zurücksetzt, wenn wir unseren Deno-Server starten
  • CRUD-Operationen für eine Tabelle ausführen
  • Fügen Sie die CRUD-Funktionalität zu unseren API-Controllern hinzu

Eine letzte Sache – hier ist der gesamte Commit-Unterschied, der in Kapitel 1 vorgenommen wurde, um MySQL zum Projekt hinzuzufügen (Quellcode, der die neuen Ergänzungen aus Kapitel 1 zeigt).

In Ihrem Projektstammordner – meiner heißt chapter_2:mysql , obwohl Ihre kann heißen, wie Sie wollen – erstellen Sie einen Ordner namens db . Erstellen Sie in diesem Ordner eine Datei namens config.ts and füge folgenden Inhalt hinzu:

export const DATABASE: string = "deno";
export const TABLE = {
  TODO: "todo",
};

Hier ist nichts Besonderes, wir definieren einfach unseren Datenbanknamen zusammen mit einem Objekt für Tabellen und exportieren es dann. Unser Projekt wird eine Datenbank namens "deno" haben und innerhalb dieser Datenbank werden wir nur eine Tabelle namens "todo" haben.

Als nächstes innerhalb der db erstellen Sie eine weitere Datei namens client.ts und fügen Sie den folgenden Inhalt hinzu:

import { Client } from "https://deno.land/x/mysql/mod.ts";
// config
import { DATABASE, TABLE } from "./config.ts";

const client = await new Client();

client.connect({
  hostname: "127.0.0.1",
  username: "root",
  password: "",
  db: "",
});

export default client;

Hier passieren ein paar Dinge.

Wir importieren Client aus mysql Bücherei. Client wird uns helfen, eine Verbindung zu unserer Datenbank herzustellen und Operationen in der Datenbank durchzuführen.

client.connect({
  hostname: "127.0.0.1",
  username: "root",
  password: "",
  db: "",
});

Client bietet eine Methode namens connect Das nimmt ein Objekt auf, in dem wir den hostname angeben können , username , password , und db . Mit diesen Informationen kann es eine Verbindung zu unserer MySQL-Instanz herstellen.

Stellen Sie sicher, dass Ihr username hat kein password , da dies mit der Verbindung zur MySQL-Bibliothek von Deno in Konflikt steht. Wenn Sie nicht wissen, wie das geht, lesen Sie dieses Tutorial, das ich geschrieben habe.

Ich habe die database verlassen Feld hier leer, weil ich es später in meinem Skript manuell auswählen möchte.

Lassen Sie uns ein Skript hinzufügen, das eine Datenbank namens "deno" initialisiert, sie auswählen und in dieser Datenbank eine Tabelle namens "todo" erstellen.

Innerhalb von db/client.ts Datei lasst uns ein paar neue Ergänzungen machen:

import { Client } from "https://deno.land/x/mysql/mod.ts";
// config
import { DATABASE, TABLE } from "./config.ts";

const client = await new Client();

client.connect({
  hostname: "127.0.0.1",
  username: "root",
  password: "",
  db: "",
});

const run = async () => {
  // create database (if not created before)
  await client.execute(`CREATE DATABASE IF NOT EXISTS ${DATABASE}`);
  // select db
  await client.execute(`USE ${DATABASE}`);

  // delete table if it exists before
  await client.execute(`DROP TABLE IF EXISTS ${TABLE.TODO}`);
  // create table
  await client.execute(`
    CREATE TABLE ${TABLE.TODO} (
        id int(11) NOT NULL AUTO_INCREMENT,
        todo varchar(100) NOT NULL,
        isCompleted boolean NOT NULL default false,
        PRIMARY KEY (id)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
  `);
};

run();

export default client;

Hier importieren wir DATABASE und TABLE aus unserer Konfigurationsdatei und verwenden diese Werte dann in einer neuen Funktion namens run() .

Lassen Sie uns dieses run() aufschlüsseln Funktion. Ich habe der Datei Kommentare hinzugefügt, die Ihnen helfen, den Arbeitsablauf zu verstehen:

const run = async () => {
  // create database (if not created before)
  await client.execute(`CREATE DATABASE IF NOT EXISTS ${DATABASE}`);
  // select db
  await client.execute(`USE ${DATABASE}`);

  // delete table if it exists before
  await client.execute(`DROP TABLE IF EXISTS ${TABLE.TODO}`);
  // create table
  await client.execute(`
    CREATE TABLE ${TABLE.TODO} (
        id int(11) NOT NULL AUTO_INCREMENT,
        todo varchar(100) NOT NULL,
        isCompleted boolean NOT NULL default false,
        PRIMARY KEY (id)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
  `);
};

run();
  • Erstellen Sie eine Datenbank namens deno . Wenn es bereits existiert, tun Sie nichts.
  • Wählen Sie dann die zu verwendende Datenbank aus, die deno heißt
  • Löschen Sie die Tabelle in deno namens todo wenn es schon existiert.
  • Als nächstes erstellen Sie eine neue Tabelle innerhalb des deno db, nennen Sie es todo , und definieren Sie seine Struktur:Es wird eine eindeutige automatische Erhöhung id haben was eine Ganzzahl sein wird, ein weiteres Feld namens todo Dies wird eine Zeichenfolge sein, und schließlich ein Feld namens isCompleted was ein boolescher Wert ist. Ich definiere auch id als meinen Primärschlüssel.

Der Grund, warum ich dieses Skript geschrieben habe, war, dass ich keine zusätzlichen Informationen in der MySQL-Instanz haben möchte. Jedes Mal, wenn das Skript ausgeführt wird, initialisiert es einfach alles neu.

Sie müssen dieses Skript nicht hinzufügen. Aber wenn Sie dies nicht tun, müssen Sie eine Datenbank und die Tabelle manuell erstellen.

Sehen Sie sich auch die Dokumentation der Deno MySQL-Bibliothek zur Erstellung von Datenbanken und zur Tabellenerstellung an.

Zurück zu unserer Agenda:Wir haben gerade zwei der vier oben im Artikel erwähnten Dinge erreicht:

  • Erstellen Sie eine MySQL-Datenbankverbindung
  • Schreiben Sie ein kleines Skript, das die Datenbank jedes Mal zurücksetzt, wenn wir unseren Deno-Server starten

Das sind bereits 50% des Tutorials. Leider können wir im Moment nicht viel sehen. Lassen Sie uns schnell einige Funktionen hinzufügen, um zu sehen, dass es funktioniert.

Durchführen von CRUD-Vorgängen an einer Tabelle und Hinzufügen der Funktionalität zu unseren API-Controllern

Wir müssen zuerst unsere Todo-Oberfläche aktualisieren. Gehen Sie zu interfaces/Todo.ts Datei und fügen Sie Folgendes hinzu:

export default interface Todo {
  id?: number,
  todo?: string,
  isCompleted?: boolean,
}

Was ist dieser ? macht den Schlüssel im Objekt optional. Ich habe dies getan, weil ich später verschiedene Funktionen verwenden werde, um Objekte mit nur einer id zu übergeben , todo , isCompleted , oder alle auf einmal.

Wenn Sie mehr über optionale Eigenschaften in TypeScript erfahren möchten, gehen Sie hier zu ihrer Dokumentation.

Erstellen Sie als Nächstes einen neuen Ordner mit dem Namen models und erstellen Sie in diesem Ordner eine Datei namens todo.ts . Fügen Sie der Datei folgenden Inhalt hinzu:

import client from "../db/client.ts";
// config
import { TABLE } from "../db/config.ts";
// Interface
import Todo from "../interfaces/Todo.ts";

export default {
  /**
   * Takes in the id params & checks if the todo item exists
   * in the database
   * @param id
   * @returns boolean to tell if an entry of todo exits in table
   */
  doesExistById: async ({ id }: Todo) => {},
  /**
   * Will return all the entries in the todo column
   * @returns array of todos
   */
  getAll: async () => {},
  /**
   * Takes in the id params & returns the todo item found
   * against it.
   * @param id
   * @returns object of todo item
   */
  getById: async ({ id }: Todo) => {},
  /**
   * Adds a new todo item to todo table
   * @param todo
   * @param isCompleted
   */
  add: async (
    { todo, isCompleted }: Todo,
  ) => {},
  /**
   * Updates the content of a single todo item
   * @param id
   * @param todo
   * @param isCompleted
   * @returns integer (count of effect rows)
   */
  updateById: async ({ id, todo, isCompleted }: Todo) => {},
  /**
   * Deletes a todo by ID
   * @param id
   * @returns integer (count of effect rows)
   */
  deleteById: async ({ id }: Todo) => {},
};

Im Moment sind die Funktionen leer, aber das ist in Ordnung. Wir werden sie nach und nach auffüllen.

Gehen Sie als nächstes zu controllers/todo.ts Datei und stellen Sie sicher, dass Sie Folgendes hinzufügen:

// interfaces
import Todo from "../interfaces/Todo.ts";
// models
import TodoModel from "../models/todo.ts";

export default {
  /**
   * @description Get all todos
   * @route GET /todos
   */
  getAllTodos: async ({ response }: { response: any }) => {},
  /**
   * @description Add a new todo
   * @route POST /todos
   */
  createTodo: async (
    { request, response }: { request: any; response: any },
  ) => {},
  /**
   * @description Get todo by id
   * @route GET todos/:id
   */
  getTodoById: async (
    { params, response }: { params: { id: string }; response: any },
  ) => {},
  /**
   * @description Update todo by id
   * @route PUT todos/:id
   */
  updateTodoById: async (
    { params, request, response }: {
      params: { id: string };
      request: any;
      response: any;
    },
  ) => {},
  /**
   * @description Delete todo by id
   * @route DELETE todos/:id
   */
  deleteTodoById: async (
    { params, response }: { params: { id: string }; response: any },
  ) => {},
};

Auch hier haben wir leere Funktionen. Fangen wir an, sie aufzufüllen.

[Get] alle Todos-API

In models/todo.ts , fügen Sie eine Definition für eine Funktion namens getAll hinzu :

import client from "../db/client.ts";
// config
import { TABLE } from "../db/config.ts";
// Interface
import Todo from "../interfaces/Todo.ts";

export default {
   /**
   * Will return all the entries in the todo column
   * @returns array of todos
   */
  getAll: async () => {
    return await client.query(`SELECT * FROM ${TABLE.TODO}`);
  },
}

Der Client stellt neben connect auch eine andere Methode zur Verfügung (Wir haben eine "connect"-Methode in db/client.ts verwendet Datei) und das ist query . Die client.query -Methode können wir MySQL-Abfragen direkt aus unserem Deno-Code so ausführen, wie sie sind.

Gehen Sie als nächstes zu controllers/todo.ts Definition für getAllTodos hinzufügen :

// interfaces
import Todo from "../interfaces/Todo.ts";
// models
import TodoModel from "../models/todo.ts";

export default {
  /**
   * @description Get all todos
   * @route GET /todos
   */
  getAllTodos: async ({ response }: { response: any }) => {
    try {
      const data = await TodoModel.getAll();
      response.status = 200;
      response.body = {
        success: true,
        data,
      };
    } catch (error) {
      response.status = 400;
      response.body = {
        success: false,
        message: `Error: ${error}`,
      };
    }
  },
}

Wir importieren lediglich TodoModel und mit seiner Methode namens getAll , die wir gerade definiert haben. Da es als Versprechen zurückkehrt, haben wir es in async/await verpackt.

Die Methode TodoModel.getAll() wird uns ein Array zurückgeben, das wir einfach an response.body zurückgeben mit status auf 200 gesetzt .

Wenn das Promise fehlschlägt oder ein anderer Fehler vorliegt, gehen wir einfach zu unserem catch-Block und geben einen Status von 400 mit success zurück auf falsch setzen. Wir setzen auch die message zu dem, was wir vom catch-Block erhalten.

Das ist es, wir sind fertig. Lassen Sie uns jetzt unser Terminal hochfahren.

Stellen Sie sicher, dass Ihre MySQL-Instanz ausgeführt wird. Geben Sie in Ihrem Terminal Folgendes ein:

$ deno run --allow-net server.ts 

Ihr Terminal sollte in etwa so aussehen:

Meine Konsole sagt mir hier zwei Dinge.

  1. Dass mein Deno-API-Server auf Port 8080 läuft
  2. Dass meine MySQL-Instanz auf 127.0.0.1 läuft , das ist localhost

Lassen Sie uns unsere API testen. Ich verwende hier Postman, aber Sie können Ihren bevorzugten API-Client verwenden.

Im Moment gibt es nur leere Daten zurück. Aber sobald wir Daten zu unserem todo hinzufügen Tabelle, es wird diese Todos hier zurückgeben.

Fantastisch. Eine API ausgefallen und vier weitere stehen noch aus.

[Post] fügt eine Todo-API hinzu

In models/todo.ts fügen Sie die folgende Definition für add() hinzu Funktion:

export default {
   /**
   * Adds a new todo item to todo table
   * @param todo
   * @param isCompleted
   */
  add: async (
    { todo, isCompleted }: Todo,
  ) => {
    return await client.query(
      `INSERT INTO ${TABLE.TODO}(todo, isCompleted) values(?, ?)`,
      [
        todo,
        isCompleted,
      ],
    );
  },
}

Die add-Funktion übernimmt object als Argument, das zwei Elemente hat:todo und isCompleted .

Also add: async ({ todo, isCompleted }: Todo) => {} kann auch als ({todo, isCompleted}: {todo:string, isCompleted:boolean}) geschrieben werden . Aber da wir bereits eine Schnittstelle in unserer interfaces/Todo.ts definiert haben Datei, die

ist
export default interface Todo {
  id?: number,
  todo?: string,
  isCompleted?: boolean,
}

wir können dies einfach als add: async ({ todo, isCompleted }: Todo) => {} . Dies teilt TypeScript mit, dass diese Funktion zwei Argumente hat, todo , bei dem es sich um eine Zeichenfolge handelt, und isCompleted , was ein boolescher Wert ist.

Wenn Sie mehr über Schnittstellen lesen möchten, gibt es zu TypeScript ein hervorragendes Dokument, das Sie hier finden können.

Innerhalb unserer Funktion haben wir Folgendes:

return await client.query(
  `INSERT INTO ${TABLE.TODO}(todo, isCompleted) values(?, ?)`,
  [
    todo,
    isCompleted,
  ],
);

Diese Abfrage kann in zwei Teile unterteilt werden:

  • INSERT INTO ${TABLE.TODO}(todo, isCompleted) values(?, ?) . Die beiden Fragezeichen hier kennzeichnen eine Verwendung von Variablen innerhalb dieser Abfrage.
  • Der andere Teil, [todo, isCompleted] , sind die Variablen, die in den ersten Teil kommen der Abfrage und durch (?, ?) ersetzt werden
  • Table.Todo ist nur ein String aus der Datei db/config.ts wo die Table.Todo Wert ist "todo "

Als nächstes in unserer controllers/todo.ts Datei, gehen Sie zur Definition von createTodo() Funktion:

export default {
   /**
   * @description Add a new todo
   * @route POST /todos
   */
  createTodo: async (
    { request, response }: { request: any; response: any },
  ) => {
    const body = await request.body();
    if (!request.hasBody) {
      response.status = 400;
      response.body = {
        success: false,
        message: "No data provided",
      };
      return;
    }

    try {
      await TodoModel.add(
        { todo: body.value.todo, isCompleted: false },
      );
      response.body = {
        success: true,
        message: "The record was added successfully",
      };
    } catch (error) {
      response.status = 400;
      response.body = {
        success: false,
        message: `Error: ${error}`,
      };
    }
  },
}

Lassen Sie uns dies in zwei Teile aufteilen:

Teil 1

const body = await request.body();
if (!request.hasBody) {
  response.status = 400;
  response.body = {
    success: false,
    message: "No data provided",
  };
  return;
}

Alles, was wir hier tun, ist zu prüfen, ob der Benutzer Daten im Körper sendet. Wenn nicht, dann geben wir einen Status 400 zurück und im Body success: false zurückgeben und message: <erromessage-string> .

Teil 2

try {
  await TodoModel.add(
    { todo: body.value.todo, isCompleted: false },
  );
  response.body = {
    success: true,
    message: "The record was added successfully",
  };
} catch (error) {
  response.status = 400;
  response.body = {
    success: false,
    message: `Error: ${error}`,
  };
}

Wenn kein Fehler vorliegt, wird TodoModel.add() Funktion aufgerufen und gibt einfach einen Status von 200 zurück und eine Bestätigungsnachricht an den Benutzer.

Andernfalls wird nur ein ähnlicher Fehler ausgegeben wie in der vorherigen API.

Jetzt sind wir fertig. Starten Sie Ihr Terminal und stellen Sie sicher, dass Ihre MySQL-Instanz läuft. Geben Sie in Ihrem Terminal Folgendes ein:

$ deno run --allow-net server.ts 

Gehen Sie zu Postman und führen Sie die API-Route für diesen Controller aus:

Das ist großartig, jetzt haben wir zwei funktionierende APIs. Nur noch drei.

[GET] todo by id API

In Ihrer models/todo.ts Datei, fügen Sie die Definition für diese beiden Funktionen hinzu, doesExistById() und getById() :

export default {
   /**
   * Takes in the id params & checks if the todo item exists
   * in the database
   * @param id
   * @returns boolean to tell if an entry of todo exits in table
   */
  doesExistById: async ({ id }: Todo) => {
    const [result] = await client.query(
      `SELECT COUNT(*) count FROM ${TABLE.TODO} WHERE id = ? LIMIT 1`,
      [id],
    );
    return result.count > 0;
  },
  /**
   * Takes in the id params & returns the todo item found
   * against it.
   * @param id
   * @returns object of todo item
   */
  getById: async ({ id }: Todo) => {
    return await client.query(
      `SELECT * FROM ${TABLE.TODO} WHERE id = ?`,
      [id],
    );
  },
}

Lassen Sie uns über jede Funktion einzeln sprechen:

  • doesExistById nimmt eine id auf und gibt einen boolean zurück zeigt an, ob eine bestimmte Aufgabe in der Datenbank existiert oder nicht.

Lassen Sie uns diese Funktion aufschlüsseln:

const [result] = await client.query(
  `SELECT COUNT(*) count FROM ${TABLE.TODO} WHERE id = ? LIMIT 1`,
  [id],
);
return result.count > 0;

Wir vergleichen einfach die Anzahl hier in der Tabelle mit einer bestimmten Aufgaben-ID. Wenn die Anzahl größer als Null ist, geben wir true zurück . Andernfalls geben wir false zurück .

  • getById gibt das todo-Element für eine bestimmte ID zurück:
return await client.query(
  `SELECT * FROM ${TABLE.TODO} WHERE id = ?`,
  [id],
);

Wir führen hier einfach eine MySQL-Abfrage aus, um eine Aufgabe nach ID zu erhalten, und geben das Ergebnis so zurück, wie es ist.

Gehen Sie als Nächstes zu Ihrer controllers/todo.ts -Datei und fügen Sie eine Definition für getTodoById hinzu Controller-Methode:

export default {
   /**
   * @description Get todo by id
   * @route GET todos/:id
   */
  getTodoById: async (
    { params, response }: { params: { id: string }; response: any },
  ) => {
    try {
      const isAvailable = await TodoModel.doesExistById(
        { id: Number(params.id) },
      );

      if (!isAvailable) {
        response.status = 404;
        response.body = {
          success: false,
          message: "No todo found",
        };
        return;
      }

      const todo = await TodoModel.getById({ id: Number(params.id) });
      response.status = 200;
      response.body = {
        success: true,
        data: todo,
      };
    } catch (error) {
      response.status = 400;
      response.body = {
        success: false,
        message: `Error: ${error}`,
      };
    }
  },
}

Lassen Sie uns dies in zwei kleinere Teile aufteilen:

const isAvailable = await TodoModel.doesExistById(
  { id: Number(params.id) },
);

if (!isAvailable) {
  response.status = 404;
  response.body = {
    success: false,
    message: "No todo found",
  };
  return;
}

Zuerst prüfen wir mit dieser Methode, ob die Aufgabe in der Datenbank gegen eine ID existiert:

const isAvailable = await TodoModel.doesExistById(
  { id: Number(params.id) },
);

Hier müssen wir params.id konvertieren in eine Number weil unsere todo-Schnittstelle nur id akzeptiert als Zahl. Als nächstes übergeben wir einfach params.id zu doesExistById Methode. Diese Methode wird als boolescher Wert zurückgegeben.

Dann prüfen wir einfach, ob die Aufgabe nicht verfügbar ist, und geben einen 404 zurück Methode mit unserer Standardantwort wie bei den vorherigen Endpunkten:

if (!isAvailable) {
  response.status = 404;
  response.body = {
    success: false,
    message: "No todo found",
  };
  return;
}

Dann haben wir:

try {
const todo: Todo = await TodoModel.getById({ id: Number(params.id) });
response.status = 200;
response.body = {
  success: true,
  data: todo,
};
} catch (error) {
response.status = 400;
response.body = {
  success: false,
  message: `Error: ${error}`,
};

Dies ähnelt dem, was wir in unseren vorherigen APIs getan haben. Hier holen wir einfach Daten aus der Datenbank und setzen die Variable todo , und dann die Antwort zurückgeben. Wenn ein Fehler auftritt, geben wir einfach eine Standardfehlermeldung im catch-Block an den Benutzer zurück.

Starten Sie jetzt Ihr Terminal und stellen Sie sicher, dass Ihre MySQL-Instanz läuft. Geben Sie in Ihrem Terminal Folgendes ein:

$ deno run --allow-net server.ts 

Gehen Sie zu Postman und führen Sie die API-Route für diesen Controller aus.

Denken Sie daran, dass wir bei jedem Neustart unseres Servers die db zurücksetzen. Wenn Sie dieses Verhalten nicht möchten, können Sie run einfach auskommentieren Funktion in der Datei db/client.ts .

gibt die Aufgabe für diese ID zurück, falls gefunden" width="2000" height="1165" loading=" faul">

Bisher haben wir APIs erstellt für:

  • Alle Todos erhalten
  • Eine neue Aufgabe erstellen
  • Eine Aufgabe nach ID abrufen

Und hier sind die verbleibenden APIs:

  • Eine Aufgabe nach ID aktualisieren
  • Eine Aufgabe nach ID löschen

[PUT] Todo-by-id-API aktualisieren

Lassen Sie uns zuerst ein Modell für diese API erstellen. Gehen Sie in unsere models/todo.ts -Datei und fügen Sie eine Definition für eine updateById hinzu Funktion:

**
 * Updates the content of a single todo item
 * @param id
 * @param todo
 * @param isCompleted
 * @returns integer (count of effect rows)
 */
updateById: async ({ id, todo, isCompleted }: Todo) => {
  const result = await client.query(
    `UPDATE ${TABLE.TODO} SET todo=?, isCompleted=? WHERE id=?`,
    [
      todo,
      isCompleted,
      id,
    ],
  );
  // return count of rows updated
  return result.affectedRows;
},

Die updateById nimmt 3 Parameter auf:id , todo , und isCompleted .

Wir führen einfach eine MySQL-Abfrage innerhalb dieser Funktion aus:

onst result = await client.query(
  `UPDATE ${TABLE.TODO} SET todo=?, isCompleted=? WHERE id=?`,
  [
    todo,
    isCompleted,
    id,
  ],
);

Dadurch wird todo eines einzelnen Aufgabeneintrags aktualisiert und isCompleted durch eine bestimmte id .

Als nächstes geben wir eine Anzahl von Zeilen zurück, die durch diese Abfrage aktualisiert wurden, indem wir Folgendes tun:

  // return count of rows updated
  return result.affectedRows;

Die Zählung ist entweder 0 oder 1, aber nie mehr als 1. Das liegt daran, dass wir eindeutige IDs in unserer Datenbank haben – mehrere Todos mit derselben ID können nicht existieren.

Als nächstes gehen Sie zu unserer controllers/todo.ts -Datei und fügen Sie eine Definition für updateTodoById hinzu Funktion:

updateTodoById: async (
  { params, request, response }: {
    params: { id: string };
    request: any;
    response: any;
  },
) => {
  try {
    const isAvailable = await TodoModel.doesExistById(
      { id: Number(params.id) },
    );
    if (!isAvailable) {
      response.status = 404;
      response.body = {
        success: false,
        message: "No todo found",
      };
      return;
    }

    // if todo found then update todo
    const body = await request.body();
    const updatedRows = await TodoModel.updateById({
      id: Number(params.id),
      ...body.value,
    });
    response.status = 200;
    response.body = {
      success: true,
      message: `Successfully updated ${updatedRows} row(s)`,
    };
  } catch (error) {
    response.status = 400;
    response.body = {
      success: false,
      message: `Error: ${error}`,
    };
  }
},

Dies ist fast dasselbe wie bei unseren früheren APIs, die wir geschrieben haben. Der Teil, der hier neu ist, ist dieser:

// if todo found then update todo
const body = await request.body();
const updatedRows = await TodoModel.updateById({
  id: Number(params.id),
  ...body.value,
});

Wir erhalten einfach den Text, den der Benutzer uns in JSON sendet, und übergeben den Text an unsere TodoModel.updateById Funktion.

Wir müssen die id konvertieren an eine Nummer, die unserer Todo-Schnittstelle entspricht.

Die Abfrage wird ausgeführt und gibt die Anzahl der aktualisierten Zeilen zurück. Von dort geben wir es einfach in unserer Antwort zurück. Wenn ein Fehler auftritt, geht es zum catch-Block, wo wir unsere Standard-Antwortnachricht zurückgeben.

Lassen Sie uns das ausführen und sehen, ob es funktioniert. Stellen Sie sicher, dass Ihre MySQL-Instanz ausgeführt wird, und führen Sie Folgendes von Ihrem Terminal aus:

$ deno run --allow-net server.ts 

Gehen Sie zu Postman und führen Sie die API-Route für diesen Controller aus:

[DELETE] todo by id API

In Ihrer models/todo.ts Datei eine Funktion namens deleteById erstellen :

/**
 * Deletes a todo by ID
 * @param id
 * @returns integer (count of effect rows)
 */
deleteById: async ({ id }: Todo) => {
  const result = await client.query(
    `DELETE FROM ${TABLE.TODO} WHERE id = ?`,
    [id],
  );
  // return count of rows updated
  return result.affectedRows;
},

Hier übergeben wir einfach eine id als Parameter und verwenden Sie dann die Lösch-MySQL-Abfrage. Wir geben dann die aktualisierte Anzahl von Zeilen zurück. Der aktualisierte Zähler ist entweder 0 oder 1, da die ID jeder Aufgabe eindeutig ist.

Als nächstes gehen Sie in Ihre controllers/todo.ts Datei und definieren Sie eine deleteByTodoId Methode:

/**
 * @description Delete todo by id
 * @route DELETE todos/:id
 */
deleteTodoById: async (
  { params, response }: { params: { id: string }; response: any },
) => {
  try {
    const updatedRows = await TodoModel.deleteById({
      id: Number(params.id),
    });
    response.status = 200;
    response.body = {
      success: true,
      message: `Successfully updated ${updatedRows} row(s)`,
    };
  } catch (error) {
    response.status = 400;
    response.body = {
      success: false,
      message: `Error: ${error}`,
    };
  }
},

Das ist ziemlich einfach. Wir übergeben die params.id zu unserer TodoModel.deleteById -Methode und gibt die Anzahl der mit dieser Abfrage aktualisierten Zeilen zurück.

Wenn irgendetwas schief geht, wird ein Fehler in den Catch-Block geworfen, der unsere Standard-Fehlerantwort zurückgibt.

Sehen wir uns das mal an.

Stellen Sie sicher, dass Ihre MySQL-Instanz ausgeführt wird. Geben Sie in Ihrem Terminal Folgendes ein:

$ deno run --allow-net server.ts 

Gehen Sie zu Postman und führen Sie die API-Route für diesen Controller aus:

Damit sind wir mit unserem Deno + Oak + MySQL-Tutorial fertig.

Der gesamte Quellcode ist hier verfügbar:https://github.com/adeelibr/deno-playground. Wenn Sie ein Problem finden, lassen Sie es mich einfach wissen. Oder stellen Sie einfach eine Pull-Anfrage und ich weise Sie im Repository darauf hin.

Wenn Sie dieses Tutorial hilfreich fanden, teilen Sie es bitte. Und wie immer bin ich auf Twitter unter @adeelibr erreichbar. Ich würde gerne Ihre Meinung dazu hören.