Разрабатываю апишку, и встал выбор, как лучше использовать связи между таблицами, через SQL-запросы или же обычным кодом и множествами запросами?
Суть - есть таблица Pool, у неё есть холдеры (таблица Holders) и при запросе к /api/pool/getAll/, я должен получать как раз таки кол-во холдеров у нужного Pool, а также все поля записи Pool.
Также у Pool есть поле userId, которое отвечает за айдишник пользователя, который создал запись в Pool, и тут также возникает вопрос, что лучше, использовать SQL-запрос разово, или написать доп. метод для получения инфы о пользователе у Pool?
Пример ответа АПИ -
{
"ID": 1,
"title": "NOT",
"rewardPool": "Reward pool",
"logo": "not_logo",
"createTime": 1734874558,
"userId": 1041770840,
"creatorName": "vitalya_genius", // Берется из таблицы users, по полю userId из таблицы Pool
"creatorAvatar": "123", // Берется из таблицы users, по полю userId из таблицы Pool
"holdersCount": 1 // Берется из таблицы holders, где poolId = ID(из таблицы Pool)
},
Вот пример двух методов, которые переписал под sql -
public function getNew(): array
{
try {
$sql = "SELECT p.*, u.name AS creatorName, u.avatar AS creatorAvatar,
(SELECT COUNT(*) FROM holders h WHERE h.poolId = p.ID) AS holdersCount
FROM pool p
LEFT JOIN users u ON p.userId = u.id
ORDER BY p.createTime ASC
LIMIT 50";
$stmt = $this->pdo->prepare($sql);
$stmt->execute();
$pools = $stmt->fetchAll(PDO::FETCH_ASSOC);
if ($pools) {
$data = ['result' => $pools, 'status' => true];
} else {
$data = ['result' => 'Пулы не найдены', 'status' => false];
}
} catch (\Exception $exception) {
$data = ['result' => $exception->getMessage(), 'status' => false];
}
return $data;
}
public function getTop(): array
{
try {
$sql = "SELECT p.*,
u.name AS creatorName,
u.avatar AS creatorAvatar,
COUNT(h.poolId) AS holdersCount
FROM pool p
LEFT JOIN holders h ON p.id = h.poolId
LEFT JOIN users u ON p.userId = u.id
GROUP BY p.id
ORDER BY holdersCount DESC
LIMIT 50";
$stmt = $this->pdo->prepare($sql);
$stmt->execute();
$pools = $stmt->fetchAll(PDO::FETCH_ASSOC);
if ($pools) {
$data = ['result' => $pools, 'status' => true];
} else {
$data = ['result' => 'Пулы не найдены', 'status' => false];
}
} catch (\Exception $exception) {
$data = ['result' => $exception->getMessage(), 'status' => false];
}
return $data;
}
Ранее у меня были доп. методы - getPoolUser, и getPoolHolderCount и я их вызывал в getNew и getTop
В них я пробегался циклом и отправлял на каждую запись в таблице Pool - запросы к другим таблицам, к примеру для получения кол-ва Holders у нужного Pool.
У getPoolUser такой же был принцип.
public function getTop()
{
try {
$sql = "SELECT * FROM `pool`";
$stmt = $this->pdo->prepare($sql);
$stmt->execute();
$this->pools = $stmt->fetchAll(PDO::FETCH_ASSOC);
if ($this->pools) {
$this->getPoolUser();
$this->getPoolHolderCount();
$data = ['result' => $this->pools, 'status' => true];
} else {
$data = ['result' => 'Пулы не найдены', 'status' => false];
}
} catch (\Exception $exception) {
$data = ['result' => $exception->getMessage(), 'status' => false];
}
return $data;
}
public function getPoolHolderCount(): array
{
foreach($this->pools as $key => $pool)
{
$holdersModel = new Holders();
$holdersCount = $holdersModel->getCountByPoolId($pool['ID']);
$this->pools[$key]['holdersCount'] = $holdersCount['result'];
}
return $this->pools;
}
public function getCountByPoolId($poolId): array
{
$holderPrepare = $this->pdo->prepare("SELECT COUNT(*) FROM holders WHERE poolId = ?");
$holderPrepare->execute(array($poolId));
$holdersCount = $holderPrepare->fetchColumn();
return $holdersCount ?? 0;
}