Тебе нравится концепция ларавельных фасадов, которые публичные методы статически вызывают.
В самой ларе по инструкции можешь сделать свой фасад и привязать к нему класс, который будет делать всю работу. Это простейший способ. Под капотом идея в том, чтобы создать твой класс в начале программы, положить его в контейнер, и всегда когда ты статически вызываешь методы - класс созданный дергается из контейнера, где он лежит, и на нем вызывается. Надеюсь ты понимаешь, что не всегда можно использовать один и тот же экземпляр во всей программе. Например для тех же моделей, где важен "текущий", а не "всегда один", как в синглтоне.
Способ ООПшный - это сделать второй класс куда скопировать все методы, но тело сделать так, чтобы в каждом методе вызывался "сиглтон" или брался класс из контейнера. Или так как Сергей delphinpro описал, тело не копируешь, но делаешь магию, в итоге один класс у тебя с пабликами, а второй вызывает через статики, но класса все равно в итоге два. В ларе тоже. Фасад у них обертка для исполнителя, а не сам исполнитель.
Причина (но не проблема) этого - отсутствие в пхп понятия "перегрузка метода" которое позволяет в одном классе написать один и тот же метод 3-4 раза указав разный набор параметров и по числу переданных параметров будет выбрано что это есть. Это штука конечно модная, но хорошо, что её нет. Когда она есть код будет более странным и непредсказуемым при беглом чтении. В пхп решили это не делать. Вернее как сказать - понятие ввели, как написал Сергей delphinpro, но реализация идет через 4 разных метода, которые ты потом с помощью if() вручную определяешь.
У меня так в библиотеке сделаны модули, я специально писал генератор фасадов, потому что у меня 20 классов, во всех методов около 10, и надо чтоб хочешь - фасадом как в ларе, хочешь иньекцией зависимости как предполагает паттерн инжектор, хочешь трейтом можно было подключать когда лень и побыстрому, хочешь - aware интерфейсом через сеттер как в симфони прямо контейнером.
https://github.com/6562680/support
Но "ООПшным" способом - это если хочеться разобраться "как". Если хочется решить проблему - бери статью о фасадах в ларе и делай по ней.
Ещё одна деталь. Если ты будешь сильно увлекаться фасадами ты сделаешь код, который невозможно поддерживать. Понимаешь, статический вызов "хардкодит" в код функции имя класса, который её выполняет. Что делает невозможным будущую подмену без наследования, а наследование там где не нужно - это не к добру.
Судя по твоему примеру с моделью ты пытаешься дать модели некое действие, потому что так подразумевает логика твоей программы, то есть ты условно хочешь научить модель Юзер создавать или там менять как-то другого/несколько/всех юзеров. Поздравляю, ты подошел к понятию "агрегата", который в книгах много где встречается. Но это слово упрощается до слова "класс-сервис", когда ты свой метод создаешь не в модели Юзер, а в другом классе, называешь его UserService, и потом его на входе конструктора ожидаешь, и он туда будет подброшен, и не надо будет статикой ничего делать.
Но да, есть и тут подводный камень. Когда хочешь изнутри модели в методе вызвать, там же конструктор уже занят $attributes, надо наследовать, а потом создавать модельки уже не через new, а через контейнер, чтобы подбрасывалось - но это боль. Поэтому перейди к работе с классами сервисами. Если ты хочешь поменять модель - ты свою модель передаешь в метод сервиса параметром, где сервис над моделью делает действие и выдает измененную.