Приложение на PHP
На этой странице подробно разбирается код тестового приложения, доступного в составе PHP SDK YDB.
Примечание
Материал статьи дополняется.
Инициализация соединения с базой данных
Для взаимодействия с YDB создается экземпляр драйвера, клиента и сессии:
- Драйвер YDB отвечает за взаимодействие приложения и YDB на транспортном уровне. Драйвер должен существовать на всем протяжении жизненного цикла работы с YDB и должен быть инициализирован перед созданием клиента и сессии.
- Клиент YDB работает поверх драйвера YDB и отвечает за работу с сущностями и транзакциями.
- Сессия YDB содержит информацию о выполняемых транзакциях и подготовленных запросах и содержится в контексте клиента YDB.
Фрагмент кода приложения для инициализации драйвера:
<?php
use YdbPlatform\Ydb\Ydb;
$config = [
// Database path
'database' => '/ru-central1/b1glxxxxxxxxxxxxxxxx/etn0xxxxxxxxxxxxxxxx',
// Database endpoint
'endpoint' => 'ydb.serverless.yandexcloud.net:2135',
// Auto discovery (dedicated server only)
'discovery' => false,
// IAM config
'iam_config' => [
//'root_cert_file' => './CA.pem', Root CA file (uncomment for dedicated server)
],
'credentials' => new AccessTokenAuthentication('AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA') // use from reference/ydb-sdk/auth
];
$ydb = new Ydb($config);
Создание строковых таблиц
Выполняется создание строковых таблиц, которые используются в дальнейших операциях тестового приложения. В результате исполнения шага в базе данных будут созданы строковые таблицы модели данных справочника сериалов:
series
- Сериалыseasons
- Сезоныepisodes
- Эпизоды
После создания вызывается метод получения информации об объекте схемы данных, и выводится результат его выполнения.
Для создания строковых таблиц используется метод session->createTable()
:
protected function createTabels()
{
$this->ydb->table()->retrySession(function (Session $session) {
$session->createTable(
'series',
YdbTable::make()
->addColumn('series_id', 'UINT64')
->addColumn('title', 'UTF8')
->addColumn('series_info', 'UTF8')
->addColumn('release_date', 'UINT64')
->primaryKey('series_id')
);
}, true);
$this->print('Table `series` has been created.');
$this->ydb->table()->retrySession(function (Session $session) {
$session->createTable(
'seasons',
YdbTable::make()
->addColumn('series_id', 'UINT64')
->addColumn('season_id', 'UINT64')
->addColumn('title', 'UTF8')
->addColumn('first_aired', 'UINT64')
->addColumn('last_aired', 'UINT64')
->primaryKey(['series_id', 'season_id'])
);
}, true);
$this->print('Table `seasons` has been created.');
$this->ydb->table()->retrySession(function (Session $session) {
$session->createTable(
'episodes',
YdbTable::make()
->addColumn('series_id', 'UINT64')
->addColumn('season_id', 'UINT64')
->addColumn('episode_id', 'UINT64')
->addColumn('title', 'UTF8')
->addColumn('air_date', 'UINT64')
->primaryKey(['series_id', 'season_id', 'episode_id'])
);
}, true);
$this->print('Table `episodes` has been created.');
}
Метод session->createTable()
не позволяет создавать колоночные таблицы. Это можно сделать с помощью метода session->query()
, который выполняет YQL-запросы.
Если вы создали строковую таблицу и хотите вывести информацию о её структуре и убедиться, что она успешно создалась, воспользуйтесь методомsession->describeTable()
:
protected function describeTable($table)
{
$data = $ydb->table()->retrySession(function (Session $session) use ($table) {
return $session->describeTable($table);
}, true);
$columns = [];
foreach ($data['columns'] as $column) {
if (isset($column['type']['optionalType']['item']['typeId'])) {
$columns[] = [
'Name' => $column['name'],
'Type' => $column['type']['optionalType']['item']['typeId'],
];
}
}
print('Table `' . $table . '`');
print_r($columns);
print('');
print('Primary key: ' . implode(', ', (array)$data['primaryKey']));
}
Запись данных
Выполняется запись данных в созданные строковые таблицы с использованием команды UPSERT
языка запросов YQL. Применяется режим передачи запроса на изменение данных с автоматическим подтверждением транзакции в одном запросе к серверу.
Фрагмент кода, демонстрирующий выполнение запроса на запись данных:
protected function upsertSimple()
{
$ydb->table()->retryTransaction(function (Session $session) {
$session->query('
DECLARE $series_id AS Uint64;
DECLARE $season_id AS Uint64;
DECLARE $episode_id AS Uint64;
DECLARE $title AS Utf8;
UPSERT INTO episodes (series_id, season_id, episode_id, title)
VALUES ($series_id, $season_id, $episode_id, $title);', [
'$series_id' => (new Uint64Type(2))->toTypedValue(),
'$season_id' => (new Uint64Type(6))->toTypedValue(),
'$episode_id' => (new Uint64Type(1))->toTypedValue(),
'$title' => (new Utf8Type('TBD'))->toTypedValue(),
]);
}, true);
print('Finished.');
}
Получение выборки данных
Выполняется запрос на получение выборки данных с использованием команды SELECT
языка запросов YQL. Демонстрируется обработка полученной выборки в приложении.
Для выполнения YQL-запросов используется метод session->query()
.
$result = $ydb->table()->retryTransaction(function (Session $session) {
return $session->query('
DECLARE $seriesID AS Uint64;
$format = DateTime::Format("%Y-%m-%d");
SELECT
series_id,
title,
$format(DateTime::FromSeconds(CAST(release_date AS Uint32))) AS release_date
FROM series
WHERE series_id = $seriesID;', [
'$seriesID' => (new Uint64Type(1))->toTypedValue()
]);
}, true, $params);
print_r($result->rows());
Параметризованные запросы
Выполняется запрос к данным с использованием параметров. Этот вариант выполнения запросов является предпочтительным, так как позволяет серверу переиспользовать план исполнения запроса при последующих его вызовах, а также спасает от уязвимостей вида SQL Injection.
Для использования параметризированных запросов можно использовать следующий код:
protected function selectPrepared($series_id, $season_id, $episode_id)
{
$result = $ydb->table()->retryTransaction(function (Session $session) use ($series_id, $season_id, $episode_id) {
$prepared_query = $session->prepare('
DECLARE $series_id AS Uint64;
DECLARE $season_id AS Uint64;
DECLARE $episode_id AS Uint64;
$format = DateTime::Format("%Y-%m-%d");
SELECT
title AS `Episode title`,
$format(DateTime::FromSeconds(CAST(air_date AS Uint32))) AS `Air date`
FROM episodes
WHERE series_id = $series_id AND season_id = $season_id AND episode_id = $episode_id;');
return $prepared_query->execute(compact(
'series_id',
'season_id',
'episode_id'
));
},true);
$this->print($result->rows());
}