I am trying to figure out if there is a way to eliminate all of the implicit variable access like shown in the photo below. Basically what we are doing is looping over the properties and calling the setters dynamically rather than typing out each setter one by one.
Here is an example of what we are doing:
component accessors="true" {
property name="first_name";
property name="last_name";
property name="middle_name";
public any function init(first_name = "", last_name = "", middle_name = "") {
var args = arguments;
structKeyList(args).each(function(ele) {
variables["set#arguments.ele#"](variables.args[arguments.ele]);
});
return this;
}
}
This is what we get when doing it this way:
In the screenshot below we changed out the word âvariablesâ for âthisâ and get twice as many implicit variable access counts.
This might not seem like a big deal for something this small but on some of our modules we sometimes get counts upwards of 60k and I am hoping if we eliminate the implicit variable access we can increase performance. Here is an example where the counts start to balloon up:
When using accessors you donât need an init()
function. In fact, itâs quite a bit faster to not have an init function. Also, the properties of the component now have accessors (getFirst_name()
) and mutators (setFirst_name()
) that can be called on the component.
This is all you really need:
component accessors="true" {
property name="first_name";
property name="last_name";
property name="middle_name";
}
You can initialize the component and set itâs properties like so:
myComponentObj = new path.to.componentName(
first_name = 'Bob',
last_name = 'Robertson',
middle_name = 'Robbie'
);
And, once the component (bean) is instantiated (as myComponentObj
) you can easily modify any of itâs values or retrieve any of itâs values:
myComponentObj.setFirst_name( 'Jane' );
and
echo( myComponentObj.getFirst_name() );
There is no need to set the arguments into the variables scope, accessors already does this for you. No need for an init function, no need to do any of what youâre currently doing if youâre using accessors, really.
HTH
1 Like
@ddspringle I wasnât aware you could do that, it is very cool, thanks. However the example I gave is a lot simpler than what we are actually doing in some places. In some of our code we are not doing it inside of the âinitâ but rather functions inside the component. We have several objects extending a base component and the base component has a method that goes and sets some of the accessors based on some logic. To rework the current code to allow for this method would not be possible without a major architecture change so is there an alternative way to prevent the implicit variable access?
Another thing I noticed that is not in my original response is that with the method you suggested it ignores the validators. For example I can make a property type numeric but pass in a string and it still gets set.
@Yamaha32088 Unfortunately itâs an all or nothing thing as far as I know. You either set accessors=true to get the accessor/mutator pattern or you donât set it (or set it to false) and wire up your own getters and setters as needed (which is considerably slower, btw).
Without seeing your code and understanding exactly what youâre doing or what you mean by âthe base component has a method that goes and sets some of the accessors based on some logicâ I canât really suggest any workarounds. If you want to shoot me your base component and one of your complex components that make use of it via email I can take a look and see if I can figure out a less invasive way of working around a giant re-engineering effort (denard.springle@gmail.com)
As for setting a type of numeric and being able to populate it with a string⌠thatâs not exactly what I find in my testing. While it doesnât throw an error as it should, it simply leaves the default value in place (null, in my case). Filed a bug: [LDEV-1560] - Lucee
Hereâs my test code:
test.cfc
component accessors="true" {
property name="alice" type="numeric";
property name="bob" type="boolean";
}
test.cfm
<cfscript>
testObj = new test(
alice = 'james',
bob = true
);
writeDump( testObj );
testObj = new test(
alice = 12,
bob = false
);
writeDump( testObj );
</cfscript>
and the results (on 5.2.3+35):
I havenât tested 4.5 yet but ACF throws an exception as expected.
EDIT: I just tested 4.5.5+006 and this is an issue there as well. This might be a type coercion issue.