Method Overloading

admin

Administrator
Staff member
I am trying to overload the __toString method to print a slightly different output from what the SplFileObject class normally prints.

Unfortunately it isn't working.

Here is all of the code for my program:


class ProjectDirectory extends DirectoryIterator {
public function __construct($path) {
parent::__construct($path);
}

public function current() {
$thisFile = parent::current()->__toString();
return new ProjectFile( $thisFile );
}
}

class ProjectFile extends SplFileInfo {
public $fileName;

public function __construct( $fileName ) {
$this->fileName = $fileName;
parent::__construct( $fileName );
}

// fails
function __toString() {
$fileToString = "<a href='http://www.phpbuilder.com/board/archive/index.php/$href_path/". $this->fileName ."'>". $this->fileName ."<a/> [". $this->get_md5() ."]<br />";
return $fileToString;
}

// overloaded but works
public function isWritable() {
return "no writing allowed";
}

// new and works
public function get_md5() {
return md5( file_get_contents( $this->fileName ));
}
}

$directories = "";
$files = "";

$thisDir = new ProjectDirectory( "./" );
foreach ( $thisDir as $thisFile ) {
if ( $thisFile->isDir() ) {
$directories .= $thisFile;
}
else {
$files .= $thisFile ."<br />";
}
}


I have written numerous scripts to test that the __toString method will overload and time and time again was proven successful.

Take this code for example:

class a1 {
public function __toString() {
return "a1";
}
}

class a2 extends a1 {
public function a() {
return new a3();
}
public function __toString() {
return "a2";
}
}

class a3 extends a1 {
public function __toString() {
return "a3";
}
}


$a1 = new a1();
echo $a1 ."<br />";

$a2 = new a2();
echo $a2 ."<br />";

$b = $a2->a();
echo $b ."<br />";



it works just fine and outputs:
a1
a2
a3

Does anybody know what is wrong with the above code?I take it nobody knows.
Where would be a good place to get an answer for this?http://www.php.net/manual/en/language.oop5.magic.php#language.oop5.magic.tostring
It is worth noting that before PHP 5.2.0 the __toString method was only called when it was directly combined with echo() or print().I am running php 5.2
The code in the second example would not have worked in previous to 5.2 versions.Okay; I see what you mean, now (incidentally, $href_path is undefined - you'll be needing to supply the ProjectFile object with the path to the file as well as the name, or file_get_contents() won't find it).

Calling __toString() explicitly does work, but that's pre-5.2 behaviour. Definitely something dodgy going on here.

Yes; very dodgy - the ProjectFile's __toString() method works until you extend SplFileInfo. As soon as you do that, it stops being called (and I guess the SplFileInfo's method is called instead). Not behaviour I'd expect.

I'm beat; perhaps bugs.php.net needs a new report filed. Does this happen with other classes that inherit from the SPL?Thanks for the confirmation, it is nice to know that it isn't me just being crazy.
I haven't tried the toString method on any of the other spl objects so I gave it a try by simply adding it to the ProjectDirectory objec in the first example.


class ProjectDirectory extends DirectoryIterator {
public function __construct($path) {
parent::__construct($path);
}

public function current() {
$thisFile = parent::current()->__toString();
return new ProjectFile( $thisFile );
}

public function __toString() {
return "This is the project directory";
}
}

class ProjectFile extends SplFileInfo {
public $fileName;

public function __construct( $fileName ) {
$this->fileName = $fileName;
parent::__construct( $fileName );
}

// fails
function __toString() {
$fileToString = "<a href='http://www.phpbuilder.com/board/archive/index.php/$hrefPath". $this->fileName ."'>". $this->fileName ."<a/> [". $this->get_md5() ."]<br />";
return $fileToString;
}

// overloaded but works
public function isWritable() {
return "no writing allowed";
}

// new and works
public function get_md5() {
return md5( file_get_contents( $this->fileName ));
}
}

$directories = "";
$files = "";

$thisDir = new ProjectDirectory( "./" );
echo $thisDir ."<br />";

foreach ( $thisDir as $thisFile ) {
if ( $thisFile->isDir() ) {
$directories .= $thisFile;
}
else {
$files .= $thisFile ."<br />";
}
}


Its output:


.
Files
This is the project directory
This is the project directory
This is the project directory
This is the project directory
This is the project directory


The period would be the current directory, and the This is the project directory is for every single file in that directory.

Just to keep me sane, I changed:


$files .= $thisFile ."<br />";

to
$files .= get_class($thisFile) ." - ". $thisFile ."<br />";

and the output.

ProjectFile - This is the project directory
ProjectFile - This is the project directory
ProjectFile - This is the project directory
ProjectFile - This is the project directory
ProjectFile - This is the project directory


:eek: ProjectFile is the object type, yet it is calling the ProjectDirectory's __toString method? :confused:
This is most definitely not the output I am expecting.
 
Back
Top