Introduction

You've probably heard of "Magic Methods" if you've done anything at all with OOP in PHP. Most likely the __construct() method is invoked when initializing an instance of a class you've defined.

While __construct() is unofficially a magic method that is required to be defined when writing classes, __toString() is optional in every sense of the word and is often overlooked in favor of writing methods designed to be invoked for the sole reason of returning a human-readable string.

There's nothing wrong with doing that, but if you can get your objects to return a human-readable string without typing anything more than the $object reference instead of $object->method(), why not get it to do that?

The concepts in this tutorial apply to PHP version 5.2 or newer. Because of limitations in the context that PHP invoked the __toString magic method before PHP 5.2, the examples contained in this tutorial may not work in those older versions.

Examples of Usage

Let's compare an example using both common practice, and using __toString.

First, an example using common practice to load a CSV file and print it as an HTML <table>.

<?php
 
$data_table = new csv_html('file.csv');
echo '<h2>Data Table</h2>' . $data_table->html_table();
 
?>

Now let's look at that same example if __toString had been defined in place of the html_table() method.

<?php
 
$data_table = new csv_html('file.csv');
echo "<h2>Data Table</h2>$data_table";
 
?>

A more useful example might be anonymous instantiation, where no reference to the object is kept. This is useful where an object is a simple formatter and will likely never be manipulated after instantiation.

<?php
 
printf('<h2>Data Table</h2>%s', new csv_html('file.csv'));
 
?>

So How do I Implement __toString()?

Precisely the same way you define your __construct() method, and any of the other magic methods, with the exception of __autoload().
As a public method within your class definition.

Here's an example, albeit a crude one, of how the class in the CSV example might be written.

<?php
 
class csv_html
{
    public $filename, $csv;
    public function __construct($filename)
    {
        $this->filename = $filename;
        $this->csv = file_get_contents($filename);
        return $this;
    }
    public function __toString()
    {
        return sprintf(
            '<table><tr><td>%s</td></tr></table>',
            str_replace(array("\n", ','), array('</tr><tr>', '</td><td>'), $this->csv)
        );
    }
}
 
?>

Now you might ask, "Why not just have the constructor return the HTML?".
Because it would make what will become your parent class constructor useless if you ever tried to extend the class, that's why.

Conclusion

Give __toString() a try, you might like it.

This page was published on It was last revised on

Contributing Authors

0

6 Comments

  • Votes
  • Oldest
  • Latest
Commented
Updated

Ah yes and public constructors are generally regarded as evil if the class has any properties that need to be set, hence the Factroy Patterns 🙂

As for the toString(), I agreed, probably the most under rated, under used method on the planet.

I find using it (unless requirements dictate otherwise) provides a neat method for generating human readable identifiers for the said object.

The other nice thing is things like C# and Java invoke it automatically when bind the objects to UI objects for the UI's Text property.

Nice to see PHP supports it as well 🙂

add a comment
0
JO
184 4
Commented
Updated

I believe PHP will throw a fatal error if constructors are defined as anything other than public.

I'm not a big fan of a lot of the design patterns in use today, I cringe any time I read the word "factory". Most of it seems like it just over complicates things to me. 🙂

add a comment
0
Commented
Updated

I am a big fan of the patterns 🙂 Especially with runtimes like Java and .NET. Singletons and all tht jazz

add a comment
0
Commented
Updated

Just a quick follow up on public constructors

private function __construct(){}

hides the public constructor. No errors, PHP 5.4

add a comment
0
JO
184 4
Commented
Updated

Interesting. What use is a private constructor? 😕

add a comment
0
Commented
Updated

Prevents initiation using 'new'. You would need a static initialization method.

MyClass::create()
// instead of
new MyClass()

Makes code more readable if class needs to be initialized into a certain state

MyClass::createDefault()
MyClass::createWith($input)

//etc

Not a fan of parameterised constructors 🙂

add a comment
0