After all this time doing PHP it never occured to me that the following is perfectly valid:
CLASS testClass{
public $attribute;
public $attribute2=10;
function testClass($a){
$this->undeclared=$a;
} function flag(){
$this->flag=true;
}
function out(){
echo $this->undeclared=$a;
}
}
$b=new testClass(5);
$b->out;
This is just as valid tho extremely more risky if you dont keep track of your own code…
CLASS testClass{
public $attribute; // this is what I am referring to when I say "declaring"
public $attribute2=10; // this is what I am referring to when I say "declaring"
function out(){
echo $this->undeclared=$a;
}
}
$b=new testClass();
$b->undeclared=5
$b->out;
My question is… other than “organizational” value, what is the real point/benefit to declaring public properties when creating a class when, essentially, you can create them at any point in the code, in same way you would create regular variables (except with $instanceName-> or $this-> preceding the variable). It would seem that there are even some uses to NOT declaring public variables at times. Example , you can tell if the flag function has been called at least once in any particular instance with isset($this->flag).
Am I some how way of the mark here? I would love to hear the opinion of he forum experts on this topic.
But I guess the point I was trying to bring up is that I thought you couldn’t have a $this->variablename w/o having a var variableName. In other words, that the properties of an object were immutable and set at the declaration level. When in fact an object can contain, inadvertently or not, more properties than its creator originally intended. (whether this can be harnessed or not is yet another matter)
Using undeclared properties in a class is generally a bad idea. You sometimes hear people talk about __SET() and __GET() magic methods. Try going through an application that uses magic all over and say write tests for troublesome methods. It can be really messy when it is so much clearer and explicit to declare your properties.
This $this->undeclared=$a; invokes the magic __SET() method.
Magic methods in classes are very heavily setter/getter based these magic methods can be used without too much trouble, but they should be used with caution.
This $this->undeclared=$a; invokes the magic __SET() method.
Even if __SET() is not a function in the class?
Please note that am NOT TRYING to set undeclared properties, I did it by accident and noticed that the the code compiled and functioned fine. It seemes to me that public properties actually behave much like regular variables do outside and can be initially set at any point in the code… or even from an instance of an object ( for that specific object).
So I guess what I am asking you is is what is happening is this? Remember my classes do not explicitly contain a _SET() function.
an undeclared property is set.
An exception is thrown because this is not actually allowable in PHP
BUT _SET() is automatically invoked ( I guess by the compiler, since I didn’t code the function into my code)
_SET creates the property as describes and all appears well?
The undeclared property will issue a warning but will still work in php 5.2x. The way I understood it from talk that the php.net team did, was that undeclared variables use the same hooks as __SET() do and issues it like a __SET() would. So PHP is being forgiving in this instance. In php 5.3 this does not work any longer and throws a fatal exception. In php 5.3 you must declare a property or explicity use __SET() to declare or set a value for a object’s property. While using php 5.2x then it is recommended as logic_earth indicated for maintenance and in addition not having to deal with warnings. In 5.2x use of __SET() is implicit so no warning is issued.
You can also read this over at PHP freaks with someone that had a similar question
Thanks Steve,
That makes a lot of sense. In fact I was using PHP5.2.6; should have mentioned it from the start, sorry. As I said earlier creating a property on the fly is not something I would normally do, so I was surprised when I saw that I could “get way with it” . Thanks again for the clarification.
I was referring to Dresden’s example where he can do this
<?php
CLASS testClass{
public $attribute; // this is what I am referring to when I say "declaring"
public $attribute2=10; // this is what I am referring to when I say "declaring"
function out(){
echo $this->undeclared=$a;
}
}
$b=new testClass();
$b->undeclared=5;
$b->out;
On my servers I now use PHP 5.3.3 and it will not let me run this without throwing a fatal exception; however I have one VM running PHP 5.2.6 and I can run this, but when I set error report to ALL it provides "Warning (3 Items) Access to undeclared property ‘undeclared’.
I do have a test page which I do have register to a custom error handler and I quickly checked to see if this was raising this error but I did not find it using search, so I thought the warning came from php?
This is not an error generated by PHP, nor would the code that you quoted give any sort of message about the undeclared property being undeclared. This is because the undeclared is being declared when you assign a value to it.
In all versions of PHP 5, the quoted code would give a single E_NOTICE level error with the message “Notice: Undefined property: testClass::$out in <file> on line 12”, which is caused by the line: $b->out; This is because, as the notice says, the property is undefined when you try to read it on that line.
Do you run any extensions or other scripts which might display different errors?
When copy/pasting code in you should make sure the code itself works. Things like: “echo $this->undeclared=$a;” will cause problems. Once the errors are removed then the code will run just fine under 5.3+ with no notices. Being able to add properties on the fly is considered to be a feature.
You can however prevent this by simply adding in your own __set method.
class testClass
{
public $attribute; // this is what I am referring to when I say "declaring"
public $attribute2=10; // this is what I am referring to when I say "declaring"
function out()
{
echo $this->undeclared;
}
function __set($name,$value)
{
echo '*** Adding properties on the fly is not allowed: ' . $name;
}
}
ahundiak, when I copied the code to my IDE, I did need to straighten up a little of the code to run it. Unfortunately when I copy something from my Eclipse into the
window it nukes the formatting, so I simply copied the examples directly using quoting so its' formatting stays ok.
I did find a custom extension that we had compiled for apache, I removed this extension, restarted apach and then did see the notice that Salathe indicated. I subsequently removed this extension on any of our VMs that had it, re ran the test suites for the apps that we have running on these VMS and they checked out fine. After removing this extension I see consistent notices (as described by Salathe).
Thanks!
Steve
This line here: echo $this->undeclared=$a;
Will always cause a notice (assuming error_reporting) is set.
There is no $a nor does it make much sense to to do an assignment during an echo.
I run this directly from the command line using 5.3.5:
error_reporting(E_ALL);
class testClass
{
public $attribute; // this is what I am referring to when I say "declaring"
public $attribute2=10; // this is what I am referring to when I say "declaring"
function out()
{
echo $this->undeclared;
}
}
$b =new testClass();
$b->undeclared=5;
$b->out();
Got the expected output and no notices. We might be talking about two different things here but I see no indication that the ability to assign properties on the fly is being removed from php?
error_reporting(E_ALL);
class testClass
{
public $attribute; // this is what I am referring to when I say "declaring"
public $attribute2=10; // this is what I am referring to when I say "declaring"
function out()
{
echo $this->undeclared;
}
}
$b =new testClass();
$b->undeclared=5;
$b->out();
I get the output of: 5, and you are correct no notices. Sorry I did not catch the $a there so that is what was throwing the notice.
The custom extension that I removed was ‘messing’ with the error reporting that I spoke about earlier. For this I was using PHP 5.2.6 I can’t test 5.3.3 until I get to a machine that I can connect to our VMs so I will try this there and let everyone know.
I ran the code on our 5.3.3 machine and we did get notices and the code fails. I don’t have time to track down why, but I trust that by default it should work and my systems have something altering this behaviour. Back to Dresden’s point, this is an ugly behaviour for objects. I mean one doesn’t HAVE TO use it but an accident of forgetting to declare the property should not work… Maybe it is my recent work with JAVA talking
There has been no discussion on that topic that I’m aware of, and cannot see such a proposal ever considered. I’m intrigued in what ServerStorm saw/read that indicated that exceptions would be thrown in PHP 5.3, especially since it sounded like it came from “the php.net team”.
My bad I looked it up and this only applies in at least php 5.3.3 to missing static properties. ie, echo Foo::$missingProperty; // fatal error: access to undeclared static property
Sorry for my lack of clarity on this as it has taken a lot of others efforts to clean it up!
Moving forward, I will be more diligent checking before speaking.