Bowen
@Bowen
Японский бог

Как правильнее записывать данные в 2 связанных таблицах?

Добрый вечер.

Есть 2 таблицы: tags & post_tags.
Я знаю лишь 2 способа записывать теги в базу:

1
$tags = array_map('trim', explode(',', $_POST["tags"])); // A,B,C,
$tags_array = array();
$tags_sql = $db->super_query("SELECT id, title FROM `tags` WHERE title REGEXP '[[:<:]]" . implode('|', $tags) . "[[:>:]]'", true);

foreach($tags_sql as $tag){
$tags_array[$tag["title"]] = $tag["id"];
}

foreach($tags as $tag) {
	$tag = trim($tag);
	if (isset($tags_array[$tag])){
		$db->query("INSERT INTO `post_tags` (post_id, tag) VALUES ('$post_id', '{$tags_array[$tag]}') ");
	}
	else {
		$db->query("INSERT INTO `tags` (title) VALUES ('$tag') ");
		$id = $db->insert_id()-1;
		$id++;
		$db->query("INSERT INTO `post_tags` (post_id, tag) VALUES ('$post_id', '$id') ");
	}
}

2
$tags = array_map('trim', explode(',', $_POST["tags"])); // A,B,C,
$tags_array = array();
$tags_sql = $db->super_query("SELECT id, title FROM `tags` WHERE title REGEXP '[[:<:]]" . implode('|', $tags) . "[[:>:]]'", true);

foreach($tags_sql as $tag){
$tags_array[$tag["title"]] = $tag["id"];
}

$gg_tags = array();
foreach($tags as $tag) {
	$tag = trim($tag);
	if (isset($tags_array[$tag])){
		$gg_tags["exist"][] = "('$post_id', '{$tags_array[$tag]}')";
	}
	else {
		$gg_tags["new_title"][] = "('$tag')";
	}
}
if (!empty($gg_tags["exist"])){
	$db->query("INSERT INTO `_post_tags` (post_id, tag) VALUES " . implode(",", $gg_tags["exist"]) . " ");
} 
else {
	$db->query("INSERT INTO `tags` (title) VALUES " . implode(",", $gg_tags["new_title"]) . " ");
	$tags_sql = $db->super_query("SELECT id, title FROM `tags` WHERE title REGEXP '[[:<:]]" . implode('|', $tags) . "[[:>:]]'", true);

	foreach($tags_sql as $tag){
		$gg_tags["new_id"][] = "('$post_id', '{$tag["id"]}')";
	}
	$db->query("INSERT INTO `post_tags` (post_id, tag) VALUES " . implode(",", $gg_tags["new_id"]) . " ");
}

В итогде, в таблице должно получиться такое:
tags
id | title
1 | A
2 | B
3 | C
post_tags
post_id | tag
1 | 1
1 | 2
1 | 3

  1. вариант не хотелось бы использовать и за того что делаются много запросов, а по мимо тегов есть еще много таблиц для которых нужна такая же конструкция.
  2. вариант не уверен что правильный. Если все-же он правильный я не уверен что это самый оптимальный вариант даже если с ним получаются меньше запросов (по моим расчетам).


Я не знаю правильно ли я пытаюсь сделать или нет, эти 2 варианта единственные или есть и другие ?
Буду признателен за советы - помощь!
  • Вопрос задан
  • 390 просмотров
Пригласить эксперта
Ответы на вопрос 2
@mantyr
Пишу много Golang кода с удовольствием:)
Если я вас правильно понял то вы:
1. на входе имеете массив тегов $tags = array("tag1", "tag2", "tag3")
2. хотите сохранить новые в базу
3. хотите получить id всех тегов и присвоить их к некоторому посту

Попробуйте сделать так:
1. INSERT IGNORE INTO `tags` (title) для всех тегов, те что есть проигнорируются
2. SELECT id FROM `tags` WHERE `title` IN (...) для всех тегов что вам нужно
3. INSERT IGNORE INTO `post_tags` для всех id полученных из второго запроса

По крайней мере это уменьшит количество кода и упростит понимание.
+ добавьте слой кеширования для хранения тегов которые уже добавлены в базу (их ведь особо много явно не будет)
Ответ написан
Bowen
@Bowen Автор вопроса
Японский бог
Проблему решил таким образом:
$tags = $db->safesql( htmlspecialchars( strip_tags( stripslashes( trim( $_POST['tags'] ) ) ), ENT_COMPAT, $config['charset'] ) );
$tags = array_filter(array_map('trim', explode(',', $tags)));
$tags_box = array();

$all_post_tags = $db->super_query("SELECT tags.*, post_tags.* FROM " . PREFIX . "_tags tags LEFT JOIN " . PREFIX . "_post_tags post_tags ON (tags.id=post_tags.tag) WHERE post_tags.post_id=$post_id", true);

foreach($all_post_tags as $tag){

	$tags_box["all_post_tags"][] = $tag["title"];
	$tags_box["all"][$tag["title"]] = $tag["tag"];

	if (!in_array($tag["title"], $tags)){
		$tags_box["remove"][] = $tag["id"];
	}

	$tag["posi"]--;
	$tags_box["upd_posi"] = ($tags[$tag["posi"]] == $tag["title"]) ? 0 : 1;
	$tag["posi"]++;
	$tags_box["upd_posi_indexes"][$tag["title"]] = $tag["posi"];
	$tags_box["upd_posi_id"][] = $tag["id"];

}
$tag_id = 0;
foreach($tags as $tag_posi => $tag_title){

	$tag_posi++;
	$tag_id++;

	if (!in_array($tag_title, $tags_box["all_post_tags"])){

		$tags_box["insert_new_tags_title"][] = "('$tag_title')";
		$tags_box["insert_new_tags_id"][] = $tag_title;
		$tags_box["post_tags"][] = "('$post_id', '{$tag_id}', '$tag_posi')";
		
	}
	$tags_box["positions"][$tag_title] = $tag_posi;
	if (isset($tags_box["upd_posi_indexes"][$tag_title])){	
		$tags_box["upd_posi_new"][] = $tags_box["upd_posi_indexes"][$tag_title];
	}
}
if (!empty($tags_box["remove"])){
	$db->query("DELETE FROM " . PREFIX . "_post_tags WHERE post_id='$post_id' AND tag REGEXP '[[:<:]]".implode('|', $tags_box["remove"])."[[:>:]]'");
} 
if (!empty($tags_box["insert_new_tags_title"])){

	$finded_tags = $db->super_query("SELECT * FROM " . PREFIX . "_tags WHERE title REGEXP '[[:<:]]" . implode('|', $tags_box["insert_new_tags_id"]) . "[[:>:]]'", true);

	foreach($finded_tags as $tag){

		if (in_array($tag["title"], $tags) && $tags_box["all"][$tag["title"]] != $tag["title"]){
			$tags_box["finded"][] = "('$post_id', '{$tag["id"]}', '{$tags_box["positions"][$tag["title"]]}')";
		}

	}
	if (!empty($tags_box["finded"])){
		$db->query("INSERT INTO " . PREFIX . "_post_tags (post_id, tag, posi) VALUES " . implode(",", $tags_box["finded"]) . "");
	}
	else {		
		$db->query("INSERT INTO " . PREFIX . "_tags (title) VALUES " . implode(",", $tags_box["insert_new_tags_title"]) . "");
		$db->query("INSERT INTO " . PREFIX . "_post_tags (post_id, tag, posi) VALUES " . implode(",", $tags_box["post_tags"]) . " ");
	}
}
if ($tags_box["upd_posi"]){
	$db->query("UPDATE " . PREFIX . "_post_tags SET posi = ELT(field(tag, ".implode(',', $tags_box["upd_posi_id"])."), ".implode(",", $tags_box["upd_posi_new"]).") WHERE tag REGEXP '[[:<:]]".implode('|', $tags_box["upd_posi_id"])."[[:>:]]' AND post_id=$post_id");
}

Буду признателен если кто-нибудь сообщит какую-нибудь альтернативу!
Ответ написан
Комментировать
Ваш ответ на вопрос

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

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