Полноценного понимания не существует.
Я долго писал в процедурном стиле и долго не мог понять зачем вообще нужны эти классы какие-то.
Всё решалось функциями. С ростом сложности проекта приходилось передавать в функции всё больше и больше аргументов. Когда аргументов стало слишком много, я стал передавать в качестве аргумента массив с переменными.
Функция изменяла значения в этом массиве и возвращала.
Иногда (часто) функция должна была вызвать другую функцию и передать туда этот массив. Количество функций росло, цепочки из них становились всё длиннее и я даже стал путаться в том, какая функция в какой цепочке (трейсе) участвует.
Тогда я стал раскладывать группы функций по разным подключаемым файлам и называл эти файлы так, чтобы по названию понять какой группе переменных они нужны.
А потом я случайно узнал, что эти какие-то непонятные методы, которые "являются поведением объектов класса" (как это обычно объясняют) на самом деле просто функции и есть. И оказалось, что можно не пропихивать массив через них, а наоборот - функции сложить в этот массив. Получилось, что класс это такой "массив" в котором есть не только переменные, но и функции. И эти функции могут видеть все эти переменные, даже если не написать global $var. И это было как раз тем, чего я очень желал и радости моей не было предела.
Кстати, узнал я это, когда забавы ради кодил 2D платформер на C# в Unity.