Задать вопрос
@crack_user

Что лучше использовать для связей в бд?

Разрабатываю апишку, и встал выбор, как лучше использовать связи между таблицами, через 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;
    }
  • Вопрос задан
  • 61 просмотр
Подписаться 1 Простой Комментировать
Пригласить эксперта
Ответы на вопрос 1
ipatiev
@ipatiev Куратор тега PHP
Потомок старинного рода Ипатьевых-Колотитьевых
Ну разумеется, что в общем случае через SQL-запросы. Они для того и придуманы.
Но есть нюансы, иногда связанные данные приходится доставать другими методами.
Например, чтобы не делать 500 отдельных запросов, берутся id нужных записей и выбираются одним запросом через where in()

Кстати, лучше всё-тиаки разделить код на модели и контроллеры. SQL убрать в модели, а в контроллерах оставить только вот это вот if ($pools) {
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы