从数据库中提取组

时间:2009-05-28 23:24:52

标签: php mysql

好吧,我有一个魔术卡网站,如果你点击主页上的设置,我试图从某个集合中拉出所有卡片。 www(点)magiccards(点)我在第一页的代码是:

    <?php

require("mysqlconnect.php");

$query = "SELECT COUNT(*) AS `Rows`, `set`,id FROM `magic_cards_copy`  GROUP BY `set` ORDER BY `set`";

$result = mysql_query($query) or die(mysql_error());

// Print out result
while($row = mysql_fetch_array($result)){
    $setlink = $row[1];
    $setlink = str_replace(" ", "", $setlink);
    $setlink = strtolower($setlink);
    $setlink = preg_replace("/[^a-z0-9]./","",$setlink);
    $setlink .= "-c-$row[2]";
    $setlink .= ".html";

    $navigation .= "< href=\"$setlink\">$row[1]</a> <small><i>($row[0])</i></small>";
}

require("template.php");

?>

,页面上的代码是:

    <?

require("mysqlconnect.php");

$cat=$_GET['cat'];

echo "Category: $cat<br>";

$query = "SELECT * FROM `magic_cards_copy` WHERE id = $cat ";

$result = mysql_query($query) or die(mysql_error());
$row = mysql_fetch_array($result);
echo "Set: $row[1]<br>";

?>

如何让代码从每组中提取卡片?任何帮助都会很棒。这对我来说更像是一个练习场。

5 个答案:

答案 0 :(得分:1)

我会创建一个包含两列的表。第一列是set-id(所有集合的唯一标识符),它将被编入索引以进行快速查找。第二列将是卡片的ID。您可以将此表用于包含所有唯一卡的表上的JOIN

BTW,清理所有输入

$cat=$_GET['cat'];

对SQL注入攻击持开放态度。您还应该将其强制转换为整数。

答案 1 :(得分:1)

阅读数据库规范化。您应该做的是有一个“集合”表,您可以在其中列出每个集合的ID号。然后在您的卡片数据库中,您没有设置名称,而是拥有与该集合对应的ID号。

示例设置表:

id    set
------------------
1     Set One Name
2     Set Two Name

示例卡表:

id    setid   card
-------------------------------------
1     1       Card One from First Set
2     1       Card Two from First Set
3     2       A card from Second Set

如果要列出集合,只需从集合表中选择所有内容即可。当您想要从一组中列出卡片时,您可以选择所有卡片,其中所设置的ID是您正在寻找的任何卡片。

答案 2 :(得分:0)

不确定你的要求,但首先要看的是这是一个练习网站是

$cat = mysql_real_escape_string($_GET['cat']);

至少可以防止SQL注入黑客攻击。你应该总是练习安全。 PHP.not on SQL Injection

答案 3 :(得分:0)

从问题中你不知道你要做什么 - 例如,提供的两个PHP脚本之间的关系是什么,你试图从所有集合中拉出卡片,还是从GIVEN集合中取出卡片?我会尝试回答两个问题:

set $ _GET ['cat']中的所有卡片:

<?php
$dbh = new PDO('mysql:dbname=testdb;host=127.0.0.1', 'dbuser', 'dbpass');
$stmt = $dbh->prepare('SELECT cardname from magic_cards_copy where set = :set');
$stmt->bindParam(':set', $_GET['cat'], PDO::PARAM_STR);
$stmt->execute();

while ($card = $stmt->fetch(PDO::FETCH_ASSOC)) {
  // display card here
}

所有套牌中的所有牌:

<?php
$dbh = new PDO('mysql:dbname=testdb;host=127.0.0.1', 'dbuser', 'dbpass');
$query = $dbh->query('SELECT cardname from magic_cards_copy');

while ($card = $query->fetch(PDO::FETCH_ASSOC)) {
  // display card here
}

请注意,我强烈建议您使用PDO,因为它可以保护您免受各种愚蠢行为。

答案 4 :(得分:0)

echo "Category: $cat<br>";

这受Cross-Site Scripting漏洞影响。由于您将其用作练习网站,因此您应该了解安全漏洞以及如何避免这些漏洞。首先阅读OWASP网站。

正如其他人所说,你也有一个SQL注入漏洞。

此外,这是您网站的输出:

Category: 143345
Set: Alliances
You have an error in your SQL syntax; check the manual that corresponds to 
your MySQL server version for the right syntax to use near ''magic_cards_copy' 
WHERE category = 'Alliances' LIMIT 40' at line 1

看起来你在表名周围使用了错误的分隔符。在表名周围使用反引号而不是单引号。

您需要创建另一个表,以记录每个组中每张卡的成员身份。这有时被称为“多对多表”或“交叉表”。这尤其正确,因为IIRC,一些魔术卡可以属于多组。

所以我就是这样做的:

CREATE TABLE CardSets (
  set_id INT PRIMARY KEY AUTO_INCREMENT,
  set_name VARCHAR(40)
);

CREATE TABLE Cards (
  card_id INT PRIMARY KEY AUTO_INCREMENT,
  card_name VARCHAR(40)
  -- other card attributes, color, flavor text, etc.
);

CREATE TABLE CardSetManifest (
  set_id INT NOT NULL,
  card_id INT NOT NULL,
  -- other attributes of card specific to a given set, e.g. rarity
  PRIMARY KEY (set_id, card_id),
  FOREIGN KEY (set_id) REFERENCES CardSets(set_id),
  FOREIGN KEY (card_id) REFERENCES Cards(card_id)
);

所以给定set_id你可以获得该套牌中的牌数:

SELECT set_id, COUNT(*) FROM CardSetManifest GROUP BY set_id;

鉴于set_id,你可以获得该套牌中的牌列表:

SELECT m.set_id, m.card_id, c.card_name
FROM CardSetManifest m JOIN Cards c USING (card_id);