PHP: Accessors (Getters/Setters)

May 11, 2010 by PHP  

In languages like C# and VB.net one can define access (read/write) to class properties using accessors (get/set).

private string _name;
public string name
{
    get
    {
        return _name;
    }
    set
    {
        _name = value;
    }
}

If we were to exclude the set accessor completely, the property becomes read-only, excluding the get accessor (obviously leaving the set accessor intact) makes the property write-only.

But more about that later, in this post we're going to talk about adding this functionality to PHP 5.

A quick way to achieve this is to simply create/use methods to get/set access to a property:
private $name;

public get_name()
{
	return $this->name;
}

public set_name($value)
{
	$this->name = $value;
}

This personally doesn't feel like a very "natural" way to access fields - since this involves calling methods and not assigning properties, we can however make it more natural by using "magic methods".

In the following snippet we do exactly that (magic methods __get & __set) by defining a base class containing the functionality to make this work.
abstract class GetterSetter
{
	// Check for property accessibility
	protected function Accessible($name)
	{
		// Check for available accessors
		if ((method_exists($this, "set_$name")) || 
			(method_exists($this, "get_$name")))
			return true;
		
		// Inform dev why access to a field was denied
		throw new Exception((property_exists($this, $name) == false) 
					? "Property $name does not exist"
					: "Property $name not accessible");
	}
	
	public function __get($name) 
	{
		if ($this->Accessible($name))
		{
			// call get accessor
			if (method_exists($this, "get_$name"))
				return $this->{"get_$name"}();
			else
				throw new Exception("Writeonly Property $name");	
		}
	}
 
	public function __set($name, $value)
	{
		if ($this->Accessible($name))
		{
			// call set accessor (if available)
			if (method_exists($this, "set_$name"))
				$this->{"set_$name"}($value);
			else
				throw new Exception("Readonly Property $name");
		}
	}
}

The preceding snippet automatically calls the appropriate methods (accessors), when we read/write to the property/field. To use functionality, simply extend a class.
class person extends GetterSetter
{
	private $Age;
	private $Name;
	public $Note; // Not processed by magic get/set methods - since its public.
	
	public function __construct($Name)
	{
		$this->Name = $Name;
	}
 
	protected function get_Age()
	{
		return $this->Age;
	}
 
	protected function set_Age($value)
	{
		if ($value < 18)
			throw new Exception('Invalid age specified');
		$this->Age = $value;
	}
 
	protected function get_Name()
	{
		return $this->Name;
	}
}

Usage:
$a = new person('Jack');
//$a->Age = 10; // Throws Exception
//$a->Age = 19; // Sets the field
//$a->Name = "Ben"; // Throws ReadOnly exception
//$a->test = 10; // Throws Exception since the field is undefined.

This ultimately provides a mechanism by which we can set constraints on class properties, e.g. field must be of certain type (int/string/bool etc), field must be in certain format (e.g. email)


Leave a Comment


Mr. September 24, 2011 by Buddy

Thanks for this thorough explanation. I am new to PHP. When I came to the topic of properties, I wondered why different books are giving different approach on accessors. I noticed it is not the same with C#. My current references don't tell much. With your concise discussion, I understood why. I hope you could also point me to PHP books that are in your arsenal so I could add it to my library. Thanks and may you achieve your dream to migrate to the states. Godbless.