3

I have several php files to include and they must act as a function in a protected scope. A closure is intended to load them (include) and execute. Though I encounter a strange effect on coding these closures. All php files ends with a return statement.

function myClosure () { 
    include 'file.php';
    return $closure;         // initialized in file.php
};
$func = myClosure();
echo $func('1');             // echoes '2'
echo $func('4');             // echoes '8'

where file.php is something like

<?php
$closure = function($a) {
    $b = $a + $a;
    return $b;
};
?>

This works. However, I would like to have the surrounding closure 'function($b)' (without the 'return') in the main code, not in the external file. Sadly, the following doesn't work as expected:

function myClosure () { 
    $closure = function($a) {
        include 'file.php';
    };
    return $closure; 
};
$func = myClosure();
echo $func('1');             // echoes null
echo $func('4');             // echoes null

where file.php is something like

<php
$b = $a + $a;
return $b;
?>

Changing the includes into include_once gives the same for the first example, and not for the second example: second echo fails to run. I'm suspecting now that this behaviour is either a bug (php 5) or due to doing some illegal trick with include. Maybe the 'return's in the code are bound to their context? I would appreciate some help, be it a lesson on clean coding, be it a correct trick.

  • You're not returning in the closure. `include 'file.php'` will translate, as you said, in `... return $b`, however, `$closure = function ...` is also scoped, thus `return $closure` will in fact return null, since it's the default value that PHP gives. Long story short, just do `return include 'file.php'` inside `myClosure`. – Andrei Nov 28 '16 at 12:11

1 Answers1

0

Since closures are scoped(as OP has already mentioned), you'll have to return inside myClosure.

You now have:

function myClosure () {
    $closure = function($a) {
       include 'file.php';
    };
    return $closure;
};

Simply change it to:

function myClosure () {
    $closure = function($a) {
        return include 'file.php';
    };
    return $closure;
};

You should receive something along the lines of:

int(2) int(4)

given that you maintain the

$func = myClosure();
var_dump($func('1')); 
var_dump($func('2'));
Andrei
  • 3,434
  • 5
  • 21
  • 44
  • I agree and feel a bit dumb to forget this. Your example works off course. Maybe I was too focussed on having the 'include_once', which does work in the first example and NOT in the second. It seems to me that every call will load the file again. My problem becomes than, how to avoid the loading of the external php file on every call of the closure? I mean, having a bare 'include' in this way is insecure. – Wim Niemans Nov 28 '16 at 12:27
  • Welp, you really can't. That's the purpose of the include itself. And since you're using closure you actually **want** it to include it every time since it's scoped. Ok, honestly speaking now, I'm not sure what you're trying to achieve here but `include` is always messy. Perhaps if you'd ask "I want to do this. Is it the best way?" would be better than what you're currently asking. Just a thought. – Andrei Nov 28 '16 at 12:29