Для начала query() меняем на это
public function query($sql, $params = []) {
$stmt = $this->db->prepare($sql);
$stmt->execute($params);
return $stmt;
}
это не принципиально для ответа на вопрос, но просто чтобы убрать бессмысленный код, который к тому же ухудшает функциональность.
А для получения ответа на вопрос надо научиться правильно соединяться с PDO.
Для этого там, где создается инстанс класса $this->db, пишем
вот такой код, в котором самой главной является строчка
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
После этого запускаем свой код, и PHP сам, человеческим голосом, сообщает нам, в чем проблема этого кода.
Таким образом мы сразу убиваем двух зайцев:
- во-первых, мы сразу перестаем нуждаться в услугах гадалок с тостера, которые начинают натужно выдумывать, по какой причине этот код может не работать
- во-вторых, получаем точное описание проблемы, а при наличии минимального умения пользоваться гуглом - еще и множество рецептов её решения.
На будущее. Сидеть тупить в код совершенно бессмысленно. проблема может быть где угодно - в другом коде, в настройках БД, в свойствах таблицы, в опечатках, которые в реальном коде есть, а в подредактированном варианте для тостера нету. И еще примерно в миллиарде причин. Все равно все перебрать нереально.
Поэтому никогда не надо уподобляться бабкам-гадалкам, которые пишут "а вы уверены" и "спробуй заячий помет, может поможет", а просто всегда настраивать пхп так, чтобы он сам сообщал,
в чем конкретно заключается ошибка.