← Cloudflare D1 / d1 / tutorials
Создание справочника сотрудников
В этом руководстве вы узнаете, как с помощью D1 создать справочник сотрудников. Это приложение позволит пользователям просматривать данные о сотрудниках организации, а администраторам добавлять новых сотрудников прямо в приложении. Для этого вам сначала нужно будет настроить База данных D1 для удобного управления данными, а затем разработаете и развернёте приложение с помощью Фреймворк HonoX ↗ и Cloudflare Pages.
Предварительные требования
Прежде чем приступить к этому руководству, убедитесь, что у вас есть следующее:
- Аккаунт Cloudflare, если у вас его нет, зарегистрироваться ↗ прежде чем продолжить.
- Последняя версия npm ↗ установлен.
Если вы не хотите проходить настройку сейчас, просмотреть готовый код ↗ на GitHub.
1. Установите HonoX
В этом руководстве вы будете использовать HonoX ↗, метафреймворк для создания full-stack сайтов и веб-API при сборке вашего приложения. Чтобы использовать HonoX в своём проекте, выполните hono-create команда.
Чтобы начать, выполните следующую команду:
npm create hono@latestВ процессе настройки вам нужно будет указать имя каталога проекта и выбрать шаблон. При выборе укажите x-basic шаблон.
2. Инициализируйте приложение HonoX
После настройки проекта вы увидите список сгенерированных файлов, как показано ниже. Это типичная структура проекта для приложения HonoX:
.
├── app
│ ├── global.d.ts // global type definitions
│ ├── routes
│ │ ├── _404.tsx // not found page
│ │ ├── _error.tsx // error page
│ │ ├── _renderer.tsx // renderer definition
│ │ ├── about
│ │ │ └── [name].tsx // matches `/about/:name`
│ │ └── index.tsx // matches `/`
│ └── server.ts // server entry file
├── package.json
├── tsconfig.json
└── vite.config.tsПроект содержит каталоги с кодом приложения, маршрутами и настройками сервера, а также конфигурационные файлы для управления пакетами, TypeScript и Vite.
3. Создайте базу данных
Чтобы создать базу данных для своего проекта, используйте инструмент командной строки Cloudflare Wrangler, которое поддерживает wrangler d1 команду для операций с базой данных D1. Создайте новую базу данных с именем staff-directory с помощью следующей команды:
npx wrangler d1 create staff-directoryПосле создания базы данных вам нужно будет настроить привязка в конфигурационный файл Wrangler чтобы интегрировать базу данных с приложением.
Эта привязка позволяет приложению взаимодействовать с ресурсами Cloudflare, такими как базы данных D1, пространства имён KV и бакеты R2. Чтобы настроить её, создайте файл Wrangler в корневом каталоге проекта и укажите основные параметры:
{
"$schema": "./node_modules/wrangler/config-schema.json",
"name": "staff-directory",
// Set this to today's date
"compatibility_date": "2026-08-28"
}"$schema" = "./node_modules/wrangler/config-schema.json"
name = "staff-directory"
# Set this to today's date
compatibility_date = "2026-08-28"Далее добавьте данные привязки базы данных в файл Wrangler. Для этого нужно указать имя привязки (в данном случае, DB), которая будет использоваться для обращения к базе данных в вашем приложении, вместе с database_name и database_id указанный при создании базы данных:
{
"d1_databases": [
{
"binding": "DB",
"database_name": "staff-directory",
"database_id": "f495af5f-dd71-4554-9974-97bdda7137b3"
}
]
}[[d1_databases]]
binding = "DB"
database_name = "staff-directory"
database_id = "f495af5f-dd71-4554-9974-97bdda7137b3"Теперь ваше приложение настроено для доступа и взаимодействия с базой данных D1, будь то через командную строку или напрямую в коде.
Также потребуется внести изменения в конфигурационный файл Vite в vite.config.js. Добавьте следующие параметры конфигурации, чтобы Vite был правильно настроен для работы с привязками Cloudflare в локальной среде:
import adapter from "@hono/vite-dev-server/cloudflare";
export default defineConfig(({ mode }) => {
if (mode === "client") {
return {
plugins: [client()],
};
} else {
return {
plugins: [
honox({
devServer: {
adapter,
},
}),
pages(),
],
};
}
});4. Взаимодействуйте с D1
Чтобы взаимодействовать с базой данных D1, вы можете напрямую выполнять SQL-команды с помощью wrangler d1 execute команда:
wrangler d1 execute staff-directory --command "SELECT name FROM sqlite_schema WHERE type ='table'"Приведённая выше команда позволяет выполнять запросы или операции прямо из командной строки.
Для таких операций, как первоначальное заполнение данными или пакетная обработка, можно передать SQL-файл с командами. Для этого создайте schema.sql файл в корневом каталоге вашего проекта и вставьте свои SQL-запросы в этот файл:
CREATE TABLE locations (
location_id INTEGER PRIMARY KEY AUTOINCREMENT,
location_name VARCHAR(255) NOT NULL
);
CREATE TABLE departments (
department_id INTEGER PRIMARY KEY AUTOINCREMENT,
department_name VARCHAR(255) NOT NULL
);
CREATE TABLE employees (
employee_id INTEGER PRIMARY KEY AUTOINCREMENT,
name VARCHAR(255) NOT NULL,
position VARCHAR(255) NOT NULL,
image_url VARCHAR(255) NOT NULL,
join_date DATE NOT NULL,
location_id INTEGER REFERENCES locations(location_id),
department_id INTEGER REFERENCES departments(department_id)
);
INSERT INTO locations (location_name) VALUES ('London, UK'), ('Paris, France'), ('Berlin, Germany'), ('Lagos, Nigeria'), ('Nairobi, Kenya'), ('Cairo, Egypt'), ('New York, NY'), ('San Francisco, CA'), ('Chicago, IL');
INSERT INTO departments (department_name) VALUES ('Software Engineering'), ('Product Management'), ('Information Technology (IT)'), ('Quality Assurance (QA)'), ('User Experience (UX)/User Interface (UI) Design'), ('Sales and Marketing'), ('Human Resources (HR)'), ('Customer Support'), ('Research and Development (R&D)'), ('Finance and Accounting');Приведённые выше запросы создадут три таблицы: Locations, Departments, а также Employees. Чтобы заполнить эти таблицы начальными данными, используйте INSERT INTO команду. После подготовки файла схемы с помощью этих команд его можно применить к базе данных D1. Для этого используйте --file флаг, чтобы указать файл схемы для выполнения:
wrangler d1 execute staff-directory --file=./schema.sqlЧтобы выполнить схему локально и заполнить локальный каталог тестовыми данными, передайте --local флаг к приведённой выше команде.
5. Создайте SQL-операторы
После того как вы настроите базу данных D1 и сконфигурируете файл Wrangler, как описано в предыдущих шагах, ваша база данных станет доступна в коде через DB привязку. Это позволяет напрямую работать с базой данных, подготавливая и выполняя инструкции SQL. На следующем шаге вы узнаете, как с помощью этой привязки выполнять типичные операции с базой данных, такие как получение данных и вставка новых записей.
Получение данных из базы данных
export const findAllEmployees = async (db: D1Database) => {
const query = `
SELECT employees.*, locations.location_name, departments.department_name
FROM employees
JOIN locations ON employees.location_id = locations.location_id
JOIN departments ON employees.department_id = departments.department_id
`;
const { results } = await db.prepare(query).run();
const employees = results;
return employees;
};Вставка данных в базу данных
export const createEmployee = async (db: D1Database, employee: Employee) => {
const query = `
INSERT INTO employees (name, position, join_date, image_url, department_id, location_id)
VALUES (?, ?, ?, ?, ?, ?)`;
const results = await db
.prepare(query)
.bind(
employee.name,
employee.position,
employee.join_date,
employee.image_url,
employee.department_id,
employee.location_id,
)
.run();
const employees = results;
return employees;
};Полный список всех запросов, используемых в приложении, см. в db.ts ↗ файл в кодовой базе.
6. Разработайте интерфейс
Приложение использует hono/jsx для рендеринга. Настроить Renderer можно в app/routes/_renderer.tsx с использованием миддлвара, отрисовывающего JSX и служащего точкой входа для вашего приложения:
import { jsxRenderer } from 'hono/jsx-renderer'
import { Script } from 'honox/server'
export default jsxRenderer(({ children, title }) => {
return (
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>{title}</title>
<Script src="/app/client.ts" async />
</head>
<body>{children}</body>
</html>
)
})Добавьте привязки, определённые ранее в global.d.ts файл, где определены глобальные типы для TypeScript, что обеспечивает согласованность типов во всём приложении:
declare module "hono" {
interface Env {
Variables: {};
Bindings: {
DB: D1Database;
};
}
}Это приложение использует Tailwind CSS ↗ для стилизации. Чтобы использовать Tailwind CSS, см. Документация TailwindCSS ↗, либо выполните шаги доступен на GitHub ↗.
Чтобы вывести список сотрудников, вызовите findAllEmployees функцию из своего db.ts файл и вызовите его внутри routes/index.tsx файл. createRoute() функция, присутствующая в файле, служит вспомогательной функцией для определения маршрутов, обрабатывающих разные HTTP методы, такие как GET, POST, PUT, или DELETE.
import { css } from 'hono/css'
import { createRoute } from 'honox/factory'
import Counter from '../islands/counter'
const className = css`
font-family: sans-serif;
`
export default createRoute((c) => {
const name = c.req.query('name') ?? 'Hono'
return c.render(
<div class={className}>
<h1>Hello, {name}!</h1>
<Counter />
</div>,
{ title: name }
)
})Существующий код в файле содержит заглушку, использующую компонент Counter. Замените этот раздел следующим блоком кода:
import { createRoute } from 'honox/factory'
import type { FC } from 'hono/jsx'
import type { Employee } from '../db'
import { findAllEmployees, findAllDepartments, findAllLocations } from '../db'
const EmployeeCard: FC<{ employee: Employee }> = ({ employee }) => {
const { employee_id, name, image_url, department_name, location_name } = employee;
return (
<div className="max-w-sm bg-white border border-gray-200 rounded-lg shadow-md">
<a href={`/employee/${employee_id}`}>
<img className="bg-indigo-600 p-4 rounded-t-lg" src={image_url} alt={name} />
//...
</a>
</div>
);
};
export const GET = createRoute(async (c) => {
const employees = await findAllEmployees(c.env.DB)
const locations = await findAllLocations(c.env.DB)
const departments = await findAllDepartments(c.env.DB)
return c.render(
<section className="flex-grow">
<h1 className="mb-4 text-3xl font-extrabold text-gray-900 dark:text-white md:text-5xl lg:text-6xl mt-12">
<span className="text-transparent bg-clip-text bg-gradient-to-r to-blue-600 from-sky-400">{`Directory `}</span>
</h1>
//...
</section>
<section className="flex flex-wrap -mx-4">
{employees.map((employee) => (
<div className="w-full sm:w-1/2 md:w-1/3 lg:w-1/4 px-2 mb-4">
<EmployeeCard employee={employee} />
</div>
))}
</section>
</section>
)
})Этот фрагмент кода показывает, как импортировать findAllEmployees, findAllLocations, а также findAllDepartments функции из db.ts файл и как использовать привязку c.env.DB чтобы вызвать эти функции. С их помощью вы можете получать и отображать полученные данные на странице.
Добавление сотрудника
Используйте export POST маршрут для создания нового сотрудника через /admin страница:
import { createRoute } from "honox/factory";
import type { Employee } from "../../db";
import { getFormDataValue, getFormDataNumber } from "../../utils/formData";
import { createEmployee } from "../../db";
export const POST = createRoute(async (c) => {
try {
const formData = await c.req.formData();
const imageFile = formData.get("image_file");
let imageUrl = "";
// TODO: process image url with R2
const employeeData: Employee = {
employee_id: getFormDataValue(formData, "employee_id"),
name: getFormDataValue(formData, "name"),
position: getFormDataValue(formData, "position"),
image_url: imageUrl,
join_date: getFormDataValue(formData, "join_date"),
department_id: getFormDataNumber(formData, "department_id"),
location_id: getFormDataNumber(formData, "location_id"),
location_name: "",
department_name: "",
};
await createEmployee(c.env.DB, employeeData);
return c.redirect("/", 303);
} catch (error) {
return new Response("Error processing your request", { status: 500 });
}
});Хранение изображений в R2
При создании нового сотрудника загруженное изображение можно сохранить в бакете R2 ещё до добавления в базу данных.
Чтобы сохранить изображение в бакете R2:
- Создайте bucket R2.
- Загрузите изображение в этот бакет.
- Получите публичный URL изображения из бакета. Этот URL затем сохраняется в базе данных и указывает на изображение, хранящееся в бакете R2.
Используйте wrangler r2 bucket create команду для создания бакета:
wrangler r2 bucket create employee-avatarsПосле создания бакета добавьте привязку бакета R2 в файл Wrangler:
{
"r2_buckets": [
{
"binding": "MY_BUCKET",
"bucket_name": "employee-avatars"
}
]
}[[r2_buckets]]
binding = "MY_BUCKET"
bucket_name = "employee-avatars"Передайте привязку R2 в global.d.ts файле:
declare module "hono" {
interface Env {
Variables: {};
Bindings: {
DB: D1Database;
MY_BUCKET: R2Bucket;
};
}
}Чтобы сохранить загруженное изображение в бакете R2, используйте put() метод, предоставляемый R2. Он позволяет загрузить файл изображения в ваш бакет:
if (imageFile instanceof File) {
const key = `${new Date().getTime()}-${imageFile.name}`;
const fileBuffer = await imageFile.arrayBuffer();
await c.env.MY_BUCKET.put(key, fileBuffer, {
httpMetadata: {
contentType: imageFile.type || "application/octet-stream",
},
});
console.log(`File uploaded successfully: ${key}`);
imageUrl = `https://pub-8d936184779047cc96686a631f318fce.r2.dev/${key}`;
}См. GitHub ↗ с полным кодом проекта.
7. Разверните своё приложение HonoX
Когда приложение готово к развертыванию, используйте Wrangler для сборки и развертывания проекта в Cloudflare Network. Убедитесь, что вы вошли в аккаунт Cloudflare, выполнив wrangler whoami команду. Если вы не выполнили вход, Wrangler предложит войти, создав API-ключ, с помощью которого можно автоматически отправлять аутентифицированные запросы с вашего компьютера.
После успешного входа убедитесь, что ваш файл Wrangler настроен так же, как показано в блоке кода ниже:
{
"$schema": "./node_modules/wrangler/config-schema.json",
"name": "staff-directory",
// Set this to today's date
"compatibility_date": "2026-08-28",
"r2_buckets": [
{
"binding": "MY_BUCKET",
"bucket_name": "employee-avatars"
}
],
"d1_databases": [
{
"binding": "DB",
"database_name": "staff-directory",
"database_id": "f495af5f-dd71-4554-9974-97bdda7137b3"
}
]
}"$schema" = "./node_modules/wrangler/config-schema.json"
name = "staff-directory"
# Set this to today's date
compatibility_date = "2026-08-28"
[[r2_buckets]]
binding = "MY_BUCKET"
bucket_name = "employee-avatars"
[[d1_databases]]
binding = "DB"
database_name = "staff-directory"
database_id = "f495af5f-dd71-4554-9974-97bdda7137b3"Запустите wrangler deploy чтобы развернуть проект в Cloudflare. После развёртывания вы можете проверить работу приложения, перейдя по предоставленному URL-адресу развёртывания. В браузере должно отобразиться ваше приложение с базовым интерфейсом, который вы создали. Если в вашей базе данных нет данных, перейдите в /admin страницу, чтобы добавить нового сотрудника, и это должно вернуть нового сотрудника на вашей домашней странице.
Заключение
В этом руководстве вы создали приложение справочника сотрудников, в котором пользователи могут просматривать всех сотрудников организации. Обратитесь к Репозиторий Staff Directory ↗ с полным исходным кодом.