Как загрузить данные в реляционную базу данных на php pdo
Есть 3 таблицы со связью 1 ко многим.
(Project)-> там находятся все проекты.
CREATE TABLE `project` (
`id` int(11) NOT NULL,
`name` varchar(255) NOT NULL,
`description` varchar(255) NOT NULL DEFAULT 'Нет описания',
`image` text,
`link` varchar(255) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
(Tags)-> там находятся теги.
CREATE TABLE `tags` (
`id` int(11) NOT NULL,
`tag_name` varchar(255) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
(P_tags)-> там находятся id проекта и id тега.
CREATE TABLE `p_tags` (
`project_id` int(11) NOT NULL,
`tag_id` int(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
--
-- Индексы таблицы `project`
--
ALTER TABLE `project`
ADD PRIMARY KEY (`id`);
--
-- Индексы таблицы `p_tags`
--
ALTER TABLE `p_tags`
ADD PRIMARY KEY (`project_id`,`tag_id`),
ADD KEY `tag_id` (`tag_id`);
--
-- Индексы таблицы `tags`
--
ALTER TABLE `tags`
ADD PRIMARY KEY (`id`);
--
-- AUTO_INCREMENT для сохранённых таблиц
--
--
-- AUTO_INCREMENT для таблицы `project`
--
ALTER TABLE `project`
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=75;
--
-- AUTO_INCREMENT для таблицы `tags`
--
ALTER TABLE `tags`
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=12;
--
-- Ограничения внешнего ключа сохраненных таблиц
--
--
-- Ограничения внешнего ключа таблицы `p_tags`
--
ALTER TABLE `p_tags`
ADD CONSTRAINT `p_tags_ibfk_1` FOREIGN KEY (`project_id`) REFERENCES `project` (`id`),
ADD CONSTRAINT `p_tags_ibfk_2` FOREIGN KEY (`tag_id`) REFERENCES `tags` (`id`);
COMMIT;
Нужно вставить в базу данных новый проект с определёнными тегами.` Для реализации я попробовал сделать такую схему
После этого, нужно сравнить id тега который мы вписали с id тега который находится в базе и уже на основе этих данный делать вставку в таблицу p_tags.
По отдельности циклы работают, как их соединить вместе я не знаю.
Если есть какой-то лёгкий способ это сделать, буду рад ему научится.
//Берём макс число. В $idcount[0][0] находится число, которое будет являться id проекта
$sth = $dbh->prepare("SELECT MAX(id) FROM project");
$sth->execute();
$idcount = $sth->fetchAll(PDO::FETCH_NUM);
// берём все теги (id,name)
$sth = $dbh->prepare('SELECT * FROM tags');
$sth->execute();
$tags = $sth->fetchAll(PDO::FETCH_ASSOC);
// Делаем цикл, узнаём что у нас 11 тегов
for ($i=0; $i < count($tags); $i++) {
echo $tags[$i]['id'].' | '.$tags[$i]['tag_name'].'<br>';
}
// Делаем цикл, узнаём что мы вписали 3 тега +
$proj_tags = $_GET["tags"];
$proj_tags = explode(",", $proj_tags);
for ($i=0; $i < count($proj_tags); $i++) {
$proj_tags[$i];
}
Ответы (2 шт):
Ну как-то так мб?
$stmt = $pdo->prepare("insert into project() values()");
$stmt->execute();
$pid = $pdo->lastInsertId(); // Получили id нового проекта
$proj_tags = explode(",", $_GET["tags"]);
$stmt = $pdo->prepare("insert into P_tags(pid, tid) select :pid, tag_id from tags where tag_name = :tname");
for($i=0; $i<count($proj_tags); $i++){
$stmt->bindParam(':pid', $pid);
$stmt->bindParam(':tname', $proj_tags[$i]);
$stmt->execute();
}
В данном коде три крупных ошибки, причем очень распространённых, так что будет полезно их рассмотреть.
- Первая и самая главная, "следующий id" никогда не получают заранее. Это приведёт к ошибкам и порче данных. id ВСЕГДА получают только после того как строка была добавлена в БД.
- Вторая - данные никогда не выгружают из базы целиком, если надо проверить только несколько строк. Надо составить запрос, который запрашивает только конкретные строки
- Третья - очень желательно добавить транзакцию, чтобы в БД е болтались ошметки данных, не привязанных ни к какому проекту.
Соответственно, и пишем код, который помогает избежать всех этих ошибок
$pdo->beginTransaction();
// сначала добавляем проект
$stmt = $pdo->prepare("insert into project(поля) values(маркеры)");
$stmt->execute([данные]);
$pid = $pdo->lastInsertId(); // Получили id нового проекта
//ищем id тегов
$proj_tags = explode(",", $_GET["tags"]);
$in = str_repeat('?,', count($proj_tags) - 1) . '?';
$sql = "SELECT id FROM tags WHERE tag_name IN ($in)";
$stm = $db->prepare($sql);
$stm->execute($proj_tags);
$tag_ids = $stm->fetchAll(PDO::FETCH_COLUMN);// получаем id тегов в массив
// Добавляем теги к проекту
$stmt = $pdo->prepare("insert into P_tags(pid, tid) VALUES (:pid, :tid)");
$stmt->bindParam(':pid', $pid);
$stmt->bindParam(':tid', $tid);
foreach($tag_ids as $tid){
$stmt->execute();
}
$pdo->commit();