$row - это не модель, это структура строки в базе данных.
Когда ты пишешь $row->property, ты программируешь в процедурном стиле:
$row = selectTableRow('users', 'id = 1');
$row->email = $new_email;
updateTableRow('users', 'id = 1', $row);
В случае, если это все обертывается в классы - это получается Table Gateway, который по сути процедурный подход, обернутый в классы. От того, каким образом ты обернешь - сделаешь публичные свойства, сделаешь геттеры/сеттеры, или сделаешь магию __get/__set - ничего принципиально не меняется, это вопрос конкретной реализации.
То, что в Laravel и Yii называется моделями, ими в строгом смысле слова не является. Их _можно_ использовать как модели, но в этом случае ты никогда не должен писать $user->email. Только $this->email внутри класса User.
В Symfony ты можешь добавить геттеры и сеттеры, чтобы получить аналог $user->email и свести все к Table Gateway. А можешь не писать, и делать полноценные ООП-модели.
Есть, конечно, еще Read Models, которые по сути своей иммутабельные read only структуры - там ты можешь написать $user->email или $user->getEmail() - но не можешь написать $user->email = $newEmail или $user->setEmail($newEmail). Конкретно в PHP тут обычно появляются геттеры по той причине, что в PHP нельзя средствами языка сделать readonly-свойство (есть вариант с магией через __get, но у него свои недостатки - придется описывать свойства в phpdoc, иначе IDE ничего не будет знать о структуре). Те модели, которые в Laravel и Yii, можно использовать как Read Models, если ограничиться только чтением свойств - но тут вознкикает проблема с тем, что Read Models обычно больше одной на одну сущность.