0

I have just learned that you can set any property of a class (as long as it's not explicitly declared as a private one). For example:

class Test {}
$test = new Test;
$test->randomthing = 'Hello world';
var_export($test);

Works just fine to set the property randomthing of the $test object.

I am trying to find out what this behaviour is called, and if it's possible to eliminate/disable it (to minimise errors in code), because as it currently stands, i can be typoing my desired properties and not notice in time.

Ideally, i would want to have:

class User {
    protected $name;
}

And then i want to be able to set a $user->name = '', but not $user->randomthing = ''. This second call would ideally throw an exception or something.

I have tried to guess this convention by looking up "dynamic properties", but that seems to refer to stuff like the double-dollar syntax to reference a property by a value in a variable.

So, what do you call this behaviour? And where can i read up more about controlling it (or disabling it)?

yivi
  • 42,438
  • 18
  • 116
  • 138
Digital Ninja
  • 3,415
  • 5
  • 26
  • 51
  • 1
    how would you plan on preventing that? That's like trying to disable adding to array functionality (as in: `$array[] = $foo`) – treyBake Jun 04 '19 at 12:11
  • @treyBake Yea that's MY question. Is it possible to prevent it, or is it a baked part of the language. (although i disagree that it's equivalent to pushing an item into an array). *i mean not "prevent", that sounds like having another behaviour prevent the previous behaviour. I meant like is it possible to have "strictly typed properties", for the lack of a better term. – Digital Ninja Jun 04 '19 at 12:13
  • 1
    You can not disable this in PHP, it’s a “feature”. If anything, you should set up your IDE to warn you about stuff like this, or run some sort of linter on your code that spots stuff like this. – 04FS Jun 04 '19 at 12:21
  • 1
    `And then i want to be able to set a $user->name = '', but not $user->randomthing = ''. This second call would ideally throw an exception or something.`. Given that `name` is protected, and you'd need to intercept `randomthing`, and assuming $user is outside the User class, you probably want to look at the __set magic method. In there you check for property existence, set the value if it is, throw an Exception if it's not. – Jonnix Jun 04 '19 at 12:24

2 Answers2

2

It doesn't have a special name or anything, it's just assigning a property to an object. This is standard and default PHP - to my knowledge, this isn't something you can disable/turn off.

All we're doing $object->newProp = 'foo' is appending a new key with a value to the object, that key + value pair isn't globally available once it's been added. It's only for that object. It's the same principle for an array:

$array = [1, 2, 3];
$array[] = 4;

We're doing the same with your object:

$object = new Class();
$object->foo = 4;
treyBake
  • 6,440
  • 6
  • 26
  • 57
  • OP could probably use __set and add some logic to fail? – Jonnix Jun 04 '19 at 12:16
  • @Jonnix only if the classes/object isn't public ([see here](https://stackoverflow.com/questions/4713680/php-get-and-set-magic-methods)) – treyBake Jun 04 '19 at 12:18
  • @Jonnix well yeah, undefined = non-public property - though, doing it that way is good for array-based class properties – treyBake Jun 04 '19 at 12:31
  • Sure, and undefined properties is (most of) what OP was asking about. Not saying it's a good option, only that it's possible. – Jonnix Jun 04 '19 at 12:37
0

I would create a "magic" __set() function that doesn't set a parameter, but instead returns an error/warning.

public function __set ( string $name , mixed $value ) {
    if( in_array( $name, [ 'various', 'valid', 'properties' ] ) ) {
        $this->$name = $value;
    } else {
        trigger_error( "Setting unknown property ".__CLASS__."->$name is not permitted." );
    }
}

https://www.php.net/manual/en/language.oop5.overloading.php#object.set

Stephen R
  • 3,512
  • 1
  • 28
  • 45