【问题标题】:PHP 7.4 typeError on database operationsPHP 7.4 数据库操作上的 typeError
【发布时间】:2020-07-21 23:52:21
【问题描述】:

我想将数据库中的一些数据编码为 JSON。

这个类打开一个到我的数据库的连接。

<?php

namespace Database;

use PDO;
use PDOException;

class Connection
{
    private string $server = "mysql:host=localhost;dbname=wbs";
    private string $user = "root";
    private string $pass = "";
    private array $options = array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,);
    protected PDO $con;

    public function openConnection()
    {
        try {
            $this->con = new PDO($this->server, $this->user, $this->pass, $this->options);
        } catch (PDOException $e) {
            echo "Something went wrong with the database connection: " . $e->getMessage();
        }
        return $this->con;
    }

    public function closeConnection()
    {
        unset($this->con);
    }
}

这个类查询数据库中的任何项目

<?php

namespace Task;

use PDO;
use PDOStatement;
use Database\Connection;

class Task
{
    private Connection $conn;
    private PDO $pdo;
    private PDOStatement $PDOStatement;


    public function __construct()
    {
       $this->conn = new Connection();
    }
    public function SqlQuery(): PDOStatement
    {
       $this->pdo = $this->conn->openConnection();

       $this->PDOStatement = $this->pdo->prepare("SELECT * FROM `tasks` 
       LEFT JOIN `projects` ON 'projects.projectid' = 'tasks.projectid' 
       LEFT JOIN `moscow` ON 'moscow.moscowid' = 'tasks.moscowid'");

       $this->PDOStatement->execute();

       return $this->PDOStatement;
    }
}

<?php

namespace Read;

use PDO;
use PDOStatement;
use Task\Task;


require_once("../config/Connection.php");
require_once("../object/Task.php");

class Read
{
    private PDOStatement $PDOStatement;
    private Task $task;
    private int $items;
    private array $task_array;
    private array $task_item;
    private array $row_count;
    private array $row_items;

    public function __construct()
    {
        $this->task = new Task();
    }

    public function EncodeToJson(): string
    {
        $this->PDOStatement = $this->task->SqlQuery();
        $this->items = $this->PDOStatement->rowCount();

        if ($this->items > 0) {

            $this->task_array = array();
            $this->task_array["records"] = array();

            while ( $this->row_count = $this->PDOStatement->fetch(PDO::FETCH_ASSOC)) {
                $this->row_items = $this->row_count;
                extract($this->row_items);

                $this->task_item = array(
                    "id" => $id,
                    "task_name" => $task_name,
                    "task_owner" => $task_owner,
                    "developer" => $developer,
                );

                array_push($this->task_array["records"], $this->task_item);
            }

            http_response_code(200);

            return json_encode($this->task_array);
        }
    }
}

$Read = new Read();

echo $Read->EncodeToJson();

这个类遍历所有获取的数据,将其存储在一个数组中并将其编码为 JSON。 错误发生在第 41 行,即while 循环。错误返回这个

致命错误:未捕获的 TypeError:类型化属性 Read\Read::$row_count 必须是数组,在 C:\laragon\www\WBS\php\api\task\Read.php 中使用的 bool 在第 41 行。

检查fetch 方法的文档

此函数成功时的返回值取决于 fetch 类型。在所有情况下,失败都会返回 FALSE。

为什么会发生 typeError 是有道理的,我只是对我应该如何设置我的字段 row_count 感到困惑而不是布尔值。

我只是对 PHP 如何使用这些类型化的属性以及如何在数据库操作中正确使用它们感到非常困惑。

【问题讨论】:

  • 没有任何类循环数据库结果
  • 您需要检查 ->fetch() 返回的值,然后再将其分配给 row_count。然后你可以先确定它不是假的。要么,要么不要强输入你的 $row_count 变量。
  • 不强类型 $row_count 变量可以解决问题,但他们无法为结果集实现类型化属性吗?
  • 如果你问我,无论如何你在那儿做的事情都是相当虚假的。 while ( $this-&gt;row_count = $this-&gt;PDOStatement-&gt;fetch(PDO::FETCH_ASSOC)) – 为什么将获取的 record 分配给一个名为 row_count 的属性开始?意义不大,尤其是考虑到您在接下来的循环中如何处理$this-&gt;row_items = $this-&gt;row_count;。 […]
  • […] 为什么在这个地方开始使用一个类属性?如果这只是一个“帮助变量”,用于循环结果集并处理循环内的数据,并且以后不再需要 - 那么这应该就是一个本地 变量,而不是类属性。

标签: php pdo php-7


【解决方案1】:

您不需要在方法中使用属性。您应该使用局部变量,但即使它们也不是必需的。请不惜一切代价避免extract()。这是非常混乱的解决方案。

您已经将原本应该是一行代码的内容变成了包含许多不必要内容的完整方法。这样做就足够了:

public function EncodeToJson(): string
{
    return json_encode(['records' => $this->task->SqlQuery()->fetchAll(PDO::FETCH_ASSOC)]);
}

但是,整个课程变得毫无意义。您没有以 OOP 方式使用它。您创建的类只是代码中的噪音。您可以删除Read 类并直接调用Task 上的方法。

echo json_encode(['records' => (new Task())->SqlQuery()->fetchAll(PDO::FETCH_ASSOC)]);

您的Task 班级也有问题。您应该遵循依赖注入设计并将连接作为参数传递给__construct

<?php

namespace Task;

use PDO;
use PDOStatement;

class Task {
    private PDO $pdo;

    public function __construct(PDO $conn) {
        $this->conn = $conn;
    }

    public function read(): PDOStatement {
        $PDOStatement = $this->pdo->prepare("SELECT * FROM `tasks` 
            LEFT JOIN `projects` ON 'projects.projectid' = 'tasks.projectid' 
            LEFT JOIN `moscow` ON 'moscow.moscowid' = 'tasks.moscowid'");

        $PDOStatement->execute();

        return $PDOStatement;
    }
}

然后当你创建一个对象时,将连接传入。

$pdo = $connection->openConnection();
$task = new Task($pdo);

在不相关的注释上:永远不要显示错误消息!。如果您只想回显错误,请不要捕获异常。不理会例外。如果要实现错误处理程序,它应该记录到文件中。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-10-18
    • 2012-04-17
    • 2020-06-02
    • 1970-01-01
    • 1970-01-01
    • 2020-04-26
    • 2020-03-14
    • 1970-01-01
    相关资源
    最近更新 更多