In my projects I sometimes emulate getters and setters using `__get()` and `__set()` but that's heavy-handed and requires lots of PHPDoc annotation for type checking. Property hooks look awesome!
In my projects I sometimes emulate getters and setters using `__get()` and `__set()` but that's heavy-handed and requires lots of PHPDoc annotation for type checking. Property hooks look awesome!
I know the textbook answer is so that every single possible property can become some mutable chain of events so you can swap names or side-effects without the caller knowing, but I've yet to find a use for that in real life.
It just leads to builder patterns and other oddities like forced decorators like Java has everywhere. I felt like beans were the realization that perhaps we shouldn't be doing this.
It makes for a cleaner OOP-y interface in which the caller only cares about actually exposed properties and not methods to get and manipulate hidden properties.
IMHO using properties directly is a much more natural way to talk about objects, than having a bunch of methods to get properties. Getters and setters also help ensure that methods are only for changing an object's state, not getting an object's state. For example:
class User{
public ForumsPost $LastForumsPost{
get{
if(!isset($this->LastForumsPost)){
$this->LastForumsPost = <get from database...>;
}
// Return the cached property so we don't keep hitting the database.
return $this->LastForumsPost;
}
}
}
print($user->LastForumsPost->Title);
print($user->LastForumsPost->PostId);
// instead of...
print(($user->GetLastForumsPost())->Title);
print(($user->GetLastForumsPost())->PostId);Then again, I'm not a fan of code that does magical things that aren't apparent. Makes it a lot harder to 1) reason about and 2) solve performance issues. I also don't want the overhead of function lookups for every property access.
Very often for a typical CRUD app, I as the caller don't really care how we got the `LastForumsPost`. It's just an object mapping that comes from some data source like the database. And if I do care, I could get it outside of the object, and set it myself.
Putting it behind a getter doesn't "hide" control flow. It just makes for a cleaner interface from the caller's perspective.
FWIW, I almost never use setters. Getters are are much more useful, especially for lazy-loading basic properties.
But you might want to support string date times and the PHP object DateTime as well. So a typical well designed ORM converts multiple PHP types into a SQL string for saving. That's what the historical __set and __get are all about. This is called "mapping" by most ORMs and a very well designed modern one like Doctrine will actually have mappings for different SQL storage engines available.
Obviously it also has to handle the reverse.
I agree! That's why it's wild to allow a setter to do literally anything.
You aren't just setting a property, there is a conversion happening under the hood.
And the reason I hate it is that code that appears to be infallible, isn't. It can have arbitrary side effects, raise exceptions, have unbounded runtime, etc.
In a lot of contexts you have something that requires a bit of code but really does behave like a property access, where it's more misleading to make it look like a method call than to make it look like a data access. E.g. using an ORM hooked up to SQLite embedded in the program. Or accessing properties of objects that you're using an EAV system or array-of-structs layout to store efficiently in memory. Or a wrapped datastructure from a C library that you're binding.
Of course if you make something look like a property that doesn't behave like a property then that's confusing. Programmers have to exercise judgement and only make things look like properties when they behave like properties. But that's not really any different from needing to name methods/objects/operators in ways that reflect what they do.
I sometimes use getters and setters to provide backwards compatibility. What was just maybe a simple data field a decade ago doesn't even exist anymore because some major system has changed and we aren't rewriting every single application when we can provide the values that they need easily enough.
If you know that setters exist then you already know that the code can do more. It's not a huge mental leap from property setting to method calls. You should never assume anything is infallible. I don't think classes should even expose raw fields.
I wrote about it here https://technex.us/2023/07/php-attributes-are-so-awesome-i-j...
It sounds like you got the gist but somehow you are in an area of programming where getter/setters aren't useful.
That's fine and okay. Part of growing up as a programmer is realizing your niche.
Most of the advice out there is deep, not broad. It's deeply connected with our niche and not necessarily broadly applicable.
The only sibling comment of yours that bothered to even show code just demonstrated how they turned user.lastPost into a method that makes a hidden DB query.
Yet the benefits are supposedly so nuanced and hard to get across that merely asking about it gets a "you'll understand when you get some real experience ;)" comment from you.
That's fine and okay.
I've been programming for 30 years, and getters/setters are both pointless and anti-productive.
They hide (potentially a lot of) code from people reading the program, which leads to a lot of "wtf" moments later.
Magic in general is bad, and it's the kind of "look how concise and clever I am" thinking that leads to unmaintainable software.
If setting a property isn't straightforward, make it private/protected and add explicit getter/setter methods. It's more work today and much less work later on.
seemed like a way to backport poor librar/framework choices to have IDE support but not for new code