Well, whether something can or can’t be represented by a primitive is a matter of use case. Can an age be an integer? Sure it can. All operations might be useful on an age for an application that does, say, enable puzzles around an age.
Do I want to control allowed operation on an object? Plenty of cases when I do, also plenty when I don’t.
Generally, if something happens to an object in some part of the code is because someone had a need.
Immutability? Sure, it’s generally a great idea but I’d rather use something when I need it or because it solves an actual problem, rather than a potential problem. If you end up with just an immutable wrapper around a string, I’d say the benefits (largely potential) don’t justify the overhead (if changing value accidentally is an issue and your unit tests don’t reveal that, then you have problems of a whole different kind in your team — and if they do, then what’s the issue to solve?)
What I don’t appreciate is something that feels like attempts to Java-fy PHP (not restricted to PHP though, a common gripe among people that learn a given language is “why isn’t it more like <insert different language>”).
Going blindly full-VO without actual needs or problems to solve (eg: do I need validation close to the object? is it a more complex object?) just leads to a huge amount of boiler plate code.