PhP_Raz
@PhP_Raz
Web - developer

Как правильно спроектировать базу и составить SQL запросы?

Здравствуйте!

Нужна помощь в проектировании базы и составлении SQL запросов.

Есть форма, которая позволяет посетителю оставить отзыв/комментарий. Форма состоит из полей: Ф.И.О., Email, Категория отзыва (можно выбрать несколько категорий), Текст отзыва. Есть админская часть, в которой админ может редактировать, добавлять и удалять категории отзыва. Я создал базу, под это приложение, которое состоит из 4 таблиц: user(для авторизации админа), comment(для хранения отзывов), category(для категорий) и cat_id(в которой хранится ID коммента и категории). Вот так она выглядит:
9ab7869b5c0a4b30884701e933c3588f.jpg
Подойдет ли для такого приложения такая база? Стоит ли убрать таблицу cat_id, а в comment добавить столбец category_id в которой будут храниться id категорий? Как лучше всего нормализовать такую базу?

Если оставить базу в таком виде, как связать столбцы comment.id с cat_id.comment_id и category.id с cat_id.category_id, чтобы, например, при удалении категории или комментария удалялись и связанные с ним записи из таблицы cat_id?
Для добавления записей в таблицу cat_id и вывода комментариев создал два метода:
public function create($comment_id, $category_id)
    {
        foreach ($category_id as $value) {
            $sql = 'INSERT INTO `cat_id`(`comment_id`, `category_id`) VALUES ("' . $comment_id . '", "' . $value . '")';
            $result = $this->mysqli->query($sql);
            if (!$result) {
                die($this->mysqli->error);
            }
        }
        return true;
    }
 
public function show_comment($id)
    {
        $sql = 'SELECT firstname, name, lastname, email, comment FROM `comment` WHERE comment.id = ' . $id;
        $result = $this->mysqli->query($sql);
        if (!$result) die($this->mysqli->error);
        $a = $result->fetch_assoc();
 
        $sql = 'SELECT category_id FROM `cat_id` WHERE cat_id.comment_id = ' . $id;
        $result = $this->mysqli->query($sql);
        if (!$result) die($this->mysqli->error);
        $b = $result->fetch_all(MYSQLI_ASSOC);
 
        $c = array();
        $sql = '';
        foreach ($b as $key => $value) {
            $sql .= 'SELECT title FROM `category` WHERE id = ' . $value['category_id'] . ';';
        }
        $result = $this->mysqli->multi_query($sql);
        if (!$result) die($this->mysqli->error);
        do {
            if ($result = $this->mysqli->store_result()) {
                while ($row = $result->fetch_row()) {
                    $c[] = $row[0];
                }
                $result->free();
            }
        } while ($this->mysqli->next_result());
        $d = array_merge($a, $c);
        return $d;
    }

Помогите пожалуйста спроектировать нормальное бд, связать между собой таблицы и составить нормальные SQL запросы.
  • Вопрос задан
  • 720 просмотров
Решения вопроса 1
werevolff
@werevolff
Если это не учебное задание, используйте, пожалуйста, ORM. Сейчас никто не работает с голым SQL на таких задачах. Потому что, во-первых, трудно разбираться с чужой реализацией шаблонных механизмов открытия/закрытия соединения, обращений к таблицам. Во-вторых, следует решать проблемы проектирования данных, а не реализации их записи в БД. Если задача учебная, то схема стандартная и мне нравится. Всё правильно нарисовано. Реализуется так же, как и любая ORM:

1. Создаём класс коннектора БД. Описываем в нём методы прямой записи в БД и удаления записей.
2. Создаём классы Comment и Category. Пусть у них будут методы get, update, delete, create. например get(id) получает из коннектора raw с данными и преобразует в ассоциативный массив. Там же реализуется получение полей связанной категории. Ну и метод delete у Comment запускает метод delete у Cаtegory, удаляя и Comment, и Category, и cat_id.
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
usdglander
@usdglander Куратор тега PHP
Yipee-ki-yay
Нормальная архитектура. В принципе так и делается. Чтобы не нарушить целочтность БД используйте внешние ключи с аттрибутом CASCADE на UPDATE и DELETE.

upd: Правда я бы переименовал таблицу cat_id в category_comment_assignment или просто category_comment. И выпилил бы из неё поле id. А ключём бы сделал связку category_id и comment_id. Ну это так... для порядка :)
Ответ написан
Ваш ответ на вопрос

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

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