It's a fairly common practice to have model classes use __get and __set` to provide access to the fields of the object rather than having to manually define getters and setters for every field on every model class.
However, Hack doesn't support this since it can't see the properties, so doesn't believe they exist. Currently, this means something in the inheritance tree (or a trait) has to be in PHP so that the type checker stops complaining.
My suggestion for a potential solution is to copy the @property attribute, but as a Hack attribute.
Something like:
<?hh
<<__Property('myProp', int), __Property('myOtherProp', ?DateTime)>>
class MyModel extends Model {
public function testing() {
var_dump($this->myProp, $this->myOtherProp);
}
}
where Model is also a Hack class which contains at least __get. Hack would then know that MyModel->myProp is an int and MyModel->myOtherProp is a nullable-DateTime even though the actual properties are never defined.
This would require __get to be defined in the ancestry of the class and trying to assign to one would require __set.
Yeah -- I don't think this is an unreasonable feature to have, I'm just not sure what the right version of this would look like. You're also not the first person to ask about it :)
cc @dlreeves FYI, we probably won't get around to this any time soon, but nice to keep track of.
Wouldn't an .hhi file be right solution for this?
No. That requires Hack to not know about the implementation of the class, which means it has to be PHP.
You're right, I should've tested first. Wishful thinking... Something like .hhi files would be nicer IMO, especially when the magic methods handle a bunch of cases.
Personally I would more love to have "proper" properties, drawing inspiration from C#:
<?hh
class MyClass {
// $myProp is an int with default getters and setters, not much different
// from simply declaring it as a field
public int $myProp { get; set; }
private string $_myField;
public string $myField {
get { return $this->_myField; }
set ($value) { $this->_myField = $value; }
}
}
This would allow one to use properties, without the uglyness of the magic methods. Also, get and set should support having different visibilities - such that you can have a property with a public get and private/protected set.
Just chiming in, my two cents. I don't make decisions about direction hhvm should go in. I am not an hhvm engineer.
HHVM has dropped support for the __get() and __set() magic methods in hhvm 4.56.0.
This allows the runtime to know that $x->prop = 4 will not invoke arbitrary Hack code.
(except for throwing a TypeError or invoking a PHP error handler if there is a runtime typemismatch, depending on the hhvm.check_prop_type_hints setting).
I don't know how much perf can be gained by having this axiom.
Most helpful comment
Personally I would more love to have "proper" properties, drawing inspiration from C#:
This would allow one to use properties, without the uglyness of the magic methods. Also,
getandsetshould support having different visibilities - such that you can have a property with a publicgetandprivate/protectedset.