Помимо стандартных способов (задать всем колонкам алиасы или использовать fetch_num), в ПДО есть забавный режим,
PDO::FETCH_NAMED, который все поля с одинаковыми названиями запихивает во вложенный массив.
Не знаю, насколько это удобно, но буквально на вопрос отвечает :D
И да, вот этот вот ужас с джейсон енкоде ой нет декоде надо стереть, пока никто не видел.
Плюс вообще убрать фетч из функции, а вместо этого возвращать стейтмент:
public function query($q, $params = [])
{
$statement = $this->pdo->prepare($q);
$statement -> execute($params);
return $statement;
}
И тогда ты сможешь использовать показанный выше режим
// обычные данные
$data = $db->query($sql, $params)->fetchAll();
// данные с дублями
$data = $db->query($sql, $params)->fetchAll(PDO::FETCH_NAMED);
А так же все 100500 остальных режимов, поддерживаемых ПДО