PHP custom function with as syntax, function ($x as $y)

Viewed 117

I'd like to implement a for loop using the $array as $element syntax in an anonymous function

Is this possible? I can't use forEach as the $array is actually an object, and forEach doesn't copy the object as it would with an array

I'm using laravel so I'm trying to write a blade directive like forEach but in a way that it makes a copy of the object.

something like:

Blade::directive('safeForEach', function ($array as $el){
return '<?php for ($i = 0; $i < count($array); $i++){ ?>';
});

where after @safeForEach is called, I can use each $el.

Blade::directive('endSafeForEach', function (){
return '<?php { ?>';
});

Any ideas please? I've tried to find the source for the blade directive but can't find it. Thanks

1 Answers

The directive command's callback takes a single parameter which is the string that is passed in the directive which you need to parse. You can check the source code of Laravel and adapt it to your own needs:

Blade::directive('safeForEach', function ($expression) {
        preg_match('/\( *(.*) +as *(.*)\)$/is', $expression, $matches); 
        $iteratee = trim($matches[1]);
        $iteration = trim($matches[2]);
        $initLoop = "\$__currentLoopData = {$iteratee}; \$__env->addLoop(\$__currentLoopData);";
        $iterateLoop = '$__env->incrementLoopIndices(); $loop = $__env->getLastLoop();'.$iteration.'=clone '.$iteratee.'[$i]';

        return '<?php '. $initLoop.' for ($i = 0; $i < count('.$iteratee.'); $i++) { '.$iterateLoop.' ?>';
});
Blade::directive('endSafeForEach', function () {
        return '<?php } ?>';
});

If for example you pass @safeForEach($a as $b) this should compile to:

$__currentLoopData = $a;
$__env->addLoop($__currentLoopData);
for ($i = 0;$i < count($a);$i++) { 
    $__env->incrementLoopIndices(); 
    $loop = $__env->getLastLoop();    
    $b = clone $a[$i];

however you need to ensure that

  1. $iteratee is countable
  2. $i does not conflict. Laravel uses a variable called $__env to store loop information and assumes that it's not used elsewhere but given the name it's less likely to be used.
  3. clone will only make a shallow copy of an object and might break for non-clonable elements so you might also need to refine that part
Related