Вопрос: Как грамотно реализовать пагинацию через класс?

Лучший ответ:
Еще раз:  Тут нет никакого ооп, у вас получается какой-то процедурный код, засунутый внутрь класса. Это к ооп не имеет никакого отношения. Не пытайтесь сделать деревянную печку, ничего хорошего не получится.
У вас:
Код реализует (такой себе) пэйджинг для одного конкретного запроса (нахрена такой пейджинг засовывать в класс?)
Код ничего не инкапсулирует, тупо выполняется как функция. По сути если мы уберем class Paginate extends Connection{ то ничего не поменяется. 
Внутри методов используются глобальные переменные (GET), что само по себе уже лютый говнокод.
Много слов про солид и прочие вещи из ооп не пишу,  в виду полного их отсутствия в коде, да и смысл?

По этому решения для вашего случая в контексте ооп просто нет, так как:
Пэйджинг работает с моделями на основе ОРМ, в пэйджинг в качестве аргумента передается модель, и далее уже пэйджинг работает с моделью, используя ее методы работы с хранилищем, а не просто тупо фигачит запросы. У вас моделей просто нет.
Модели подразумевают конкретный интерфейс, который позволяет работать с пэйджингом адекватно. Ну и моделей нет ))
Точкой взаимодействия между моделью и пэйджингом будет контроллер, про который тут вообще у вас никто не в курсе.
Вывод (view) никогда не пересекается с кодом логики, в него просто передаются готовые данные, после чего они вставляются в нужные точки шаблона.

Худший ответ:
Попытка не пытка.

1. Пагинация (постраничная навигация) НЕ НАСЛЕДУЕТ соединение, а ИСПОЛЬЗУЕТ его. наследовать = быть КОПИЕЙ С ИЗМЕНЕНИЯМИ, использовать = требовать в коде (ЗАВИСЕТЬ). В ООП можно писать "extends" (наследовать), а можно пробрасывать через конструктор (зависимости). То что вы сделали - это использование "наследования" для "зависимости", оно к вам завтра вернется, когда что-то захотите ещё сюда всунуть, как будете второе наследование делать?

2. Размышляйте так. Чтобы сделать навигацию вам нужно:
1 - имя таблицы
2 - число страниц
3 - отступ, чтобы переходить на вторую страницу
4 - (необязательно) SELECT COUNT результатов, чтобы показать сколько всего страниц
5 - фильтр, чтобы скрыть ненужные результаты (самый прикол в том, что фильтр универсальный сделать не выйдет, т.к. придется написать SQL заново, он весь про фильтры)
6 - сортировка, чтобы выдать в нужном порядке (бывает несколько-ступенчатая сортировка "сначала-по-подгруппе-потом-по-цене", но её никто никогда не делает, лень правит мир)

Вы здесь крышей упадете писать одну функцию, которая делает это всё.

К человекам здесь пришло понимание, что нужно передавать "недоделанный" запрос из функции в функцию, дописывая в него кусочек. Для удобства запрос оборачивают в объект, которые называют Query.

Если вы пытаетесь сделать на чистом SQL запросы - вам придется очень многое изучить. Поэтому как решение я предлагаю такую последовательность действий:
1 - Изучаете, что такое composer, ставите в ваш проект какой-нибудь пакет (пока любой, например, symfony/var-dumper), добиваетесь что работает функция dd() (этот пакет её содержит, вам не нужно функцию создавать) в вашем коде. На самом деле там один консольный вызов и одна строка в коде, там нет "методики на 40 действий"
2 - ставите пакет illuminate/database
3 - гуглите статью "eloquent without laravel"
4 - создаете модельку под вашу таблицу
5 - на модельке вызываете метод ->paginate(), где его для вас заботливо написали
6 - и только здесь начинаете изучать детали, которые хотели выучить сразу, чтобы сделать не просто пагинацию, а фильтруемую и сортируемую пагинацию (если оно надо). Скорее всего у вас появятся классы FilterBuilder, SorterBuilder, PaginationBuilder и Pagination, в которой будет метод вроде ->paginate($query, $paginationBuilder)
7 - что такое паттерн "строитель" (Builder) читать на https://refactoring.guru

У вас долгий путь впереди. Если вы делаете задачу впервые, возможно, вы ушатаете неделю или полторы.

3. Кое-что о запросах. Пагинация с OFFSET имеет смысл только в очень простых запросах. На практике запросы имеют UNION, JOIN и "subquery", чтобы собирать данные, и кое-где работать не будет. Рекомендуется либо сразу оттолкнуться от (id > ?) вместо OFFSET (а заодно охренеть от того, что "айди больше" + "сортировка" опять не пашут, то есть вам по сути надо сделать "rowNum > ?", но почти все СУБД не дают такого параметра и придется КЕШИРОВАТЬ сделав запрос первый раз тяжелый, а следующий раз выбирать номер результата в кеше), либо делать велосипед с выгрузкой результатов в файл, например, и потом с помощью условного $splFileObject->fseek() выбирать прямым указанием номер первой строки и число результатов после (сложнее, веселая задачка потренироваться, на практике - создает больше гемора, чем пользы)