Welcome to the second article in my series on object-oriented PHP programming. In the first article, we looked at the basics of OOP in PHP — including the concepts of classes, objects, properties and methods — and we saw how to create basic classes and objects in PHP.
In this article, you’re going to delve a bit deeper into properties and methods in PHP. This will give you a solid grounding when it comes to using objects in PHP, before we move on to more advanced topics such as inheritance in later articles.
These are the concepts you’ll explore in this article:
- Constructors and destructors, which let your objects do specific things whenever they’re created or deleted
- Static properties and methods, for creating class properties and methods that are not tied to specific objects
- Class constants, which are handy for storing fixed values related to a class
- Type hinting, for restricting the types of objects that can be passed to a method
- The
__get()
and__set()
magic methods for overloading property accesses - The
__call()
magic method for overloading method calls
All set to delve deeper into properties and methods? Great! Let’s go!
Constructors and destructors
When you create a new object, there are sometimes things that are good to do at the same time. For example, you might want to set some or all of the object’s properties to initial values, or you might want to load the object’s data automatically from a database table.
Likewise, when an object is removed from memory, you might want to do things like removing dependent objects, closing files, or closing database connections.
How do you remove an object?
PHP automatically removes an object from memory when there are no more variables left that reference the object. For example, if you create a new object and store it in a variable called $myObject
, and then remove the variable by calling unset($myObject)
, the object is also removed from memory. Similarly, if you create $myObject
as a local variable in a function, the variable — and therefore the object — are removed when the function exits.
PHP gives you 2 special methods that you can use to automatically do stuff when an object is created or removed:
- An object’s constructor is called automatically just after the object is created.
- An object’s destructor is called automatically just before the object is removed.
Working with constructors

Use a constructor whenever you want to initialize stuff when an object is created. This might include setting properties, opening files, and reading data.
To create a constructor method, simply add a method with the name __construct()
to your class (that’s 2 underscores before the word “construct”). PHP then automatically calls this method when an object based on the class is created.
Here’s an example of a constructor:
class MyClass { public function __construct() { echo "I've just been created!"; } } $myObject = new MyClass(); // Displays "I've just been created!"
MyClass
contains a simple constructor that displays a message using echo
. The last line of code in the script creates a new object based on MyClass
. When this happens, PHP automatically calls the constructor, displaying the message.
Here’s a somewhat more practical use of a constructor — initializing properties:
class Member { private $username; private $location; private $homepage; public function __construct( $username, $location, $homepage ) { $this->username = $username; $this->location = $location; $this->homepage = $homepage; } public function showProfile() { echo "<dl>"; echo "<dt>Username:</dt><dd>$this->username</dd>"; echo "<dt>Location:</dt><dd>$this->location</dd>"; echo "<dt>Homepage:</dt><dd>$this->homepage</dd>"; echo "</dl>"; } } $aMember = new Member( "fred", "Chicago", "http://example.com/" ); $aMember->showProfile();
When you run the above script, it displays the following:
Username: fred Location: Chicago Homepage: http://example.com/
Our Member
class contains 3 private properties, and a constructor that accepts 3 arguments — one for each property. The constructor sets the object’s properties to the argument values. The class also contains a showProfile()
method that displays the property values using echo
.
The script then creates a new Member
object, passing 3 values — “fred”, “Chicago”, and “http://example.com/” — to the constructor as it does so. The constructor stores the values in the new object’s properties. Finally, the script calls the object’s showProfile()
method to display the stored values.
Working with destructors

Use a destructor to clean things up when an object is deleted. You might need to save the object to a database, or close open files related to the object.
To create a destructor, add a method called __destruct()
to your class. The destructor is called automatically just before the object is deleted. Here’s a simple example:
class MyClass { public function __destruct() { echo "I'm about to disappear - bye bye!"; // (Clean things up here) } } $myObject = new MyClass(); unset( $myObject ); // Displays "I'm about to disappear - bye bye!"
Here, we’ve created a simple destructor that displays a message. We then create a new object from our class, then immediately delete the object by unsetting the variable that points to the object. Just before the object is deleted, PHP calls the destructor, which displays the message in the page.
Unlike constructors, you can’t pass arguments to a destructor.
Destructors are also called just before the script exits, since all objects (and other variables) are deleted when the script stops running. So this code also triggers the destructor:
class MyClass { public function __destruct() { echo "I'm about to disappear - bye bye!"; // (Clean things up here) } } $myObject = new MyClass(); exit; // Displays "I'm about to disappear - bye bye!"
Similarly, if the script stops running due to an error then any destructors will also be called.
When objects of a child class are created, its parent class’s constructor isn’t automatically called. Only the child’s constructor is called. However, you can explicitly call the parent class’s constructor from within the child’s constructor by writing parent::__construct()
. The same is true of destructors — you can call the destructor explicitly using parent:__destruct()
. We’ll look at parent and child classes in the next tutorial on inheritance.
Static properties
We looked at static function variables in PHP Variable Scope: All You Need to Know. Like a regular local variable, a static variable can only be accessed from within a function. However, unlike a local variable, a static variable retains its value between function calls.
Static properties work in a similar way. A static property is tied to its class, but it retains its value for the lifetime of the script. Compare this to a regular property, which is tied to a particular object, and which disappears when the object is deleted.
Static properties are useful in situations where you want to store a persistent value that is related to a class, but not to specific objects. They’re a bit like global variables for classes.
To create a static property, just add the keyword static
before the property name:
class MyClass { public static $myProperty; }
Here’s an example that shows how static properties work:
class Member { private $username; public static $numMembers = 0; public function __construct( $username ) { $this->username = $username; self::$numMembers++; } } echo Member::$numMembers . "<br>"; // Displays "0" $aMember = new Member( "fred" ); echo Member::$numMembers . "<br>"; // Displays "1" $anotherMember = new Member( "mary" ); echo Member::$numMembers . "<br>"; // Displays "2"
There are a few interesting things going on here, so let’s work through the script:
- Our
Member
class contains 2 properties: a private$username
property, and a static$numMembers
property, which is initially set to zero. - The constructor takes a
$username
argument and sets the newly-created object’s $username property to this value. At the same time, it increments the$numMembers
static property to record the fact that we now have one more member.Notice that the constructor refers to the static$numMembers
property usingself::$numMembers
.self
is similar to the$this
keyword that we saw in the last tutorial. Whereas$this
refers to the current object,self
refers to the current class. Similarly, whereas you use->
to access properties and methods of a specific object, you use::
to refer to properties and methods of a class. - Finally, the script creates a couple of new
Member
objects, displaying the value of the$numMembers
static property as it goes. Notice that the property retains its value throughout the lifetime of the script, independent of the objects derived from the class.Again, the script uses the::
operator to access the static property. We can’t useself
here because the code is outside the class, so instead we write the class name, followed by::
, followed by the property name (Member::$numMembers
). (We could also have usedMember
instead ofself
inside the constructor, if we’d wanted to.)
It’s worth noting that our script accessed the $numMembers
static property before it created its first Member
object. You don’t need to create objects to access static properties of a class.
Static methods
As well as static properties, you can also create static methods. As with static properties, a static method is tied to a class, but you don’t need to create an object from the class in order to call the static method. This makes static methods useful when you want to create a method that doesn’t need to work with actual objects.
To create a static method, just use — you guessed it — the static
keyword:
class MyClass { public static function myMethod() { // (do stuff) } }
Our static property example earlier used a public static $numMembers
property. It’s good practice to make properties private, and write public methods to access them instead. So let’s modify the example to make the $numMembers
property private, and add a public static method to retrieve the property’s value:
class Member { private $username; private static $numMembers = 0; public function __construct( $username ) { $this->username = $username; self::$numMembers++; } public static function getNumMembers() { return self::$numMembers; } } echo Member::getNumMembers() . "<br>"; // Displays "0" $aMember = new Member( "fred" ); echo Member::getNumMembers() . "<br>"; // Displays "1" $anotherMember = new Member( "mary" ); echo Member::getNumMembers() . "<br>"; // Displays "2"
Here, we’ve created a static method called getNumMembers()
that returns the value of the $numMembers
static property. We’ve also made $numMembers
private so that the calling code can’t access the property directly.
We then changed our calling code to retrieve the value of $numMembers
by calling the getNumMembers()
static method. Notice that the code can call the method without needing to create an object first, because the method is static.
Class constants

We looked at regular constants in an earlier tutorial. A constant lets you define a global fixed value within your code; the constant’s value remains fixed throughout the running of the script, and can’t be changed.
Class constants are similar to regular constants. The main difference is that, rather than being global, a class constant is accessed through the class that defined it. Class constants are useful for storing fixed values or settings that are related to a specific class.
You define a class constant by using the const
keyword, like this:
class MyClass {
const CONSTANT_NAME = value;
}
You can then access the constant using the class name and the ::
operator, much like static properties:
MyClass::CONSTANT_NAME
As with static properties and methods, you can also access a class constant from within a method of the same class method by using the self
keyword.
Let’s try out class constants with an example. We’ll add some constants to our Member
class to define some numeric values that represent a member’s privilege level (member, moderator, or administrator). By using constants instead of the numeric values in the code, we make the code easier to read. Here’s the script:
class Member { const MEMBER = 1; const MODERATOR = 2; const ADMINISTRATOR = 3; private $username; private $level; public function __construct( $username, $level ) { $this->username = $username; $this->level = $level; } public function getUsername() { return $this->username; } public function getLevel() { if ( $this->level == self::MEMBER ) return "a member"; if ( $this->level == self::MODERATOR ) return "a moderator"; if ( $this->level == self::ADMINISTRATOR ) return "an administrator"; return "unknown"; } } $aMember = new Member( "fred", Member::MEMBER ); $anotherMember = new Member( "mary", Member::ADMINISTRATOR ); echo $aMember->getUsername() . " is " . $aMember->getLevel() . "<br>"; // Displays "fred is a member" echo $anotherMember->getUsername() . " is " . $anotherMember->getLevel() . "<br>"; // Displays "mary is an administrator"
Here we’ve created 3 class constants — MEMBER
, MODERATOR
, and ADMINISTRATOR
— and given them values of 1, 2, and 3 respectively. Next we’ve added a $level
property to store each member’s privilege level, and modified the constructor to initialize the $level
property. Our class also includes a getLevel()
method that returns an appropriate message depending on the member’s privilege level. It compares $level
against the 3 class constants to determine which string to return.
The script itself creates a couple of Member
objects using different privilege levels. Again, it uses the class constants to represent the levels, rather than using the raw numeric values. The script then calls each member’s getUsername()
and getLevel()
methods, and displays the results in the page.
Checking method arguments with hints

PHP is a loosely-typed language, which means it’s not too fussy about the types of data that you pass around a script. For example, you can happily pass a numeric value to PHP’s strlen()
function for calculating the length of a string. PHP first converts the number into the string, then returns its length:
echo strlen( 123 ); // Displays "3"
Often this implicit data type conversion is quite convenient, but it can lead to bugs that are hard to track down, especially when you work with more complex data types such as objects.
An example scenario
Consider this example:
class Member { private $username; public function __construct( $username ) { $this->username = $username; } public function getUsername() { return $this->username; } } class Topic { private $member; private $subject; public function __construct( $member, $subject ) { $this->member = $member; $this->subject = $subject; } public function getUsername() { return $this->member->getUsername(); } } $aMember = new Member( "fred" ); $aTopic = new Topic( $aMember, "Hello everybody!" ); echo $aTopic->getUsername(); // Displays "fred"
This script works as follows:
- We create our usual
Member
class, with a$username
property, a constructor, and agetUsername()
method. - We also create a
Topic
class to hold forum topics. It has 2 properties:$member
and$subject
.$member
will hold aMember
object representing the member that created the topic.$subject
will hold the topic subject. - The
Topic
class also has a constructor that accepts aMember
object — the member that created the topic — and a subject string. It stores theMember
object and subject string in theTopic
object’s properties. The class also has agetUsername()
method to return the username of the member that created the topic. It does this by calling itsMember
object’sgetUsername()
method. - You can see this working towards the end of the script. We create a new
Member
object with a username of “fred”. Then we create a newTopic
object, passing in the “fred”Member
object and “Hello everybody!” as the subject. Finally, we call the topic’sgetUsername()
method to retrieve the topic creator’s username, and display the return value (“fred”).
So far so good.
Let’s break things!
Now we’ll add the following code to the end of the script:
class Widget { private $colour; public function __construct( $colour ) { $this->colour = $colour; } public function getColour() { return $this->colour; } } $aWidget = new Widget( "blue" ); $anotherTopic = new Topic( $aWidget, "Oops!" ); // Displays "Fatal error: Call to undefined method Widget::getUsername()" echo $anotherTopic->getUsername();
Here, we add an unrelated Widget
class, with a $colour
property, a constructor, and a getColour(
) method to retrieve the widget’s colour.
Then, at the end of our script, we create a new Widget
object, followed by a new Topic
object, passing in the Widget
object as the topic’s “author”, instead of a Member
object as expected.
Finally, we attempt to display the username of the topic’s creator by calling the Topic
object’s getUsername()
method. This method in turn attempts to call the getUsername()
method of the Widget
object. Since the Widget
object doesn’t contain a getUsername()
method, we get this error:
Fatal error: Call to undefined method Widget::getUsername()
The problem here is that the cause of the error is not immediately obvious. Why is the Topic
object trying to call Widget::getUsername()
? In complex classes this sort of problem can be hard to track down.
Type hinting to the rescue
It would be better if we could ensure that the Topic
class’s constructor only accepts Member
objects in the first place, thereby avoiding potential problems further down the line.
This is exactly what type hinting does. To use it, you put the name of the class that a method should accept before the parameter name in the method definition:
function myMethod( ClassName $object ) {
// (do stuff)
}
Let’s modify our Topic
constructor so that it will only accept Member
objects:
class Topic { private $member; private $subject; public function __construct( Member $member, $subject ) { $this->member = $member; $this->subject = $subject; } public function getUsername() { return $this->member->getUsername(); } }
Now let’s try again to create a Topic
object using our Widget
object as the topic “author”:
$aWidget = new Widget( "blue" ); $anotherTopic = new Topic( $aWidget, "Oops!" );
This time, PHP immediately raises the following error:
Catchable fatal error: Argument 1 passed to Topic::__construct() must be an instance of Member, instance of Widget given, called in script.php on line 55 and defined in script.php on line 24
This error is much more useful, because it shows you exactly what the problem is — we tried to pass a Widget
object to a method that expected a Member
object. It even tells you the exact place in the script where the method was called, and also the place where the method is defined. This makes debugging the script so much easier.
Overloading properties with __get()
and __set()

As you know, classes usually contain properties, like this:
class MyClass { public $aProperty; public $anotherProperty; }
If your class properties are public then your calling code can read and set them using the ->
operator:
$myObject = new MyClass; $myObject->aProperty = "hello";
However, PHP also lets you create “virtual” properties that don’t actually exist in the class, but can still be accessed using the ->
operator. This can be useful in certain situations, such as:
- You have a lot of properties and you want to store them in an array, instead of having to declare each property individually
- You want to store a property somewhere outside of an object, such as in another object, or even in a file or database table
- You want to calculate property values on-the-fly, rather than storing them somewhere
To create these “virtual” properties, you add a couple of PHP magic methods to your class:
__get( $propName )
- Called automatically when something attempts to read
$propName
, an invisible property of the object __set( $propName, $propValue )
- Called automatically when something attempts to set
$propName
, an invisible property of the object, to a value,$propValue
“Invisible” in this context means that the property isn’t accessible to the code that tries to use it. This can mean that the property doesn’t exist in the class at all, or that the property exists but the code isn’t allowed to access it — for example, the property is private, and code outside the class is trying to read it.
Let’s try this out. We’ll modify our Member
class so that, in addition to the predefined $username
property, it can accept additional arbitrary properties, which it stores in a $data
array:
class Member { private $username; private $data = array(); public function __get( $property ) { if ( $property == "username" ) { return $this->username; } else { if ( array_key_exists( $property, $this->data ) ) { return $this->data[$property]; } else { return null; } } } public function __set( $property, $value ) { if ( $property == "username" ) { $this->username = $value; } else { $this->data[$property] = $value; } } } $aMember = new Member(); $aMember->username = "fred"; $aMember->location = "San Francisco"; echo $aMember->username . "<br>"; // Displays "fred" echo $aMember->location . "<br>"; // Displays "San Francisco"
Here’s how this code works:
- Our
Member
class contains a regular private$username
property, and it also has a private$data
array to hold additional “virtual” properties. - The
__get()
method takes a single argument,$property
, which is the name of the property to retrieve. If$property
is"username"
then the method returns the value of the$username
private property. Otherwise, it checks to see if the property name appears as a key in the$data
array. If it does then it returns the element’s value; otherwise, it returnsnull
. - The
__set()
method takes 2 arguments:$property
, the name of the property to set, and$value
, the value to set the property to. If$property
is"username"
, the method sets the$username
property to the value stored in$value
. Otherwise, it sets the element in the$data
array that has a key of$property
to the value stored in$value
. - Once we’ve created our
Member
class, we create a newMember
object and set its$username
property to"fred"
. This triggers the__set()
method, which sets the actual$username
property in the object. We then set the object’s$location
property to"San Francisco"
. Since this property doesn’t exist in the object,__set()
stores it in the$data
array instead. - Finally, we retrieve the values of the
$username
and$location
properties and display them.__get()
retrieves the$username
value from the actual$username
property, and the$location
value from the"location"
element in the$data
array.
As you can see, by using __get()
and __set()
we’ve created a class that can hold both a regular $username
property, and also any arbitrary property that the calling code wants to set. The calling code doesn’t need to know whether each property really exists in the object or not. It just sets and reads the property using the ->
operator.
The example also shows how you can use __get()
and __set()
to easily create so-called “getter” and “setter” methods to access private properties. We didn’t need to write separate getUsername()
and setUsername()
methods to access the private $username
property. Instead, we used __get()
and __set()
to manipulate $username
. This approach means you only have to write 2 methods in total, instead of 2 methods for each private property.
A note on encapsulation
Using private properties, combined with getter and setter methods, is generally a better approach than using public properties.
Getter and setter methods can do things to the data going in and out of the object, such as checking that the data is in the right format, or converting the data to a different format.
Getters and setters also hide the details of how each property is implemented, which makes it easier to rewrite the innards of a class at a later date without affecting the code that uses the class. For example, you might later decide to store a particular property directly in a database table, instead of in an object’s property. Provided the property is accessed only through getter and setter methods, all you have to do is rewrite those methods. The calling code doesn’t need to be changed.
This technique is called encapsulation, and it’s one of the main advantages of object-oriented programming.
Overloading methods with __call()
As well as providing __get()
and __set()
to intercept property accesses, PHP gives you another magic method, __call()
, that you can use to intercept method calls. Whenever some code tries to call a method in your class that either doesn’t exist, or that it’s not allowed to call, PHP automatically calls your __call()
method instead.
Here’s the general syntax of the __call()
method:
public function __call( $methodName, $arguments ) {
// (do stuff)
}
When an attempt is made to call an invisible method in your class, PHP calls your __call()
method, passing in the name of the method that was called as a string, and a list of any arguments supplied as an array. Your __call()
method should then handle the call appropriately, optionally returning a value to the calling code.
__call()
can be useful for situations where you want to hand off some parts of your class’s functionality to another class. Here’s a simple example:
class Member { private $username; public function __construct( $username ) { $this->username = $username; } public function getUsername() { return $this->username; } } class Topic { private $member; private $subject; public function __construct( $member, $subject ) { $this->member = $member; $this->subject = $subject; } public function getSubject() { return $this->subject; } public function __call( $method, $arguments ) { return $this->member->$method( $arguments ); } } $aMember = new Member( "fred" ); $aTopic = new Topic( $aMember, "Hello everybody!" ); echo $aTopic->getSubject() . "<br>"; // Displays "Hello everybody!" echo $aTopic->getUsername() . "<br>"; // Displays "fred"
This is based on the type hinting example from earlier in the article. We have a Member
class with a $username
property, and a Topic
class that can hold a Member
object (the topic author) and a subject. The Member
class contains a getSubject()
method to retrieve the topic subject, but it doesn’t explicitly have a method to retrieve the author’s username. Instead, it contains a __call()
method that traps any call to a nonexistent method, and passes the call off to the Member
object to handle.
When the script then tries to call $aTopic->getUsername()
, PHP realizes that this method doesn’t exist in the Topic
class. So it calls __call()
instead, which in turn calls the Member
object’s method of the same name (getUsername()
). That method returns the member’s username to __call()
, which in turn returns the username to the calling code.
PHP features some other methods related to overloading that you might find useful, including __isset()
, __unset()
, and __callStatic()
. Find out more.
Summary
In this tutorial you’ve taken your object-oriented PHP skills further as you’ve explored properties and methods in depth. You’ve looked at:
- Constructors and destructors, which are useful for initializing and cleaning up objects
- Static properties and methods, which you can use to create properties and methods that work at the class level, rather than the object level
- Class constants, that are handy for storing class-related configuration settings and fixed values
- Type hinting, which limits the type of objects that can be passed to a method — this can make your code easier to debug, and
- The
__get()
,__set()
, and__call()
magic methods for intercepting property accesses and method calls. These let you create “virtual” properties and methods that don’t exist in a class, but can still be accessed by code that uses the class.
Armed with the knowledge in this tutorial, and the previous one, you’re now ready to start writing fairly complex object-oriented code in PHP. But it doesn’t end there! In the next tutorial in the series, we dive into one of the truly powerful aspects of OOP: the ability of one class to inherit behaviours from another class.
Happy coding!
Thank you for this tutorial.
I’ve avoided teaching myself PHP objects/classes for several years now, but find myself with a very appropriate use for them at this point. Your tutorial is laid out nicely, starting with basics and progressing appropriately, providing good explanations of each additional aspect!
Paul
@TunerGeek: Thanks very much for your feedback! It’s great to know that people are finding these tutorials helpful. 🙂
Cheers,
Matt
Matt, i’ve very appreciative that you put time and effort in making very simplistic tutorials on the web. There are about 2 tutorials I’ve read and both arent at as smooth as yours.
I’m a new (trying to be) php dev that really needs great resources like these to fast track me to a dev position.
Really glad I stumbled upon your tutorials. Keep up the fantastic work.
THANKS!
@xarejay28x: Thanks for the kind words 🙂 Good luck with your PHP coding!
Actually, I was avoiding to read what are magic methods are but now I’ve got a full understanding of magic method because of your article.
Thanks.
Hello . I think you have a fail in the last lines where you write:
The Member class contains a getSubject() method to retrieve the topic subject, but it doesn’t explicitly have a method to retrieve the author’s username. Instead, it contains a __call() method that traps any call to a nonexistent method, and passes the call off to the Member object to handle.
should be
The Topic class
Thanks a lot for your supernices tutorials 🙂
A “fail”???
What you mean is an error
Important note for the Americans:
One cannot “have” a fail!
you CAN have a failure or you can fail at something
Hi,
Thank you for the articles, very usefull.
Hoewevr I have a problem: starting from class Member I do not see anyting on the screen.
I use a provider that has the 4.2 php version.
Is this the cuase of the problem?
Thanks.
Regards.
Raf
@raf: I would recommend PHP5. Check your server’s error log to find the exact problem.