7 Replies - 458 Views - Last Post: 25 February 2013 - 08:30 PM Rate Topic: -----

#1 e_i_pi  Icon User is offline

  • = -1
  • member icon

Reputation: 789
  • View blog
  • Posts: 1,675
  • Joined: 30-January 09

__get() and what context it is invoked in

Posted 10 February 2013 - 07:17 PM

Is there any way to determine what context a __get() is invoked in? I'm thinking in terms of templating engines, specifically a javascript template and displaying boolean values as strings. Take the following for example:
<? if($this->isViewable): ?>
$true = <?= $this->isViewable ?>;
<? else: ?>
$false = <?= $this->isViewable ?>;
<? endif; ?>


If there is no __get() method for $this, the output of the above code will either be '$true = 1;' OR '$false = ;' depending on the value of $this->isViewable.

On the other hand, if we define the __get() method as:
public function __get($property)
{
  if($this->$property === false) return 'false';
  if($this->$property === true) return 'true';
  return $this->$property;
}


...then the conditional statement in the template will always be true, so the output will either be '$true = true;' or '$true = false;'. Anyone got any ideas about how to tackle this by using __get()? I've racked my brain and I'm not sure it's possible. The two options I can see are:
  • Have two properties ($isViewable and $stringIsViewable) and store both the boolean and string values separately. This seems messy to me, as it could lead to mismatches between the intended data.
  • Use a custom PHP function in the template which casts booleans, nulls, etc to string, like so: <?= toString($this->isViewable) ?>

I prefer the second option, but I'd like some feedback/insight from forum colleagues :)/>

This post has been edited by e_i_pi: 10 February 2013 - 07:19 PM


Is This A Good Question/Topic? 0
  • +

Replies To: __get() and what context it is invoked in

#2 CTphpnwb  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 2889
  • View blog
  • Posts: 10,002
  • Joined: 08-August 08

Re: __get() and what context it is invoked in

Posted 10 February 2013 - 07:37 PM

Why are you returning a string instead of true/false in the get method?
Was This Post Helpful? 1
  • +
  • -

#3 creativecoding  Icon User is offline

  • Hash != Encryption
  • member icon


Reputation: 926
  • View blog
  • Posts: 3,204
  • Joined: 19-January 10

Re: __get() and what context it is invoked in

Posted 10 February 2013 - 09:19 PM

Not sure if I'm totally following your example script up there e_i_pi, but I'm going to assume the variables you are trying to assign (through PHP), aren't in PHP.

CTphpnwb: He's outputting a boolean value, where true will output "1" and false will output "0", he wants it so that true outputs "true" and false "false".

This is pretty interesting... An option you can consider is prepending the variables with their data type, like a form of casting. Something like this:

public function __get($property){
		if(substr($property, 0, 2) == "s_"){ // They want to cast $property to a string
			$newProp = substr($property, 2); // Get property name
			if(gettype($this->$newProp) == "boolean"){ // We're going to do some special stuff for booleans
				$newProp = ($this->$newProp) ? 'true' : 'false';
			} else {
				$newProp = (string)$this->$newProp; // Just cast it
			}
			return $newProp;
		}
		return $this->$property;
	}



And using this, your example would look like:
<? if($this->isViewable): ?>
$true = <?= $this->s_isViewable ?>;
<? else: ?>
$false = <?= $this->s_isViewable ?>;
<? endif; ?>




Another super-complicated and probably super-slow idea could be to get the calling script's line + file using debug_traceback(), opening up the file that called __get, and detecting what type of opening tag was used (ie <? and <?php would return the actual value, while <?= would return the string version). But that's super complicated and probably a bad idea.

This post has been edited by creativecoding: 10 February 2013 - 09:22 PM

Was This Post Helpful? 1
  • +
  • -

#4 CTphpnwb  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 2889
  • View blog
  • Posts: 10,002
  • Joined: 08-August 08

Re: __get() and what context it is invoked in

Posted 10 February 2013 - 10:06 PM

Right, but I think the template is driving bad PHP code. Why not do something like this?
if($this->_get("isViewable")) {
	// output something
	echo "True";
} else {
	// output something else
	echo "False";
}


or
$True_false = array("False","True");
echo $True_false[$this->_get("isViewable")];

Was This Post Helpful? 1
  • +
  • -

#5 e_i_pi  Icon User is offline

  • = -1
  • member icon

Reputation: 789
  • View blog
  • Posts: 1,675
  • Joined: 30-January 09

Re: __get() and what context it is invoked in

Posted 11 February 2013 - 12:51 AM

creativecoding has the right idea of what i am getting at. I want to reference the properties without using prefixes like 's_' though, which is the part I don't think is possible. Consider the following template:
<b>Testing</b>
<br>
<? if($this->myBoolean === true): ?>
This text shows if the $myBoolean is true
<br>
<? endif; ?>
<? if($this->myBoolean === false): ?>
This text shows if the $myBoolean is false
<br>
<? endif; ?>
<script type="text/javascript">
var myBooleanJs = <?= $this->myBoolean ?>;
if(myBooleanJs === true)
{
	alert('myBooleanJs is true');
} else if(myBooleanJs === false) {
	alert('myBooleanJs is false');
} else {
	alert('myBooleanJs is non-boolean');
}
</script>


Mixing of languages aside, consider lines 3 and 12. In line 3, we need $this->myBoolean to be returned as a boolean value. In line 12, we need it returned as a string literal. The difference between lines 3 and 12 is that line 3 references the property in a code context, whereas line 12 is echoing the property. I guess what I'm asking is if anyone knows if there is a way to apply a __toString() magic method to a property, not an object. I don't think there is a way.

I think the best solution will be to change line 12 of the above to:
var myBooleanJs = <?= toJavascriptString($this->myBoolean) ?>;


...and define the toJavascriptString() function as...
function toJavascriptString($value)
{
	if($value === null)	return 'null';
	if($value === true)	return 'true';
	if($value === false)	return 'false';
	if(gettype($value) === 'array')	return json_encode($value, JSON_FORCE_OBJECT);
	return $value;
}


Was This Post Helpful? 0
  • +
  • -

#6 Dormilich  Icon User is offline

  • 痛覚残留
  • member icon

Reputation: 3479
  • View blog
  • Posts: 10,025
  • Joined: 08-June 10

Re: __get() and what context it is invoked in

Posted 11 February 2013 - 01:00 AM

View Poste_i_pi, on 11 February 2013 - 08:51 AM, said:

In line 3, we need $this->myBoolean to be returned as a boolean value. In line 12, we need it returned as a string literal. The difference between lines 3 and 12 is that line 3 references the property in a code context, whereas line 12 is echoing the property. I guess what I'm asking is if anyone knows if there is a way to apply a __toString() magic method to a property, not an object.

I think that is more of an issue of programming design. why should a property have a string representation, resp. what does it mean if it had?

well, one thing that comes to mind then is var_dump()s little brother var_export().
var_export($this->myBoolean); // echoes "true" or "false"

Was This Post Helpful? 2
  • +
  • -

#7 Atli  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 3710
  • View blog
  • Posts: 5,958
  • Joined: 08-June 10

Re: __get() and what context it is invoked in

Posted 24 February 2013 - 03:22 PM

A little late to the party here, but I'd just like to make one comment on this whole issue.

Having the object itself determine the string value of the boolean attribute seems a bit off to me. I mean, why would you want the object itself to control what string value is printed into the template? The string representation of a boolean (and other numeric types) can be vastly different based on what kind of template it's being injected into. For instance, in your case you want it to be the Javascript boolean values: "true" or "false", but in other cases it may well need to be "1" or "0", or "Yes" or "No".

In my opinion, the string injected into the template should be determine in the template, not inside the object providing the data.
var myBooleanJs = <?= $this->myBoolean ? "true" : "false" ?>;



If it's really an issue, and getting a string value out of the object is a must, then I'd suggest abandoning manipulations of things like magic methods and just go with an old-school method. Something like:
var myBooleanJs = <?= $this->getMyBooleanString() ?>;


var myBooleanJs = <?= $this->getMyBoolean(self::GET_STRING) ?>;


Or something along those lines.

There is really no point going overboard in trying to keep it only as an attribute reference. If anything, that just makes the code less understandable. The point of the above method calls is obvious even to somebody with no prior knowledge of the system. If you just reference a boolean attribute, people will be expecting it to print out the typical string value for an echoed boolean. They won't be expecting it to print a custom string without examining the source code for the class, or if you add comments explaining it, which in itself more or less a wasted effort.

KISS, you know :)
Was This Post Helpful? 0
  • +
  • -

#8 e_i_pi  Icon User is offline

  • = -1
  • member icon

Reputation: 789
  • View blog
  • Posts: 1,675
  • Joined: 30-January 09

Re: __get() and what context it is invoked in

Posted 25 February 2013 - 08:30 PM

Yeah I've gone with an injected PHP function in the templates, like this:
var myBooleanJs = <?= toString($this->myBoolean) ?>;


...which converts null to 'null', true to 'true', false to 'false', arrays to JSONs, and otherwise just echoing the value. I thikn it throws exceptions on objects and some other complex data-types, not sure, at work and can't look at the code :)
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1