[SOLVED]Passing functions as an argument.

PHP programming forum. Ask questions or help people concerning PHP code. Don't understand a function? Need help implementing a class? Don't understand a class? Here is where to ask. Remember to do your homework!

Moderator: General Moderators

User avatar
JellyFish
DevNet Resident
Posts: 1361
Joined: Tue Feb 14, 2006 7:18 pm
Location: San Diego, CA

[SOLVED]Passing functions as an argument.

Post by JellyFish »

How can I pass a function or a block of code as function's argument?

In javascript I know i can like so:

Code: Select all

myFunction(function () {
//blcok of code
});
but how do I do this in php?

Thanks for reading, I hope it's more simple then I might think.
Last edited by JellyFish on Tue Dec 04, 2007 8:53 pm, edited 1 time in total.
User avatar
volka
DevNet Evangelist
Posts: 8391
Joined: Tue May 07, 2002 9:48 am
Location: Berlin, ger

Post by volka »

You can pass the function's name.

Code: Select all

<?php
function bar($x) {
	echo $x*2;
}
function foo($fn) {
	$fn(1234);
}
foo('bar');
User avatar
Christopher
Site Administrator
Posts: 13596
Joined: Wed Aug 25, 2004 7:54 pm
Location: New York, NY, US

Post by Christopher »

Or pass either a string or array in the form for call_user_func(). That is the PHP standard for passing functions/object methods around.
(#10850)
User avatar
JellyFish
DevNet Resident
Posts: 1361
Joined: Tue Feb 14, 2006 7:18 pm
Location: San Diego, CA

Post by JellyFish »

volka wrote:You can pass the function's name.

Code: Select all

<?php
function bar($x) {
	echo $x*2;
}
function foo($fn) {
	$fn(1234);
}
foo('bar');
Well, I'm really looking for a way to pass a handle that will be executed in the function. Err. For example, myFunction has one parameter, handle, and you pass in a block of code to be executed in myFunction. The only way to pass in blocks of code in javascript is through using a function. But sense you can really create functions as fluently in php is there another way to pass multiple statements to be executed?

Why I need this is because I'm creating an each() method for a class of mine. It will allow me to execute a block of code for each row of something or other. But basically it's an each() method.
User avatar
Christopher
Site Administrator
Posts: 13596
Joined: Wed Aug 25, 2004 7:54 pm
Location: New York, NY, US

Post by Christopher »

Maybe if you showed and example of what you are trying to achieve.
(#10850)
User avatar
volka
DevNet Evangelist
Posts: 8391
Joined: Tue May 07, 2002 9:48 am
Location: Berlin, ger

Post by volka »

You mean something like closures in python or ruby or maybe anonymous classes in java?
User avatar
JellyFish
DevNet Resident
Posts: 1361
Joined: Tue Feb 14, 2006 7:18 pm
Location: San Diego, CA

Post by JellyFish »

Here's an example:

Code: Select all

database->each(array("query" => "SELECT...","callback" => /*passed in code*/));
This method to database would call callback for every row that's returned by query. Now callback needs to be a block of code to be executed for every row.

I hope it's clear of what I'm doing, I can't think of any other way to explain it. :?
User avatar
volka
DevNet Evangelist
Posts: 8391
Joined: Tue May 07, 2002 9:48 am
Location: Berlin, ger

Post by volka »

'callback'=>'nameOfFunction'
Even if you use create_function() the return value will be the name of the newly created function as string.

Code: Select all

$fn = create_function('$x', 'return $x;');
var_dump($fn);
string(9) "
lambda_1"
User avatar
JellyFish
DevNet Resident
Posts: 1361
Joined: Tue Feb 14, 2006 7:18 pm
Location: San Diego, CA

Post by JellyFish »

volka wrote:'callback'=>'nameOfFunction'
Even if you use create_function() the return value will be the name of the newly created function as string.

Code: Select all

$fn = create_function('$x', 'return $x;');
var_dump($fn);
string(9) "
lambda_1"
Hmm. I don't understand? You mean just define a function then pass it like you said before? The only problem with this is that I have this function that I defined left over. If I could create the function within the same statement like:

Code: Select all

database->each(array("callback" => function foo(){
//functions code
}));
Or if I could somehow delete a function:

Code: Select all

function foo() {
//functions code
}
database->each(array("callback" => 'foo'));
unset('foo');
I don't know if unset would be the correct function for removing a function.
User avatar
Christopher
Site Administrator
Posts: 13596
Joined: Wed Aug 25, 2004 7:54 pm
Location: New York, NY, US

Post by Christopher »

Ok ... now I am really confused. You have a function "left over" that you want to "delete"? Honestly it sounds like you are trying to do something that there is probably a fairly normal solution for, but you are headed in some odd direction. I can't imagine that you really want to do what you think you want do to. Although you could simulate wacky things with calls like create_function() and eval(). It actually sounds like you want to implement something like the Command pattern...

What are you actually trying to do?
(#10850)
User avatar
JellyFish
DevNet Resident
Posts: 1361
Joined: Tue Feb 14, 2006 7:18 pm
Location: San Diego, CA

Post by JellyFish »

I'm trying to pass a function as an argument for a method to a class of mine. Kind of like how I could do this in javascript:

Code: Select all

myobject.mymethod(function () {
//code
});
I would like to do it in php:

Code: Select all

myobject->mymethod(function () {
//code
});
But does it work in php like it does javascript? That was my question. And if the answer is no, then my other question is: How can i pass a function as an argument in php?

Well, volka said that I could do something like this:

Code: Select all

function foo()
{
//code
}

myobject->mymethod('foo');
but now I'm left with this foo function that I don't want, because it takes up namespace. And I don't think I can redefine a function if I ever wanted to call mymethod multiple times:

Code: Select all

function foo()
{
//code
}

myobject->mymethod('foo');

function foo()
{
//deferent code
}

myobject->mymethod('foo');
SO I would have to use a different name for my function other then foo. But then I would have to keep track of the functions that I created just to pass into a method.

Whew...

If you are still confused that answer this simple question: Will the follow code err?

Code: Select all

myobject->mymethod(function () {
//code
});
???
User avatar
Christopher
Site Administrator
Posts: 13596
Joined: Wed Aug 25, 2004 7:54 pm
Location: New York, NY, US

Post by Christopher »

The things in Javascript you describe are called Closures. Perhaps you could look around to see if anyone has hack to together a system that implements something like Closures. But I think a simpler solution would be to use the Command pattern.

http://www.phppatterns.com/docs/design/ ... nd_pattern
http://en.wikipedia.org/wiki/Command_pattern

The idea is, just like you showed, you pass a thing that has the same interface but contains different code. In your case it would be something like:

Code: Select all

class MyClass {
    function mymethod($command) {
        $command->foo()
    }
}
$myobject = new MyClass();

class Bar1 {
    function foo() {
    //code
    }
}
$myobject->mymethod(new Bar1($some, $params));

class Bar2 {
    function foo() {
    //deferent code
    }
}
$myobject->mymethod(new Bar2($other, $params));
(#10850)
User avatar
volka
DevNet Evangelist
Posts: 8391
Joined: Tue May 07, 2002 9:48 am
Location: Berlin, ger

Post by volka »

In any way the function/method will exist for the remainder of the php instance.
User avatar
vigge89
Forum Regular
Posts: 875
Joined: Wed Jul 30, 2003 3:29 am
Location: Sweden

Post by vigge89 »

I'm guessing this is what you want?

Code: Select all

class object {
    public function method($funcName) {
        echo $funcName(1, 3); // should output 4
    }
}

$function = create_function('$a, $b', "return (int)\$a+(int)\$b;");
$object = new object();
$object->method($function);
User avatar
JellyFish
DevNet Resident
Posts: 1361
Joined: Tue Feb 14, 2006 7:18 pm
Location: San Diego, CA

Post by JellyFish »

vigge89 wrote:I'm guessing this is what you want?

Code: Select all

class object {
    public function method($funcName) {
        echo $funcName(1, 3); // should output 4
    }
}

$function = create_function('$a, $b', "return (int)\$a+(int)\$b;");
$object = new object();
$object->method($function);
In a way yes. But the create_function doesn't appear to be very..."good". Not like javascript which uses, I guess you say, closure or lambda style programming.

I think I got my answer though.

I'll look more into it.

Thank you everyone, very much appreciated! :D
Post Reply