is there some equivalent way to use safe navigatio...
# cfml-general
w
is there some equivalent way to use safe navigation when using square bracket struct notation?
Copy code
var env = server?.system?.environment ?: {};
if( env.keyExists(arguments.name) ) { ... }

to this: 

var env = server?.system?.environment?[arguments.name] ?: "";
or something similar. it's not hugely important to do the second way, just curious if there's a square bracket version of safe navigation
t
I cant give you a definitive answer but I have never got it to work
w
i'm sure there's a way to do it with evaluate() but i wouldn't bother if that's the case tbh.
t
adobe define it as an alternative to the dot . operator
You can use the safe navigation operator to access members of a Struct or values of an object.
Instead of ".", using the safe operator ensures that exception is not thrown when the variable is not defined.
w
right. just not sure it's worth
var myValue = evaluate("server?.system?.environment?.#arguments.name# ?: ''");
assuming that works
t
this is my version
return server.system.properties[ settingName ] ?: server.system.environment[ settingName ] ?: defaultValue;
d
Won't that crash if system doesn't exist in server, etc?
t
yes it would but someone would have to delete it from the scope and I would be very cross if they did
d
understood, but we have no idea about @websolete's use case, he was asking about the syntax for safely navigating through a possibly incomplete hierarchy.
w
to be clear, my use case is a application.cfc method to return environment vars, the method as it stands now (lucee 5.x):
Copy code
/**
	 * Returns the specified environment variable
	 *
	 * @name string 					the name of the env variable in the server.system.environment scope
	 * 
	 * @throws InvalidEnvVariable 		thrown when the specified variable does not exist
	 * 
	 * @return any 
	 */
	private any function getEnvVar( required string name ) {
		var env = server?.system?.environment ?: {};
		if( len(arguments.name) && env.keyExists(arguments.name) ) {
			return env[arguments.name];
		}
		else {
			throw( type="InvalidEnvVariable", message="The specified environment variable [#arguments.name#] does not exist" );
		}
	}
i just wanted it to be the 'best' it could be syntactically before i move on and forget about it
i could have try/catch'ed it and referenced it directly, letting it throw an exception if it doesn't exist, but i find that undesirable if you can gracefully check existence
a
I just... erm... tried it... https://trycf.com/gist/a431e29bb1cedbbcd82981276184aaf3/acf2021?theme=monokai
Copy code
st = {
    "DOES_EXIST" = "some value"
}

writeoutput(st?["DOES_NOT_EXIST"]) // undefined
writeoutput(st?["DOES_EXIST"]) // some value

key = "DOES_NOT_EXIST"
//writeoutput(st?[key]) // Error: Invalid CFML construct
Note that it only seems to work with string literals. Not with variables. Someone who cares should perhaps raise a bug for that (ping @Mark Takata (Adobe)) Doesn't work at all on Lucee. See above re "someone who cares ~"
(ah, there's already a ticket for Lucee for this: https://luceeserver.atlassian.net/browse/LDEV-2540)
Oh... also doesn't work for arrays, just structs.