PDA

Click to See Complete Forum and Search --> : [RESOLVED] Issue with Access to Private Static Method


tomcatexodus
Apr 8th, 2010, 09:25 PM
I'm working on a simple Template class (Mucklate) and I'm having a visibility problem with one of the methods. How can I allow the anonymous callback function for ob_start to access the parseTemplate method if I make the parseTemplate private static? I would rather it be invisible outside the class. Any other way I can achieve this?

(This isn't the whole class, and it's still in progress, so if it looks odd, that's why.)
public function __construct($templatePath, $stripWhitespace = false){

if($templatePath && file_exists($templatePath)){

ob_start(function($buffer){ return Mucklate::parseTemplate($buffer); });

include($templatePath);

}

}

public static function parseTemplate($buffer){

foreach(Mucklate::$varSet as $var){

$buffer = str_replace(Mucklate::$delimiter . $var["var"] . strrev(Mucklate::$delimiter), $var["value"], $buffer);

}

return $buffer;

}

kows
Apr 9th, 2010, 06:37 PM
after much digging and experimenting, I don't think you can. but, ob_start() doesn't take a function as a parameter in the first place -- it takes a function's name. you'd need to specify the class (for static)/object (for non-static) and method in an array if you want to use a method for ob_start():
//static methods:
ob_start(array('MyClass', 'parseTemplate'));

//non-static methods:
ob_start(array($this, 'parseTemplate'));
however, as far as I can figure out, there's no way to provide a private method as the callback function for ob_start(). for example, this class works as expected:
<?php
class Test {

public function __construct(){
if(ob_start(array('Test', 'parseTemplate'))){
echo "assigned output buffer";
}else{
echo "couldn't assign output buffer";
}
}

public static function parseTemplate($buffer){
return __CLASS__ . $buffer;
}

}

$t = new Test();
?>
the output is:
Testassigned output buffer
however, once the access modifier for parseTemplate() is changed to private (static or non-static), the script simply dies.

I don't know of any workaround for this.

tomcatexodus
Apr 10th, 2010, 11:26 PM
however, once the access modifier for parseTemplate() is changed to private (static or non-static), the script simply dies.


It is strange the way it dies too. Perhaps because of the output buffering, but I don't even get a error returned regarding the visibility issue. Unfortunate too though.

visualAd
Apr 11th, 2010, 01:56 PM
It is strange the way it dies too. Perhaps because of the output buffering, but I don't even get a error returned regarding the visibility issue. Unfortunate too though.
You will get an error, if you send the errors to an error log. It will occur on line zero in unknown :)

I remember back in the early days of v5, visibility was very inconsistent. But it is worth noting that the call to the output buffer callback occurs outside the scope of the class so I would not have expected it to work. If it is really necessary, you can use reflection to verify the method which called the function, but is it worth it?

penagate
Apr 13th, 2010, 02:32 AM
The general problem is that PHP doesn't have proper function pointers. Your private method is being called by name and so the scope resolution occurs from the foreign class. In other languages you can pass a function pointer which can be called from anywhere regardless of whether or not its target is visible from the point where it is called.

An alternative approach to this specific case is to parse the buffer in the destructor of the template class, rather than using a callback.

<?php
class TestParser
{
public function __construct()
{
ob_start();
}

public function __destruct()
{
$data = ob_get_contents();
ob_clean();

$data = strrev($data); // do your parsing here
echo $data;

ob_end_flush();
}
}

$parser = new TestParser();

?>Hello world, foo bar baz and all that

This approach allows you to make your parsing function private.