PHP 7.4 typeError при операциях с базой данных - PullRequest
0 голосов
/ 09 апреля 2020

Я хотел бы закодировать некоторые данные из базы данных в 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 l oop. ошибка возвращает это

Неустранимая ошибка: Uncaught TypeError: Типизированное свойство Read \ Read :: $ row_count должно быть массивом, bool используется в C: \ laragon \ www\WBS \ php \ api \ task \ Read. php в строке 41.

Проверка документов по методу fetch

Возвращаемое значение этой функции в случае успеха зависит от извлечения тип. Во всех случаях FALSE возвращается при ошибке.

Было бы понятно, почему произошла ошибка typeError, я просто запутался относительно того, что я должен сделать своим полем row_count Я пытался привести его к массив безуспешен, и можно было бы предположить, что PDO::FETCH_ASSOC вернет массив вместо логического значения.

Я просто очень смущен тем, как PHP использует эти типизированные свойства и как правильно использовать их с операциями с базой данных .

1 Ответ

2 голосов
/ 09 апреля 2020

Вам не нужно использовать свойства в вашем методе. Вы должны использовать локальные переменные, но даже они не нужны. Пожалуйста, избегайте 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);

На несвязанной ноте: Никогда не отображать сообщения об ошибках! . Не перехватывайте исключения, если единственное, что вы хотите сделать, это повторить ошибку. Оставьте исключения в покое. Если вы хотите реализовать обработчик ошибок, он должен вести запись в файл.

...