错误:SQLSTATE[HY000] [2002] 没有此文件或目录。

4

我知道这种类型的问题可能已经被问了好几次,但它们都与Laravel有关,在我的情况下,这是没有框架的纯PHP。

我有一个表单,用于收集用户的表单数据并将其保存到数据库中,但我一直在收到有关MYSQL的错误:Error: SQLSTATE[HY000] [2002] No such file or directory。这是我的数据库配置文件和包含它的文件:

// Database config 
<?php

$host = 'localhost';
$user = 'admin';
$password = '123456';
$db_name = 'nairobi';

$dsn = 'mysql:host='.$host.';dbname='.$db_name;
$options = [ 
  PDO::ATTR_PERSISTENT => true,
  PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
];

    // Create a new PDO instance 
    try {
      $dbh = new PDO($dsn, $user, $password);
    } catch (PDOException $e) {
      print "Error: " . $e->getMessage() . "</br>";
      die();
    }

?>

<?php 
require "./library/Database.php";

if (isset($_POST['submit'])) {

  $first_name = $_POST['first_name'];
  $last_name = $_POST['last_name'];
  $email = $_POST['email'];

  $sql = 'INSERT INTO TABLE members(first_name, last_name, email) 
  VALUES (:first_name, :last_name, :email)';
  $stmt = $dbh->prepare($sql);
  $stmt_value = [
    ':first_name' => $first_name, 
    ':last_name' => $last_name, 
    ':email'=>$email
  ];
  $stmt->execute($stmt_value);
}


?>

是的,我知道处理表单的脚本不安全。

此外,当我访问该页面时,出现以下错误

Fatal error: Uncaught PDOException: SQLSTATE[HY000] [2002] No such file or directory in /var/www/html/library/Database.php:19 Stack trace: #0 /var/www/html/index.php(2): require() #1 {main} thrown in /var/www/html/library/Database.php on line 19

如果需要的话,这就是我所采用的SQL语句。
CREATE TABLE IF NOT EXISTS members(
  member_id INT AUTO_INCREMENT NOT NULL PRIMARY KEY,
  first_name VARCHAR(255) NOT NULL,
  last_name VARCHAR(255) NOT NULL,
  email VARCHAR(255) NOT NULL UNIQUE,
  reference_code INT NOT NULL
);

这个整个项目也在一个Docker容器中,这里是 docker-compose.yml 文件。
version: '3.7'

services:
  php:
    container_name: nairobi_php
    build:
      context: ./
    volumes:
      - './src:/var/www/html'
    depends_on:
      - mysql
    ports:
      - 80:80

  mysql:
    container_name: nairobi_mysql
    image: mysql:8.0
    environment:
      MYSQL_ROOT_PASSWORD: CUeHpADRmZCtnTFGctxp
      MYSQL_DATABASE: nairobi
      MYSQL_USER: admin
      MYSQL_PASSWORD: 123456
    restart: always
    command: --default-authentication-plugin=mysql_native_password
    ports:
      - 3306:3306

  adminer:
    image: adminer
    restart: always
    ports:
      - 8080:8080


你确定 "./library/Database.php" 存在于那个位置吗? - nbk
你是否用答案中的代码替换了database.php中的代码?你是否确认你的端口号正确,就像我在答案中提到的那样?你确定database.php中没有其他内容吗?我的代码中第19行是一个}。 - user1805543
这是我这边的源代码长这样:链接 - Tijani
请查看我更新的答案!能否截个屏并上传到其他地方呢?我在imgur.com上没有看到任何东西。 - user1805543
我用你的表格替换了我的,但仍然出现相同的错误,我甚至尝试重新构建我的Docker容器,但问题仍然存在。 - Tijani
显示剩余3条评论
2个回答

3

我终于解决了这个问题,感谢@Dlk的帮助。

问题的原因是在database.php文件中,我引用mysql主机时使用的是localhost而不是docker-compose.yml文件中MYSQL服务的名称。因此,database.php文件应该像这样:

<?php

$host = 'nairobi_mysql'; // Must be the service name of the database in `docker-compose.yml`
$db_name = 'nairobi';
$user = 'admin';
$pass = '123456';
$charset = 'utf8mb4'; // Always set charset for database
$port = '3306'; 

$dsn = "mysql:host=$host;dbname=$db_name;port=$port;charset=$charset";
$options = [
    PDO::ATTR_ERRMODE            => PDO::ERRMODE_EXCEPTION,
    PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
    PDO::ATTR_EMULATE_PREPARES   => false,
];
try {
     $pdo = new PDO($dsn, $user, $pass, $options);
} catch (\PDOException $e) {
     throw new \PDOException($e->getMessage(), (int)$e->getCode());
}

?>

这与我的docker-compose.yml文件相关联。

version: '3.7'

services:
  php:
    container_name: nairobi_php
    build:
      context: ./
    volumes:
      - './src:/var/www/html'
    depends_on:
      - mysql
    ports:
      - 80:80

  mysql:
    container_name: nairobi_mysql
    image: mysql:8.0
    environment:
      MYSQL_ROOT_PASSWORD: CUeHpADRmZCtnTFGctxp
      MYSQL_DATABASE: nairobi
      MYSQL_USER: admin
      MYSQL_PASSWORD: 123456
    restart: always
    command: --default-authentication-plugin=mysql_native_password
    ports:
      - 3306:3306

  adminer:
    image: adminer
    restart: always
    ports:
      - 8080:8080


很好,很高兴你解决了!我在评论中提到过,你可能没有看到你能把localhost改成127.0.0.1或者你的IP地址吗? IP -> 你的服务名称 - user1805543

1
首先按照以下方式更改您的连接:使用以下代码替换Database.php中的代码,并阅读代码中的注释。
$host = 'localhost';
$db   = 'nairobi';
$user = 'admin';
$pass = '123456';
$charset = 'utf8mb4'; // Always set charset for database
$port = '3308'; //Your port can be 3306 or 3307

$dsn = "mysql:host=$host;dbname=$db;port=$port;charset=$charset";
$options = [
    PDO::ATTR_ERRMODE            => PDO::ERRMODE_EXCEPTION,
    PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
    PDO::ATTR_EMULATE_PREPARES   => false,
];
try {
     $dbh = new PDO($dsn, $user, $pass, $options);
} catch (\PDOException $e) {
     throw new \PDOException($e->getMessage(), (int)$e->getCode());
}

现在是您的代码!您正在使用准备语句,这使得您的代码足够安全。 检查Database.php文件的URL是否正确,并将您的更改为此。
require_once "./library/Database.php";
    if (isset($_POST['submit'])) {

      $first_name = $_POST['first_name'];
      $last_name = $_POST['last_name'];
      $email = $_POST['email'];
      $reference_code = $_POST['reference_code'];
    //You have a `TABLE` name call members so you dont need `TABLE` its causing problem
    //Your query should look like this
      $sql = 'INSERT INTO members (first_name, last_name, email, reference_code) VALUES (:first_name, :last_name, :email, :reference_code)';
      $stmt = $dbh->prepare($sql);
      $stmt->execute([$first_name, $last_name, $email, $reference_code]);
    //I removed array here which you dont need, you can directly add fields in execute.
      $stmt->closeCursor();
    //Use `closeCursor()` to free your connection instead unset or close.
    }

最终 确保您已创建了数据库。 确保您在数据库中创建了名为“members”的表。

如果您已完成以上所有步骤,则代码将正常工作,无需任何问题。

HTML表单应如下所示,如果您想上传图像,则需要在表单中添加多重加密。

<form action="yourpage.php" method="post">
  <div class="container">first_name</b></label>
    <input type="text" placeholder="Enter first_name" name="first_name" required>

    <label for="last_name"><b>last_name</b></label>
    <input type="text" placeholder="Enter last_name" name="last_name" required>

    <label for="email"><b>email</b></label>
    <input type="email" placeholder="Enter email" name="email" required>

    <label for="reference_code"><b>reference_code</b></label>
    <input type="text" placeholder="Enter reference_code" name="reference_code" required>

    <button type="submit">Login</button>
  </div>
</form>

数据表格应该长这样:

CREATE TABLE IF NOT EXISTS `members` (
  `member_id` int(8) NOT NULL AUTO_INCREMENT,
  `first_name` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
  `last_name` varchar(64) COLLATE utf8mb4_unicode_ci NOT NULL,
  `email` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
  `reference_code` int(11) NOT NULL,
  PRIMARY KEY (`member_id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

谢谢,伙计。我非常感激你的帮助,但现在我又遇到了一个问题。这是我得到的错误信息这里。如果有帮助的话,这是在一个 Docker 容器内部。 - Tijani
请检查您添加的URL是否为空,编辑您的问题并在底部添加错误。同时,请检查“./library/Database.php”路径是否正确。 - user1805543
你可以把localhost改成127.0.0.1或者你的IP地址(如果有的话)。参考连接docker https://nickjanetakis.com/blog/docker-tip-35-connect-to-a-database-running-on-your-docker-host。 - user1805543

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接