Как стать автором
Обновить
930.36
OTUS
Цифровые навыки от ведущих экспертов

Создаем свою CRUD API на Express и MySQL: часть первая

Время на прочтение6 мин
Количество просмотров27K
Всем привет. В преддверии старта курса «Fullstack разработчик JavaScript», хотим поделиться небольшим материалом, который был написан нашим внештатным автором.



Express один из самых популярных веб-фреймворков, который поддерживает роутинг, миддлвейрс и систему шаблонов. Делать бэкенд на Node.js без Express в 2020 году — довольно странное занятие, ведь Express де-факто — каркас для создания веб-приложения на Node.js.
Сегодня мы попробуем создать несложное CRUD API используя базу данных MySQL. Опытный в Node.js читатель спросит, а где же MongoDB, с которым Node.js обычно применятся в паре но, скажу сразу, это статья больше для PHP разработчиков, которые хотят немного потрогать Node.js, и чтобы смягчить переход в новую экосистему мы воспользуемся MySQL. API мы будем создавать для несложного Todo приложения, на тот случай, если кто-то захочет к своей todo (и даже неважно, написанной с помощью React или нет), присоединить немного бэка и поиграть с ним.


«Архитектура» и суть нашего приложения



В нашем приложении можно будет создавать, получать, обновлять и удалять Todo. В общем, у нас будет минимальный набор функций CRUD (create read update delete).

В конце мы совместим приложение c приложением на React и все протестируем.

Для начала приведу структуру файлов приложения:



Дальше я приведу таблицу действий и методов, которые есть в нашем приложении:

Методы Url Действия
GET /deals получение всех дел
GET /deals/2 Получение id c номером 2
POST /deals добавление нового дела
PUT /deals/3 Обновить пользователя с id=3
DELETE /deals/3 удалить пользователя с id=3
DELETE /deals удалить всех пользователей

Создание своего Node.js приложения

Переходим в вашу любимую директорию, запускаем терминал и создаем ваше приложение. Кстати, из заголовка, наверное, понятно, что Node.js у вас уже должна быть установлена. Если вы еще этого не сделали, то этого просто не может быть скачайте по ссылке отсюда.

    $ mkdir CRUD_API
    $ cd CRUD_API

Дальше необходимо инициализировать наше приложение с помощью npm init. Т.к. приложение у нас скорее тестовое и обучающее, я воспользуюсь командной, которая заполнит все данные по дефолту, чтобы не тратить время на мелкие детали:

 npm init -y
 

Если что, потом руками в package.json вы сможете поменять данные на те, которые вам нужны: репозиторий github, тэги, автора, и т.д.

Потом нам нужно поставить все необходимые для работы приложения пакеты:

  npm i express mysql body-parser --save


Если вы собираетесь отправлять потом вашу разработку на github, вам стоит создать скрытый файл .gitignore, чтобы не таскать с собой тяжелейшие node_modules и не позориться. Пишем:

    touch .gitignore 
    code .gitignore 

Там вписываем node_modules, в дальнейшем в этот файл вы сможете вписать наименования папок и файлов, которые хотите увидеть потом на удаленном сервере.

Базовая настройка Express


В корневой папке проекта создаем файл server.js:

    const express = require("express");
    const bodyParser = require("body-parser");
    
    const app = express();
    
    //делаем наш парсинг в формате json
    app.use(bodyParser.json());
    
    // парсит запросы по типу: application/x-www-form-urlencoded
    app.use(bodyParser.urlencoded({ extended: true }));
    
    //  простой response - request
    app.get("/", (req, res) => {
      res.json({ message: "Это стартовая страница нашего приложения" });
    });
    
    // установить порт, и слушать запросы
    app.listen(3001, () => {
      console.log("Сервер запущен на 3001 порту");
    });

Теперь мы можем запустить сервер с помощью:

node server.js

Express нам нужен для создания своего api, а пакет body-parser помогает нам парсить request и создавать req.body, который пригодится для работы роутинга.

Сейчас наш сервер умеет следующее:

  • Создаем Express app, который отдает body-parser миддлевеир используя app.use()
  • у нас есть простой get, просто для тестирования работы приложения
  • Слушаем 3001 порт на все входящие изменения

Первично наше приложение работает, дальше можно заняться базой данных.

Создаем свою таблицу данных MySQL

Я очень надеюсь, что у читателя данной статьи нет проблемы с тем, чтобы самостоятельно скачать и установить MySQL и MySQLWorkBranch. Дальше вы самостоятельно создаете scheme(БД) с названием, которое вам больше нравится (в моем случае TODO), и потом выбрать молнию-запрос и скопировать/набрать следующую команду:

    CREATE TABLE IF NOT EXISTS `todo` (
        id int(11) NOT NULL PRIMARY KEY AUTO_INCREMENT,
        text varchar(255) NOT NULL
      ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

В нашей базе данных будет все по минимуму: только id и сам текст дел. Однако добавить ещё колоночку, в которой может описана, к примеру, срочность вашего дела, надеюсь, проблем не вызовет.

Конфигурация & коннект с нашей базой данных

Давайте установим и сконфигурируем соединение с базой данных. Мы создадим новую папку app прямо в нашей корневой папке, и там создадим файл db.config.js в папке config, вот примерно с таким содержанием, которое зависит от ваших настроек в MySQLWorkBranch. В моем случае файл будет выглядеть вот так:

  module.exports = {
    HOST: "localhost",
    USER: "pavel",
    PASSWORD: "",
    DB: "TODO"
  };

После этого создаем папку для описания наших моделей app/mode, в которой мы потом создадим модель:

  const mysql = require("mysql");
  const dbConfig = require("../config/db.config.js");
  
  // создаем соединение с нашей базой данных
  const connection = mysql.createConnection({
    host: dbConfig.HOST,
    user: dbConfig.USER,
    password: dbConfig.PASSWORD,
    database: dbConfig.DB
  });
  
  // открываем наше соединение с базой данных
  connection.connect(err => {
    if (err) throw error;
    console.log("успешно соединено с базой данных");
  });

  module.exports = connection;
   //экспортируем наше соединение

Создаем Модель

В папке model, мы создаем файл, который называется deal.model.js. Если у вас возникает вопрос, что же такое вообще модель, вам стоит прочитать статью вроде этой и ознакомиться с паттерном проектирования MVC. Я собираюсь создать конструктор для Deal объекта, и использовать connection для следующих CRUD функций:

  • создание нового дела
  • нахождение дела по id
  • получение всех дел
  • возможность обновлять наше дело по id
  • Удаление одного дела по id
  • полное удаление всех дел

Итого, нам придется заняться следующими делами:

  // конструктор нашего дела
  const Deal = function(deal) {
    this.text = deal.text;
  };
  //у нашей модели будут функции, с помощью которых можно осуществлять все операции CRUD, которые были озвучены в начале статьи:
  Deal.create = (newDeal, result) => {
    sql.query("INSERT INTO TODO SET ?", newDeal, (err, res) => {
      //операция вставки из SQL
      if (err) {
        console.log("error: ", err);
        result(err, null);
        //немного бедная обработка ошибок, но на первое время хватит
        return;
      }
  
      console.log("Дело сделано", { id: res.insertId, ...newDeal });
      result(null, { id: res.insertId, ...newDeal });
    });
  };


Остальную часть кода я размещу в spoiler, потому, что не вижу смысла приводить его весь, ведь там по сути повторяется паттерн кода, меняются только sql — команды и аргументы:

остальная часть кода
Deal.findById = (dealId, result) => {
sql.query(`SELECT * FROM TODO WHERE id = ${dealId}`, (err, res) => {
if (err) {
console.log(«error: », err);
result(err, null);
return;
}

if (res.length) {
console.log(«найдено дело: », res[0]);
result(null, res[0]);
return;
}

// когда ничего не удалось найти
result({ kind: «not_found» }, null);
});
};

Deal.getAll = result => {
sql.query(«SELECT * FROM TODO», (err, res) => {
if (err) {
console.log(«error: », err);
result(null, err);
return;
}

console.log(«deals: », res);
result(null, res);
});
};

Deal.updateById = (id, deal, result) => {
sql.query(
«UPDATE TODO SET text =? WHERE id = ?»,
[deal.text, id],
(err, res) => {
if (err) {
console.log(«error: », err);
result(null, err);
return;
}

if (res.affectedRows == 0) {
result({ kind: «not_found» }, null);
return;
}

console.log(«Обновлено дело », { id: id, ...deal });
result(null, { id: id, ...deal });
}
);
};

Deal.remove = (id, result) => {
sql.query(«DELETE FROM TODO WHERE id = ?», id, (err, res) => {
if (err) {
console.log(«error: », err);
result(null, err);
return;
}

if (res.affectedRows == 0) {
// если дело не удалось получить по id
result({ kind: «not_found» }, null);
return;
}
console.log(«Удален пользователь с », id);
result(null, res);
});
};

Deal.removeAll = result => {
sql.query(«DELETE FROM TODO», (err, res) => {
if (err) {
console.log(«error: », err);
result(null, err);
return;
}

console.log(`deleted ${res.affectedRows} deals`);
result(null, res);
});
};



На этом пока все. На подходе следующая часть этой статьи, в которой мы закончим написание бэка и примемся за его тестирование. И по традиции, несколько полезных ссылок:

Теги:
Хабы:
Всего голосов 11: ↑8 и ↓3+5
Комментарии4

Публикации

Информация

Сайт
otus.ru
Дата регистрации
Дата основания
Численность
101–200 человек
Местоположение
Россия
Представитель
OTUS