Vahag Chakhoyan
Vahag Chakhoyan

Reputation: 779

Php function as function's parameter

In my php project I have some functions that in some cases I want to call under try-catch block, and in some cases not under try-catch block. And now I want to write a function that gets some function as parameter, calls it and return false in case of exception.

Approximately code like this and with support of different numbers of parameters for 'someFunction'.

function tryTo($someFunctionName) {
    try {
        return someFunctionName();
    } catch (Exception $error) {
        return false;
    }

How to organize that?

Upvotes: 1

Views: 2299

Answers (3)

YamiTenshi
YamiTenshi

Reputation: 176

PHP allows you to call a number of things as if they were functions - this includes:

  • function names as strings (for instance "myFunc")
  • arrays containing a function name as the first element and an array of arguments as the second element (for instance ["myFunc", ["arg1", "arg2"]])
  • arrays containing an object as the first element and an array of arguments as the second element (for instance [new MyClass(), ["arg1", "arg2"]])
  • instances of classes implementing the __invoke() magic method
  • Closures/anonymous functions

All of these can be denoted by the callable typehint. As such, implementing your function as such:

tryTo(callable $callable) {
    try {
        $callable();
    catch(\Exception $ex) {
        return false;
    }
}

would allow you to use tryTo() for anything PHP considers callable, and enforce that whatever you pass can be used to call a function.

So the following will work:

tryTo('myFunc'); // Equivalent to myFunc();
tryTo('MyClass::myFunc'); // Equivalent to MyClass::myFunc();
tryTo(['myFunc', ['myArg', 'myOtherArg']]; // Equivalent to myFunc('myArg', 'myOtherArg');
tryTo([new MyClass(), 'myFunc']); // Equivalent to (new MyClass())->myFunc();
tryTo(function() { echo 'test'; }); // executes whatever closure you pass

You can see here for more information.

That said, I'm seriously questioning the use case for a function like that - generally, exceptions shouldn't happen unless something is wrong, and using a function like that opens you up to silent failures. At the very least, you should log the exception that occurred so you can see that something went wrong, but in my opinion you should handle specific exceptions wherever they're relevant. That, however, is an entirely different discussion altogether and does nothing to answer your question.

Upvotes: 0

trincot
trincot

Reputation: 350272

You need to define your original functions as Closures so they are represented by variables and can be passed as function arguments.

Here is example code:

function myFunc ($arg) {
    echo "called myFunc with '$arg' as argument";
}

// create a Closure for it
$myFunc = function ($arg) { myFunc($arg); };

function tryTo($someFunctionName, $arg) {
    try {
        return $someFunctionName($arg);
    } catch (Exception $error) {
        return false;
    }
}

// call tryTo passing the Closure and the argument
echo tryTo($myFunc, "test");

As of PHP 5.6 you can also use the spread operator which makes it a piece of cake to support multiple arguments. That way one tryIt function can host for functions with different numbers of parameters:

function tryTo($someFunctionName, ...$args) {
    try {
        return $someFunctionName(...$args);
    } catch (Exception $error) {
        return false;
    }
}

Upvotes: 3

Tanveer Hussain
Tanveer Hussain

Reputation: 123

<?php 
function tryTo($someFunctionName) {
  try {
    return $someFunctionName();
} catch (Exception $error) {
    return false;
}

// call tryTo function by passing function name
tryTo(functionName);
?>

Upvotes: 0

Related Questions