я и написал статический класс + нэймспэйс ~ модуль
А в чем проблема? Пишешь 6 функций, get, post, put, delete, any, dispatch в своем неймспейсе, там же определяешь глобальный массив роутов, в функциях хендлеры роутов кладешь в этот массив. А в диспатче берешь реквест_ури и ищешь по регулярке совпадения среди маршрутов. Нашел маршрут и совпал метод -- поздравляю, можно исполнять хендлер, а если нет - кидаешь исключение с надеждой, что кто-то выше его поймает(ну или на клиент рендерить сразу)