PHP ob_start: callback a static method with $this - php

With PHP's ob_start($callback), you can pass a static method as a callback like this:
class TemplateRenderer {
function myCallback($bufferContents) {
return 'Foobar instead of the buffer';
}
}
ob_start(array('TemplateRenderer', 'myCallback'));
Or you can refer to an object like this:
$myTemplateRenderer = new TemplateRenderer();
ob_start(array($myTemplateRenderer, 'myCallback'));
Both of these work, but I'd like to know if I can start the output buffer from within a class method, and refer to the callback using $this
class TemplateRenderer {
function myCallback($bufferContents) {
return 'Foobar instead of the buffer';
}
function init() {
// --- this doesn't work ----
ob_start(array($this, 'myCallback'));
// --- this doesn't work either ----
ob_start(array('this', 'myCallback'));
}
}
TemplateRenderer::init();
If it's even possible, what's the syntax for referring to a "callable" from within its own class?

I would follow Barmar's suggestion, but if you for whatever reason don't want to make instantiation, you can try this solution:
class TemplateRenderer {
static function myCallback($bufferContents) {
return 'Foobar instead of the buffer';
}
function init() {
ob_start(array('self', 'myCallback'));
}
}
TemplateRenderer::init();

You need to call init() using an object so that $this will be set.
$myTemplateRenderer = new TemplateRenderer();
$myTemplateRenderer->init();

Related

Call static function from variable

I have the following setup:
class test {
public static function something() {
$somethingElseFunction = "somethingElse";
// How can I call the method with the name saved in variable?
}
public static function somethingElse($a) {
echo 'bla';
}
}
How can I call the function using the variable? (the function name is in variable).
Also I need to do a function_exists() for it.
Tried this:
if (function_exists(self::$somethingElseFunction ())) {
if (!call_user_func(self::$somethingElseFunction , $a)) {
}
}
Didn't work.
In PHP>=5.4 you can use just self:: de-reference:
self::$somethingElseFunction();
-but in earlier versions that will cause error (because it wasn't allowed to use dynamic static methods de-reference). So then you can always use such things as call_user_func_array() :
class test {
public static function something() {
$somethingElseFunction = "somethingElse";
call_user_func_array(array(__CLASS__, $somethingElseFunction), array("bla"));
}
public static function somethingElse($a) {
var_dump($a);
}
}
test::something();
-this will work for PHP>=5.0
About function_exists() call - it expects string as parameter, thus I recommend to use method_exists() - because that function is intended to do the stuff:
public static function something() {
$somethingElseFunction = "somethingElse";
if(method_exists(__CLASS__, $somethingElseFunction))
{
call_user_func_array(array(__CLASS__, $somethingElseFunction), array("bla"));
}
}
You should be able to use the following:
test::$somethingElseFunction();
Use this function:
$classname = 'somethingElse';
call_user_func('test::' . $classname, $params);

How to Pass a function to a class in php

I have a class that generates data based on a few things. I would like to format that data from the outside. So I am trying to pass a function into the class so that it would format that data. I have looked at many examples, but it seems this is unique.
Can anybody give an idea of how to do this? The following code gives an error.
<?php
class someClass {
var $outsideFunc; // placeholder for function to be defined from outside
var $somevar='Me'; // generated text
function echoarg($abc){
$outsideFunc=$this->outsideFunc; // bring the outside function in
call_user_func($outsideFunc,$abc); // execute outside function on text
echo $abc;
}
}
function outsidefunc($param){ // define custom function
$param='I am '.$param;
}
$someClass=new someClass();
$someClass -> outsideFunc = 'outsideFunc'; // send custom function into Class
$someClass -> echoarg($someClass->somevar);
$someClass -> outsidefunc = 'outsidefunc';
In PHP, function names are not case sensitive, yet object property names are. You need $someClass->outsideFunc, not $someClass->outsidefunc.
Note that good OOP design practice calls for the use of getter and setter methods rather than just accessing properties directly from outside code. Also note that PHP 5.3 introduced support for anonymous functions.
Yeah. You are right. Now there is no error. But it does not work either.
By default, PHP does not pass arguments by reference; outsidefunc() does not actually do anything useful. If you want it to set $param in the caller to something else, and do not want to just return the new value, you could change the function signature to look like this:
function outsidefunc(&$param) {
You would also need to change the way you call the function, as call_user_func() does not allow you to pass arguments by reference. Either of these ways should work:
$outsideFunc($abc);
call_user_func_array($outsideFunc, array(&$abc));
Why not pass your function as an argument?
<?php
class someClass {
public $somevar="Me";
public function echoarg($abc,$cb=null) {
if( $cb) $cb($abc);
echo $abc;
}
}
$someClass = new someClass();
$someClass->echoarg($someClass->somevar,function(&$a) {$a = "I am ".$a;});
i am not sure what exactly you are looking for, but what i get is, you want to pass object in a function which can be acheive by
Type Hinting in PHP.
class MyClass {
public $var = 'Hello World';
}
function myFunction(MyClass $foo) {
echo $foo->var;
}
$myclass = new MyClass;
myFunction($myclass);
OP, perhaps closures are what you're looking for?
It doesn't do EXACTLY what you're looking for (actually add function to class), but can be added to a class variable and executed like any normal anonymous function.
$myClass->addFunc(function($arg) { return 'test: ' . $arg });
$myClass->execFunc(0);
class myClass {
protected $funcs;
public function addFunc(closure $func) {
$this->funcs[] = $func;
}
public function execFunc($index) { $this->funcs[$index](); } // obviously, do some checking here first.
}

Is it possible to determine whether a method was called from inside or outside of a class?

Example code:
class MyClass {
function echo_msg {
echo // now what...
}
function echo_from_inside {
$this->echo_msg()
}
}
result should be:
$my_instance = new MyClass();
$my_instance->echo_msg(); // I was called from OUTside
$my_instance->echo_from_inside(); // I was called from INside
It might be easier, rather than detecting from whence the function was called, to wrap a private function with a public one. Like so:
class MyClass{
private function myob(){
//do something
}
public function echo_msg(){
$this->myob();
//do other stuff like set a flag since it was a public call
}
private function foo(){ //some other internal function
//do stuff and call myob
$this->myob();
}
}
$obj=new MyClass();
$obj->echo_msg();//get output
$obj->myob(); //throws error because method is private
You can try and get the caller of your method:
$trace = debug_backtrace();
$caller = array_shift($trace);
echo 'called by '.$caller['function']
echo 'called by '.$caller['class']
this should work for you.
You could add an optional parameter like such:
function echo_msg($ins=false) {
if($ins){/*called from inside*/}else{/*called from outside*/}
echo // now what...
}
and leave that last. If you are calling it from inside the class, pass it true, otherwise pass nothing!

PHP add methods to Functions

Is it possible to add methods to functions?
For example:
<?
function func(){
;
}
//add method
func->test = function(){
;
}
func->test();
func();
I'm coming from a javascript background, and therefore I'm used to 'everything is an object'.
EDIT:
I was just explaining where the misconception may often come from for new phpers. I understand the above code doesn't work.
EDIT 2
Figured it out.
class myfunc_class{
function __invoke(){
//function body
}
function __call($closure, $args)
{
call_user_func_array($this->$closure, $args);
}
}
$func = new myfunc_class;
$func->test = function(){
echo '<br>test<br>';
};
$func->test();
$func();
Even sexier :)
class func{
public $_function;
function __invoke(){
return call_user_func_array($this->_function,func_get_args());
}
function __construct($fun){
$this->_function = $fun;
}
function __call($closure, $args)
{
call_user_func_array($this->$closure, $args);
}
}
$func = new func(function($value){
echo $value;
});
$func->method = function(){
echo '<br>test<br>';
};
$func('someValue');
$func->method();
No.
Not everything is an object in PHP. In fact the only thing that is an object is, well, an object. More specifically, and generally, an instantiation of a class.
Your code converted to PHP
// function_object.php
<?php
class FunctionObject {
public method func() {
// do stuff
}
}
?>
In other code you would use it like this:
<?php
// example.php in same folder as function_object.php
include 'function_object.php';
$FuncObj = new FunctionObject;
$FuncObj->func();
Also: read more about PHP & OOP
No, because an object is a different PHP language construct than a function. Functions do not have properties, but are instead simply execution instructions.
But, if func were instead a pre-defined class, then yes... with a bit of witchcraft, ignoring public outcry, foregoing readability and PHP coding standards, and by using closures with the __call() magic method...
class func
{
function __call($func, $args)
{
return call_user_func_array($this->$func, $args);
}
}
$obj = new func;
$obj->test = function($param1, $param2)
{
return $param1 + $param2;
};
echo $obj->test(1,1);
This won't work as you'd think without __call(), because by $obj->test(1,1), PHP thinks you're trying to call a non-existent method of func when out of object scope. But inside, being that the new "test" property is of a type: closure, the call_user_func_array() just sees the "test" property as just another function, so you can hide this bit of trickery from outside scope.
You would need your function func() to return an object, then you'd be able to do something like: func()->test();
But please note that your way of handling objects is not right in PHP and I suggest that you go read the OO documentations here.
In difference to javacript, in PHP not everything is an object. Therefore you need to differ between function and class.
If you want to create an object, you need to define the class first.
class myClass {
}
You can then add as many functions to the class as you need. But you need to define them first:
class myClass {
function test() {
echo "test!\n";
}
}
When everything is ready, you can bring it to life then:
$class = new myClass;
$class->test();
Checkout the manual for more.
You can't do what you're trying to do, but you can define functions inside of other functions.
This example outputs text:
function a() {
function b() { echo 'Hi'; }
}
a();
b();
Output: HiHi
This example outputs an error:
function a() {
function b() { echo 'Hi'; }
}
b();
Output: ERROR

Execute a method when an instance variable is referenced in a PHP class?

Is it possible to run a function when referring to a variable in a php class rather than simply returning its value, similar to javascript's ability for a variable to hold a method?
class LazyClassTest()
{
protected $_lazyInitializedVar;
public function __construct()
{
/* // How can this call and return runWhenReferrenced() when
// someone refers to it outside of the class:
$class = new LazyClass();
$class->lazy;
// Such that $class->lazy calls $this->runWhenReferrenced each
// time it is referred to via $class->lazy?
*/
$this->lazy = $this->runWhenReferrenced();
}
protected function runWhenReferrenced()
{
if (!$this->_lazyInitializedVar) {
$this->_lazyInitializedVar = 'someValue';
}
return $this->_lazyInitializedVar
}
}
PHP5s magic method __get($key) and __set($key, $value) might be what you need. More information about them is available in the PHP manual.
This sounds like PHP5.3: lambda / closures / anonymous functions
http://php.net/manual/en/functions.anonymous.php:
<?php
$greet = function($name) {
printf("Hello %s\r\n", $name);
};
$greet('World');
$greet('PHP');
?>
You are probably heading in the wrong direction. You normally want to define a getter getLazyVar(). There is a reason why people always make properties protected and defined getters / setters: So they can pre- or postprocess the values.

Categories