2026-02-07 15:54:21 +03:00
2026-02-07 15:54:21 +03:00
2026-02-07 15:54:21 +03:00
2026-02-07 15:54:21 +03:00
2026-02-07 15:54:21 +03:00
2026-02-07 15:54:21 +03:00

Database (PocketMine-MP)

Плагин для PMMP 5.36+ с поддержкой PostgreSQL/MySQL через PDO, пулом соединений, миграциями, ORM на атрибутах и кэшем сущностей.

Требования

  • PHP 8.1+ (как у PMMP 5.x).
  • Расширения: pdo + pdo_pgsql (PostgreSQL) или pdo_mysql (MySQL). Проверяется при запуске.

Установка

  1. Соберите плагин (zip папку pmmp/Database или сборка через DevTools).
  2. Поместите архив/папку в plugins/.
  3. Запустите сервер один раз для генерации config.yml.
  4. Заполните config.yml, перезапустите сервер.

Конфигурация (config.yml)

driver: "postgres"   # postgres | mysql
host: "127.0.0.1"
port: 5432           # 3306 для mysql по умолчанию
database: "server"
username: "postgres"
password: ""
options:
  persistent: false  # persistent соединения PDO
  timeoutSeconds: 10
pool:
  size: 4            # размер пула PDO

cache:
  enabled: true
  writeBehind: true
  flushIntervalSeconds: 10
  maxDirty: 100
  ttlSeconds: 0
  maxEntries: 0
  preloadBatchSize: 20
  preloadDelayTicks: 20
  preloadAsync: true

migrations:
  enabled: true
  table: "db_migrations"

Быстрый старт

use andrewkydev\Database\DatabaseProvider;
use andrewkydev\Database\ORM\Attributes as ORM;
use andrewkydev\Database\ORM\Conditions;

$db = DatabaseProvider::get();

// Raw SQL
$db->query()->execute("UPDATE players SET level = level + 1 WHERE username = ?", ["Steve"]);

// ORM-модель
#[ORM\Entity(table: "players")]
final class Player {
    #[ORM\Id(autoIncrement: true)]
    #[ORM\Column(name: "id")]
    public int $id;

    #[ORM\Column(unique: true, length: 32)]
    #[andrewkydev\Database\ORM\Attributes\CacheKey]
    public string $username;

    #[ORM\Column]
    public int $level;
}

$orm = $db->orm();
$orm->enableCache(Player::class, preload: true);

$player = $orm->findOneWhere(Player::class, "username = ?", ["Steve"]);
$top = $orm->query(Player::class)
    ->where(Conditions::gt("level", 10))
    ->orderBy("level DESC")
    ->limit(10)
    ->list();

Компоненты API

  • DatabaseApi (через DatabaseProvider::get()):
    • config() — текущий DatabaseConfig.
    • schema()SchemaManager (DDL: create/drop db/table, колонки, индексы).
    • query()QueryRunner (сырой SQL sync/async).
    • orm()EntityManager (ORM, кэш, QueryBuilder).
    • migrations()MigrationManager.

Сырые запросы (QueryRunner)

  • execute($sql, $params=[])rowCount().
  • query($sql, $params=[], $mapper=null) — массив строк или маппер.
  • executeAsync/queryAsync($sql, $params, $onSuccess, $onError=null) — выполняется в async-пуле PMMP, создаёт отдельный PDO.

ORM и атрибуты

  • Основные атрибуты: Entity, Id(autoIncrement), Column(name, nullable, length, unique, type), Json, CacheKey, Transient.
  • Связи: OneToOne, ManyToOne, OneToMany, ManyToMany (target, mappedBy, joinColumn, referencedColumn, joinTable, inverseJoinColumn, cascadePersist/remove, lazy).
  • Ленивая загрузка свойств: LazyRelationsTrait.

Операции ORM (EntityManager)

  • CRUD: insert/update/delete/save + async аналоги.
  • Поиск: findById/findAll/findOneWhere/findWhere/count/exists/deleteWhere (+ async).
  • Построитель: query(Class)::QueryBuilder (select/where/and/or/group/having/order/limit, joinFetch для manyToOne/oneToOne, withRelations для загрузки связей, async listAsync/oneAsync/countAsync/existsAsync/deleteAsync).
  • Загрузка связей: loadRelation(s) и батч loadRelationsFor.

Условия (Conditions)

eq, ne, gt, gte, lt, lte, like, in, isNull, isNotNull, raw. Комбинации через Condition->and()/or().

Кэш сущностей

  • Включается cache.enabled.
  • Регистрация: $orm->enableCache(Model::class, ['id','username'], preload: true);
  • Ключи по умолчанию: Id, поля с CacheKey, уникальные колонки.
  • writeBehind=true: update/delete складываются в очередь (CacheManager) и сбрасываются периодически (CacheFlushTask) или при достижении maxDirty.
  • ttlSeconds и maxEntries контролируют размер/старение. Прогрев — CachePreloadTask/CachePreloadAsyncTask.

Миграции

  • Интерфейс Migration { version(): int; up(SchemaManager $schema, QueryRunner $query): void; }
  • Регистрация: $db->migrations()->register(new class implements Migration {...});
  • Запуск: $db->migrations()->runPending(); (создаёт таблицу migrations.table при необходимости).
  • Генерация схемы по модели: OrmSchema::fromEntity(Model::class, SqlDialect::POSTGRES|MYSQL)SchemaManager::createTable(...).

DDL (SchemaManager)

  • createDatabase/dropDatabase
  • createTable(TableSpec), dropTable
  • addColumn/updateColumn/dropColumn
  • addIndex/dropIndex (учитывает синтаксис Postgres/MySQL).

Асинхронность

  • Все async методы используют Server::getInstance()->getAsyncPool() и собственный PDO, не блокируя main thread.
  • Колбэки: onSuccess($rows|$entity|$count) и опциональный onError($message).

Практические советы

  • Всегда задавайте #[Id] и уникальные поля — это улучшает кэш и генерацию схемы.
  • Для критичных данных можно отключить writeBehind, чтобы обновления уходили сразу.
  • joinFetch используйте для manyToOne/oneToOne, а большие коллекции грузите через withRelations или отдельные запросы.
  • Postgres: автоинкремент переводится в SERIAL/BIGSERIAL; MySQL — AUTO_INCREMENT.

Отладка и проблемы

  • Ошибка о расширениях — установите/включите pdo, pdo_pgsql или pdo_mysql.
  • DatabaseApi is not initialized — плагин ещё не загрузился; обращайтесь к DatabaseProvider::get() после onEnable.
  • Пустой пул — проверьте доступ к БД и креды в конфиге.
Description
No description provided
Readme 58 KiB
Languages
PHP 100%