【问题标题】:PHP and MySQL Select a Single Value [duplicate]PHP和MySQL选择一个值[重复]
【发布时间】:2014-01-19 14:44:22
【问题描述】:

我想知道如何从我的 MySQL 表中选择一个值。该表包括 username 和 id 列等(id 是自动递增的,username 是唯一的)。给定用户名,我想设置一个会话变量$_SESSION['myid'] 等于与给定用户名对应的id 列中的值。这是我已经尝试过的代码:

session_start();
$name = $_GET["username"];
$sql = "SELECT 'id' FROM Users WHERE username='$name'";
$result = mysql_query($sql);
$value = mysql_fetch_object($result);
$_SESSION['myid'] = $value;

到目前为止,我得到了:

可捕获的致命错误:stdClass 类的对象无法转换为字符串。

将$value 转换为字符串类型并不能解决问题。

【问题讨论】:

  • 只是提醒... mysql 扩展已弃用,将来将被删除:改用 mysqli 或 PDO
  • 这存在严重的安全问题。正如@WesC 指出的那样,不要使用 mysql_* 函数。此外,您很容易受到 SQL 注入攻击。

标签: php mysql sql database user-accounts


【解决方案1】:
  1. 不要在查询中的字段名或表名中使用引号。

  2. 获取对象后,您需要通过属性/属性名称访问对象属性/属性(在您的情况下为 id)。

注意:请使用 mysqli_* 或 PDO,因为 mysql_* 已弃用。这里使用的是 mysqli:

session_start();
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$link = new mysqli('localhost', 'username', 'password', 'db_name');
$link->set_charset('utf8mb4'); // always set the charset
$name = $_GET["username"];
$stmt = $link->prepare("SELECT id FROM Users WHERE username=? limit 1");
$stmt->bind_param('s', $name);
$stmt->execute();
$result = $stmt->get_result();
$value = $result->fetch_object();
$_SESSION['myid'] = $value->id;

额外提示:在这种情况下使用限制 1,它将节省执行时间:)

【讨论】:

  • 这可以消除错误消息,但在屏幕上打印 $_SESSION['myid'] 现在会显示“id”而不是特定的 int。
  • @user3055501 :试试上面的代码。我已更改 $sql 行并提供您的反馈。它应该工作:)
  • ...并且永远不要在查询中使用原始用户输入。
【解决方案2】:

mysql_* 函数已弃用且不安全。 您问题中的代码容易受到injection attacks 的攻击。强烈建议您改用 PDO 扩展,如下所示:

session_start();

$query = "SELECT 'id' FROM Users WHERE username = :name LIMIT 1";
$statement = $PDO->prepare($query);
$params = array(
    'name' => $_GET["username"]
);
$statement->execute($params);
$user_data = $statement->fetch();

$_SESSION['myid'] = $user_data['id'];

$PDO 是您的 PDO 对象变量。有关 PHP 和 PDO 的更多信息,请参阅https://www.php.net/pdo_mysql。

如需额外帮助:

下面是如何使用 PDO 连接到数据库的快速入门:

$database_username = "YOUR_USERNAME";
$database_password = "YOUR_PASSWORD";
$database_info = "mysql:host=localhost;dbname=YOUR_DATABASE_NAME";
try
{
    $PDO = new PDO($database_info, $database_username, $database_password);
}
catch(PDOException $e)
{
    // Handle error here
}

【讨论】:

  • 感谢韦斯的回答。当我有更多时间时,我一定会研究 PDO。
  • 从个人经验来看,我建议你早点而不是晚点。您使用mysql_* 函数编写的代码越多,您就越会发现需要完全重写。此外,它实际上非常方便,并且在其他领域更有条理。
  • 如果其他人看到这个并惊慌失措,您可以改为使用 mysqli 更好。注意mysql末尾的i
  • 就像@AndersM 说的 - 我还发现 mysqli 比 PDO 更易于使用/阅读,用于简单查询。但是请注意,Wes 提出了一个非常重要的观点:如果您的查询的任何部分包含不是 100% 受您控制的文本,则使用准备好的语句。在mysqli中,即prepare,manual discussion of prepared statements
【解决方案3】:

您可以使用mysqli_fetch_field 方法来做到这一点。

session_start();
$link = mysqli_connect("localhost", "my_user", "my_password", "world");
$name = $_GET["username"];
$sql = "SELECT 'id' FROM Users WHERE username='$name' limit 1";
$result = mysqli_query($link, $sql);
if ($result !== false) {
    $value = mysqli_fetch_field($result);
    $_SESSION['myid'] = $value;
}

注意:您也可以使用mysql_fetch_field() 方法来做到这一点,但它将在 php v5.5 中被弃用

【讨论】:

  • mysqli_fetch_field "返回一个包含字段定义信息的对象,如果没有可用的字段信息,则返回 FALSE。所以这不会像答案所建议的那样工作。 -1 因为这个。
  • @GusstavvGil:在调用mysqli_fetch_field 之前,我已通过确保存在有效的$result 来更正代码。我还添加了缺少的 $link 参数。
  • @ToolmakerSteve mysqli_fetch_field 不返回值。它返回字段定义,如名称、表、标志。 -1 因为这个...php.net/manual/en/mysqli-result.fetch-field.php
  • 不应使用此答案,因为它不安全/不稳定。
  • 警告: 这个答案是完全错误的。 mysqli_fetch_field() 返回有关表列的元数据,而不是值本身。
【解决方案4】:

试试这个

$value = mysql_result($result, 0);

【讨论】:

  • 警告: mysql_* 扩展自 PHP 5.5.0 起已弃用,自 PHP 7.0.0 起已被删除。相反,应该使用mysqli 或PDO_MySQL 扩展名。在选择 MySQL API 时,另请参阅 MySQL API Overview 以获得更多帮助。
  • “试试这个”答案在 Stackoverflow 上的价值很低,因为它们在教育/授权 OP 和成千上万的未来研究人员方面做得很差。即使您觉得您的解决方案是超基本的/不言自明的,所有答案都应该包含某种形式的简单英语支持文本。告诉研究人员它是如何工作的,它为什么起作用,它与其他答案有何不同,为什么你认为这是一个好主意,提供文档链接等。当你回答的目的是帮助人们和为他人树立良好答案的榜样。
【解决方案5】:

mysql_* 扩展已于 2013 年弃用,并于 2018 年从 PHP 中完全删除。您有两种选择 PDO 或 MySQLi。

PDO

更简单的选择是 PDO,它有一个简洁的辅助函数 fetchColumn():

$stmt = $pdo->prepare("SELECT id FROM Users WHERE username=?");
$stmt->execute([ $_GET["username"] ]);
$value = $stmt->fetchColumn();

Proper PDO tutorial

MySQLi

你可以用 MySQLi 做同样的事情,但它更复杂:

$stmt = $mysqliConn->prepare('SELECT id FROM Users WHERE username=?');
$stmt->bind_param("s", $_GET["username"]);
$stmt->execute();
$data = $stmt->get_result()->fetch_assoc();
$value = $data ? $data['id'] : null;

fetch_assoc() 如果数据库没有返回任何行,则可能返回 NULL,这就是为什么我使用三元检查是否有任何数据返回。

从 PHP 8.1 开始你也可以使用fetch_column()

$stmt->execute();
$value = $stmt->get_result()->fetch_column();

【讨论】:

【解决方案6】:

当您使用mysql_fetch_object 时,您将获得一个对象(属于stdClass 类),其中包含该行的所有字段。

使用mysql_fetch_field 而不是mysql_fetch_object,这将为您提供结果集的第一个字段(在您的情况下为id)。文档是here

【讨论】:

  • 警告: 这个答案是完全错误的。 mysql_fetch_field() 返回有关表列的元数据,而不是值本身。
【解决方案7】:

试试这个

session_start();
$name = $_GET["username"];
$sql = "SELECT 'id' FROM Users WHERE username='$name' LIMIT 1 ";
$result = mysql_query($sql) or die(mysql_error());
if($row = mysql_fetch_assoc($result))
{
      $_SESSION['myid'] = $row['id'];
}

【讨论】:

  • 警告: mysql_* 扩展自 PHP 5.5.0 起已弃用,自 PHP 7.0.0 起已被删除。相反,应该使用mysqli 或PDO_MySQL 扩展名。在选择 MySQL API 时,另请参阅 MySQL API Overview 以获得更多帮助。
【解决方案8】:

很明显,只有一个id对应一个username,因为username是唯一的。

但实际问题在于查询本身-

$sql = "SELECT 'id' FROM Users WHERE username='$name'";

O/P

+----+
| id |
+----+
| id |
+----+

即'id' 实际上被视为字符串而不是id 属性。

正确的语法:

$sql = "SELECT `id` FROM Users WHERE username='$name'";

即使用重音(`)代替单引号(')。

或

$sql = "SELECT id FROM Users WHERE username='$name'";

完整代码

session_start();
$name = $_GET["username"];
$sql = "SELECT `id` FROM Users WHERE username='$name'";
$result = mysql_query($sql);
$row=mysql_fetch_array($result)
$value = $row[0];
$_SESSION['myid'] = $value;

【讨论】:

  • 需要一个 ;在第五行。
  • 警告: mysql_* 扩展自 PHP 5.5.0 起已弃用,自 PHP 7.0.0 起已被删除。相反,应该使用mysqli 或PDO_MySQL 扩展名。在选择 MySQL API 时,另请参阅 MySQL API Overview 以获得更多帮助。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-04-09
  • 2016-02-18
  • 1970-01-01
  • 1970-01-01
  • 2014-07-22
  • 2013-04-25
相关资源
最近更新 更多