Sigh... didn't take long for me to be writing CFML again. My excuse is this started out being comparison code for a PHP article, but I've run into some issues.
Consider this code:
// Application.cfc
component {
this.invokeImplicitAccessor = true;
}
// Test.cfc
component {
property numeric score;
public function getPropertyMetadata(){
return getMetadata().properties;
}
}
// testTest.cfm
test = new Test();
writeDump(test.getPropertyMetadata());
This demonstrates that this sets the property correctly, as the output bears out:Array | ||||||||||||
1 |
|
(and ColdFusion is the same)
Next I want to give it an initial value, so presume the syntax is the same as param:
param numeric someOptionaNumericVar=0;
The equivalent being:
property numeric score=0;
On Railo I get this:
Array | ||||||||||||||||
1 |
|
Err: no. It's parsed the code as if it was this (I'll use tags for clarity here):
<cfproperty name="numeric" score="0">
(bear in mind that
<cfproperty>
is one of those constructs which accepts any old attribute/value pair, and any non-standard-CFML ones are treated as metadata).But Railo's parsed the thing wrong here, IMO. In ColdFusion I get this:
The following information is meant for the website developer for debugging purposes. | |||
Error Occurred While Processing Request | |||
|
OK. Well it sux this doesn't work. I'll have to do it this way:
property type="numeric" name="score" default=3;
Next issue.
I have my default value, but ColdFusion seems to deny it's there!
Here's an updated example CFC:
// Test.cfc
component accessors=true {
property type="numeric" name="score" default=3;
public function getPropertyMetadata(){
return getMetadata().properties;
}
public function dumpScore(message){
writeOutput("#message#:<br>");
writeOutput("Exists in variables scope: #structKeyExists(variables, "score")#<br>");
writeOutput("Exists in this scope: #structKeyExists(this, "score")#<br>");
writeOutput("<hr>");
}
}
And test rig:
// testTest.cfm
test = new Test();
test.dumpScore("Initial state");
score = test.getScore();
writeOutput("Score is: #score#<br>");
test.dumpScore("After get()");
test.setScore(44);
writeOutput("Score is: #test.getScore()#<br>");
test.dumpScore("After set()");
Here's the summary:
- I default the property to 3
- I check if it's defined in either variables or this scope
- I get it
- I check if it's defined again
- I set it to something else
- I check again
Running this on Railo, I get this:
Initial state:
Exists in variables scope: true
Exists in this scope: false
Score is: 3
After get():
Exists in variables scope: true
Exists in this scope: false
Score is: 44
After set():
Exists in variables scope: true
Exists in this scope: false
So it's stored in the variables scope. As one would expect.
But on ColdFusion:
Initial state:
Exists in variables scope: NO
Exists in this scope: YES
Score is: 3
After get():
Exists in variables scope: YES
Exists in this scope: YES
Score is: 44
After set():
Exists in variables scope: YES
Exists in this scope: YES
There are two things wrong here. Firstly: ColdFusion should not be exposing properties as public! They are supposed to be accessed via accessors, after all. Also: it doesn't expose the default correctly in the variables scope to start with.
I used to despair because I'd find bugs in ColdFusion when trying to test something in Railo, and just comparing how ColdFusion does the same thing. Now I'm finding bugs in ColdFusion when I'm not even trying to use CFML!
Summary of bugs:
- Railo should be able to parse
property numeric score=0
as a numeric property called score with a default of zero. Same as it would for aparam
. It's fair enough if it gets more complex than that, then perhaps the old-school syntax becomes necessary: RAILO-3205. - ColdFusion exposes properties via the
this
scope: 3825535. - ColdFusion mishandles property defaults: 3825537.
Back to PHP now.
--
Adam