Strongly Typed PHP

January 28, 2007 by PHP   This post is closed for comments.   This post is marked as obsolete.

Update 2016/05/22:
This post has officially been retired, an updated post (post PHP 7.x) can be read over here.
Often you'll hear the term "strongly typed" which refers to certain constraints being enforced regarding the type of a variable. (e.g. inability to compare a string value to an integer value unless you explicitly convert the string value to an integer)

PHP in contrast is a "weakly typed" language which means PHP implicitly converts types when/as needed. (sometimes in a funky manner)

Its also regarded as "dynamically typed" since instead of being required to explicitly declare the type of your variables (which one cant do in PHP, minus type hinting) types get derived from the value assigned to it (and re-derived when needed) during run-time.

But what if you want to make your classes strongly typed? (Force whoever use our class to assign the correct type of values to our class properties) - surely we can put checks in our code, but that can get a bit tedious.

Overloading in PHP 5 is a quick solution, one can overload the get and set members and control whatever variables get assigned and retrieved from your class.

Here is a quick snippet:
<?php

class StronglyTyped
{
	private $x;
	
	public function __get($name)
	{	
		if (!isset($this->enforcetype[$name]))
		{
			die("<b>Exception occured: </b>calling property $name which does not exist or set private");
		}		
		return $this->x[$name];
	}
	
	public function __set($name,$value)
	{		
		$type = $this->enforcetype[$name];
		
		if (isset($type) && $type != "")
		{
			$given = gettype($value);
	
			if ($given == $type) 
				$this->x[$name] = $value;
			else
			{	
				$exception = ($given != "") ? "<b>Exception occured on $name property:</b> 
												Type <i>$type</i> expected, type <i>$given</i> was supplied"
											: "<b>Exception occured:</b> no type specified for property $name";
				die($exception);
			}
		}
		else die("<b>Exception occured:</b> property $name not defined<br/>");
	}
}

?>

In the next snippet we inherit from the top class our "constraining class", we need to create an array, which contains our variable names and our preset types we want to constraint on.

class test extends StronglyTyped
{
	protected $enforcetype = array("stringy" => "string",
					"inty" => "integer",
					"booly" => "bool");
}

Once we instantiate the class, and try to assign an integer value for example, to the stringy member, we get an exception, since we specified that we only accept string types for that member. If we try to assign to undefined members we get an exception as well, all much like we see in languages like C#.

$a = new test();
//$a->inty = "10"; // Exception occured on inty property: Type integer expected, type string was supplied
//$a->stringy = 1; // Exception occured on stringy property: Type string expected, type integer was supplied
//$a->booly = "test"; // Exception occured on booly property: Type bool expected, type string was supplied


Update 2010-12-16
Apparently as of PHP 5.3, you're not allowed to set the visibility of magic methods to private/protected, only as public - I altered the snippets to reflect this change.


January 25, 2011 by Christoff Truter

Hey george Thanks for pointing out the documentation on gettype, I noticed the documentation on gettype a while ago as well, but didn't realise I made the mistake in one of my examples as well. Thank you, will adjust the snippet.

Web developer January 25, 2011 by george herson

Agree that code benefits from variable typing. The "time saved" by not doing so has a negative sign. Scala implicitly types (mostly), which would be ideal. A suggestion to not use gettype() for this purpose from php.net: "Never use gettype() to test for a certain type, since the returned string may be subject to change in a future version. In addition, it is slow too, as it involves string comparison. &lt;p&gt; Instead, use the is_* functions." -- http://php.net/manual/en/function.gettype.php

June 5, 2009 by Type hinting

Yes, this is what they call type hinting in PHP 5 http://www.php.net/oop5.typehinting Another way of doing this, is to create getters/setters for these properties you wish to be "strongly typed" and define your "constraints" within these methods. http://www.codebooth.com/snippets/24

Using wrappers May 26, 2009 by Lideln

What one could do to implement strongly typed variables, is to use wrapper classes just as it is done in Java, where everything is object. And do not forget that you can specify the class of a function parameter, like : public static final myFunction(Animal $oAnimal) And if you call that function with anything else than an Animal class instance, it will fail. Then, all you have to do, is to create a wrapper class for all the "basic types" you use (int, string, boolean, double, ...) See you !

Can do February 6, 2006 by Christoff Truter

Hey Thoward, it should be quite easy to modify the solution, one can simply remove the die in the set method, maybe register it as warning against PHP's trigger_error method (If you wish to check up on things later on) This was just a quick solution I came up with when I wanted some C# functionality in my PHP classes - always looking for better ways to do things, maybe give it a PHP flavour like you suggested?

I can see both points. February 5, 2006 by thoward

I came across this article looking for information on strong-typing in PHP because I'm a C# developer needing to do some OO work in PHP5. The lack of strong typing makes my poor brain twitch and quiver and leaves me running screaming from my IDE. That said, I think your implementation of strong typing shouldn't be so absolute. The way I would expect the behaviour to work would be: I have a variable that I want to strongly type, I register it in the strongly typed associative array (keyed by variable name, value of type name). The strongly typed base class get and set overloads check the array, and if the property is in the array, it enforces the type defined there strictly. If not, it does nothing (i.e., behaves in the normal dynamically typed PHP way). From what I can tell, in your implementation, if a variable is not registered in the array, it will throw an exception... Making it far to strict for Rome.

Strongly Typed PHP February 4, 2006 by Data Dude

This is gr8. Because a language that isn't strongly typed leaves the loophole open for erroneous code and code that is hard to read and debug. Although I'm a huge fan of strongly typed languages, there must also be a way to declare a "variant" type that only infer the type at initialization so that the type cannot change after it has been assigned, which makes "type inference" possible (For example the var keyword in C#).

Think about it February 3, 2006 by Christoff Truter

Thank you for your comment. When creating this class, my first and obvious design was to check existing class members, so yes i did think about it. The problem was that once you defined your class members, it fell outside the jurisdiction of the class get/set (don't know why PHP 5 behaves this way...) which we need to get this working, since I want to control everything that goes into and comes out of my class. So unfortunately I had to resort to doing it with an array, there will probably be a better way, this is a work in progress :) Assign all types to class members - yes thats the whole idea, and not being able to create new members not defined within the class is also correct, isn't it a bit dodgy doing that outside the class and inheritance in any case? There is quite a few pros in strongly typing (google it), mostly its supposed to help us to write better code, help enforce constraints on our classes, sooo when others use it, they cant assign crap to it. I think it all boils down to best practices and what we consider to be standards etc. Think about it - try a language like C# for a bit. Tell me what you think?

Not that great! February 2, 2006 by rudie

You'd seriously have to assign types to _all_ class members!! And you can't create any new members like this. It's a weird class. IF I'd use "strong typing", I wouldnt create the $enforcetype array, but just have the class check the type of the existing class members. That means you'd have to init all class members in your class. It means, though, that you can't set any class member to NULL, which sucks. I don't think this "strongly typed" stuff is that awesome!