Skip to content

Latest commit

 

History

History
199 lines (149 loc) · 13.7 KB

File metadata and controls

199 lines (149 loc) · 13.7 KB

CLAUDE.md

Этот файл содержит рекомендации для Claude Code (claude.ai/code) при работе с кодом в данном репозитории.

Обзор проекта

krugozor/database — это библиотека классов PHP >= 8.0 для простой, удобной, быстрой и безопасной работы с базой данных MySQL с использованием расширения mysqli. Библиотека предоставляет систему типизированных заполнителей, которая автоматически экранирует SQL-параметры для предотвращения SQL-инъекций, сохраняя при этом читаемость и отлаживаемость SQL-запросов.

Пространство имён: Krugozor\Database

Ключевая философия разработки:

  • Это НЕ ORM, SQL-конструктор или реализация ActiveRecord
  • Это обёртка над mysqli, которая добавляет систему экранирования параметров на основе заполнителей
  • Разработчики пишут обычный SQL с типизированными заполнителями вместо ручного экранирования значений
  • Библиотека дополняет mysqli, а не заменяет её - вы можете получить доступ к базовому объекту mysqli

Основная архитектура

Основные классы

  1. Mysql (src/Mysql.php) - Основной класс подключения к базе данных и выполнения запросов

    • Управляет подключением через mysqli
    • Парсит SQL-шаблоны с заполнителями и подставляет экранированные значения
    • Два режима работы: MODE_STRICT (строгое соответствие типов) и MODE_TRANSFORM (толерантное преобразование типов, по умолчанию)
    • Сохраняет выполненные запросы при включённой отладке
    • Поддерживает интернационализированные сообщения об ошибках (английский и русский)
  2. Statement (src/Statement.php) - Обёртка над mysqli_result для удобного получения данных

    • Предоставляет методы для выборки результатов в виде ассоциативных массивов, индексированных массивов или объектов
    • Методы для одной строки: fetchAssoc(), fetchRow(), fetchObject(), getOne()
    • Методы для множества строк: fetchAssocArray(), fetchRowArray(), fetchObjectArray()
    • Автоматически освобождает mysqli_result при уничтожении объекта
  3. MySqlException (src/MySqlException.php) - Пользовательский класс исключений, расширяющий Exception

Система заполнителей

Основная особенность библиотеки — типизированные заполнители, которые автоматически экранируют значения в соответствии с их типом:

Скалярные заполнители

  • ?i - Целое число (например, ?i123)
  • ?d - Число с плавающей точкой (например, ?d12.56)
  • ?s - Строка с экранированием (например, "?s""д\'Артаньян")
  • ?S - Строка для LIKE с экранированием % и _ (например, "%?S%""%\% \_")
  • ?n - Литерал NULL (игнорирует аргумент, всегда выводит NULL)
  • ?f - Имя поля/таблицы с экранированием обратными кавычками (например, ?f`field_name`)

Заполнители массивов

  • ?ai, ?ad, ?as - Простые массивы (например, ?ai с [1, 2, 3]"1", "2", "3")
  • ?Ai, ?Ad, ?As - Ассоциативные массивы в виде пар ключ=значение (например, ?As`name` = "value", `age` = "25")
  • ?a[?i, "?s"] - Явное указание типа для элементов массива
  • ?A[?i, "?s"] - Явное указание типа для элементов ассоциативного массива

Важно: Строковые заполнители (?s, ?S) должны быть обёрнуты в кавычки в SQL-шаблоне (например, 'WHERE name = "?s"'), в отличие от подготовленных выражений PDO.

Команды для разработки

Тестирование

# Запуск примера/тестового скрипта (требуется подключение к MySQL)
php console/tests.php

Перед запуском тестов:

  1. Настройте подключение к MySQL в console/tests.php (константы: MYSQL_SERVER, MYSQL_USER, MYSQL_PASSWORD, MYSQL_PORT)
  2. Убедитесь, что ваш пользователь MySQL имеет привилегию CREATE для создания тестовой базы данных
  3. Скрипт создаст временную базу данных krugozor_database_test и очистит её после выполнения

Установка

composer require krugozor/database

Зависимости

  • PHP >= 8.0
  • ext-mysqli
  • ext-mbstring

Общие шаблоны использования

Базовое подключение и запрос

use Krugozor\Database\Mysql;

$db = Mysql::create('localhost', 'user', 'password', 3306);
$db->setCharset('utf8')
   ->setDatabaseName('mydb');

// Выполнение запроса
$result = $db->query('SELECT * FROM users WHERE id = ?i', 123);
$row = $result->fetchAssoc();

Выбор режима

  • MODE_TRANSFORM (по умолчанию): Автоматически преобразует типы (например, "123"123 для ?i)
  • MODE_STRICT: Выбрасывает исключение при несоответствии типов

Установка режима: $db->setTypeMode(Mysql::MODE_STRICT);

Методы запросов

  • query(...$args) - Выполнить запрос с вариативными аргументами
  • queryArguments($sql, array $args) - Выполнить запрос с массивом аргументов
  • prepare(...$args) - Парсить SQL-шаблон без выполнения (полезно для построения запросов по частям)

Получение информации о запросах

  • getQueryString() - Получить последний выполненный SQL (после подстановки заполнителей)
  • getOriginalQueryString() - Получить SQL-шаблон (до подстановки)
  • getAffectedRows() - Получить количество строк, затронутых INSERT/UPDATE/DELETE
  • getLastInsertId() - Получить ID автоинкремента из последнего INSERT

Отладка

$db->setStoreQueries(true);
// ... выполнение запросов ...
$all_queries = $db->getQueries(); // Массив выполненных запросов

Доступ к нативному mysqli

$mysqli = $db->getMysqli(); // Доступ к базовому объекту mysqli

Структура файлов

src/
  Mysql.php          - Основной класс базы данных с подключением и парсингом запросов
  Statement.php      - Обёртка над результирующим набором
  MySqlException.php - Класс исключений
console/
  tests.php          - Комплексные примеры использования и тестовый скрипт

Важные особенности реализации

  1. Логика парсинга заполнителей (Mysql.php:655-838): Метод parse() использует многобайтовые строковые функции для поиска и замены заполнителей. Он поддерживает отслеживание смещения для корректной обработки замен переменной длины.

  2. Валидация типов: Три приватных метода обрабатывают проверку и преобразование типов:

    • getValueIntType() - Валидирует/преобразует целые числа
    • getValueFloatType() - Валидирует/преобразует числа с плавающей точкой
    • getValueStringType() - Валидирует/преобразует строки Каждый учитывает текущую настройку MODE_STRICT или MODE_TRANSFORM.
  3. Парсинг заполнителей массивов: Сложная логика обрабатывает как простые массивы (?ai), так и массивы с явным указанием типов (?a[?i, "?s"]). Парсер рекурсивно вызывает сам себя для элементов массива.

  4. Экранирование имён полей (Mysql.php:997-1034): Обрабатывает нотацию database.table путём разделения по . и оборачивания каждой части в обратные кавычки, удваивая существующие обратные кавычки.

  5. Обработка ошибок: Библиотека перехватывает как старые ошибки mysqli, так и mysqli_sql_exception, оборачивая их в MySqlException с локализованными сообщениями.

  6. Поддержка сериализации: Реализует __sleep() и __wakeup() для поддержки сериализации/десериализации, автоматически переподключаясь при десериализации.

Мультиязычная документация

Структура файлов

README.md           # Английская версия (основной файл в корне)
docs/
  README_ru.md      # Русская версия (ЭТАЛОН для всех переводов)
  README_fr.md      # Французская версия

Правила перевода

  1. Эталон — русский текст: Все переводы делаются ТОЛЬКО с русского файла docs/README_ru.md. Никогда не используй другие источники (старые файлы, backup и т.д.).

  2. Структура ссылок:

    • В README.md (корень): ссылки на переводы docs/README_ru.md, docs/README_fr.md
    • В docs/README_*.md: ссылка на английский ../README.md, на другие переводы README_*.md
    • Ссылка на console/tests.php: в корне ./console/tests.php, в docs ../console/tests.php
  3. Блок ссылок на языки в начале каждого файла:

    • Английский: **Other languages:**
    • Русский: **Другие языки:**
    • Французский: **Autres langues:**
    • Текущий язык НЕ включается в список ссылок
  4. Перевод контента:

    • Профессиональный перевод, не дословный
    • Технические термины (названия классов, методов, placeholders) НЕ переводятся
    • Примеры кода остаются на PHP, комментарии переводятся
    • Текстовые строки в примерах адаптируются к языку (например, "Д'Артаньян" → "d'Artagnan")
    • Ссылки на php.net ведут на соответствующую языковую версию (/ru/, /en/, /fr/)
  5. При обновлении переводов:

    • Сначала прочитать русский эталон docs/README_ru.md
    • Определить изменённые секции
    • Обновить ВСЕ файлы переводов, сохраняя идентичную структуру
    • Проверить соответствие примеров кода во всех версиях

Важные правила

  • Когда пользователь изменяет README_ru.md (или просит обновить переводы):
  1. Определить, какие секции изменились
  2. Обновить соответствующие секции во всех файлах переводов
  3. Сохранить специфичные для языка особенности перевода
  • Когда пользователь просит сделать перевод на новый язык:
  1. Эталон, с которого переводим - docs/README_ru.md
  • Отвечай пользователю на русском языке