php - Having trouble understanding why my Closure wasn't working

835

I have a controller in laravel, AppExportController. In one of my functions on that controller, I iterate over many records and return a file download. I decided I wanted to create a little function so I could cache a certain thing, a Zone Name in this instance.

This was my first attempt at writing a function to cache the zone names (the getZoneName function obviously):

<?php

namespace App\Http\Controllers;

class AppExportController extends Controller {
    /**
     * Create a new controller instance.
     *
     * @return void
     */
    public function __construct() {
        $this->middleware('auth');
        $this->middleware('client.approved');
    }

    public function prices(Request $request) {
        $user = Auth::user();
        ...

        $zoneNameCache = [];
        function getZoneName($zoneId) use (&$zoneNameCache) {
            try {
                if (!empty($zoneNameCache[$zoneId])) {
                    return $zoneNameCache[$zoneId];
                } else {
                    $zone = ServiceZone::find($zoneId);
                    $zoneNameCache[$zoneId] = $zone->name;
                    return $zone->name;
                }
            } catch(Exception $e) {
                return '';
            }
        };


        $prices = []; // I actually do a database query here, don't worry about that
        $records = [];

        foreach($prices as $price) {
            // output to $records here
            $records[] = [
                ...
                getZoneName($price->service_zone_id),
                ...
            ];
        }

        return response();
    }

}

This was making that route 500 error, and I tracked it down to being for sure the closure aspect of the function -- when I took out theuse (&$zoneNameCache) part, it worked (but didn't cache anything of course).

So I tried another thing -- assigning the function to a variable instead. And that worked! With the closure, and caching was working!

<?php

namespace App\Http\Controllers;

class AppExportController extends Controller {
    /**
     * Create a new controller instance.
     *
     * @return void
     */
    public function __construct() {
        $this->middleware('auth');
        $this->middleware('client.approved');
    }

    public function prices(Request $request) {
        $user = Auth::user();
        ...

        $zoneNameCache = [];
        $getZoneName = function ($zoneId) use (&$zoneNameCache) {
            try {
                if (!empty($zoneNameCache[$zoneId])) {
                    return $zoneNameCache[$zoneId];
                } else {
                    $zone = ServiceZone::find($zoneId);
                    $zoneNameCache[$zoneId] = $zone->name;
                    return $zone->name;
                }
            } catch(Exception $e) {
                return '';
            }
        };


        $prices = []; // I actually do a database query here, don't worry about that
        $records = [];

        foreach($prices as $price) {
            // output to $records here
            $records[] = [
                ...
                $getZoneName($price->service_zone_id),
                ...
            ];
        }

        return response();
    }

}

I don't know why the second one should work but not the first one. Can anyone shed light on this?

761

Answer

Solution:

Without assigning it to a variable, or returning it, it is not a closure.

This way you have function declaration, within another function or method in this case.

Which is not allowed, and therefore will give you a 500 for sure.

If you check your php error_log and probably your laravel log. It will tell you that.

If your do not want to assign it to a variable at that point, you could return it immediately

return function().......

People are also looking for solutions to the problem: php - Laravel, migrate existing table from local phpmyadmin to server

Source

Didn't find the answer?

Our community is visited by hundreds of web development professionals every day. Ask your question and get a quick answer for free.

Ask a Question

Write quick answer

Do you know the answer to this question? Write a quick response to it. With your help, we will make our community stronger.

Similar questions

Find the answer in similar questions on our website.