Cannot Access Variable Inside the Controller Callback Function

Hi,

In the following controller code, I am trying to access the variable $countries inside the function get_shipping_country():

$siteRoot = kirby()->roots()->index();
require_once $siteRoot . '/code/countries.php' // Pulls in the $countries array
/**
$countries = [
    'DE' => 'Germany',
    // [...]
];
*/

return function ($site, $pages, $page) {
$data = [];

// [...]

function get_shipping_country($order) {
        global $countries;
        $country_code = $order->shipping->country;

        return $countries[$country_code];
    }

// [...]

return compact('data');
}

Unfortunately, this doesn’t work. The variable $countries is only accessible outside the callback, but I cannot access it from within.

Does anybody have an idea of what I did wrong here? Any suggestions are highly welcome!

Cheers,

Stefan

What you could do:

<?php
$siteRoot = kirby()->roots()->index();
require_once $siteRoot . '/code/countries.php'; // Pulls in the $countries array

return function ($site, $pages, $page) use($countries){
$data = [];



function get_shipping_country($order, $countries) {

        $country_code = $order->shipping->country;
        return $countries[$country_code];
    }



return compact('data', 'countries');
};

Then in your template:

echo get_shipping_country($order, $countries);

But I’d define those countries in the config file:

c::set('countries', [
  'DE' => 'Germany',
];

Then you can access them from anywhere and no need to require a separate file, no need to use use() etc.

controller:

<?php

return function ($site, $pages, $page){
$data = [];



function get_shipping_country($order) {
        $countries = c::get('countries');
        $country_code = $order->shipping->country;
        return $countries[$country_code];
    }



return compact('data');
};

template:

echo get_shipping_country($order);

@texnixe Thanks for your detailed answer!

You are right, the second solution is probably the most elegant.

The problem with the first solution (in my case) is that get_shipping_country() is added to an array and then called from inside another function with only the $order argument being passed. I just don’t know how to pass the additional argument $countries there:

function get_shipping_country($order) {
        $country_code = $order->shipping->country;
        return $countries[$country_code];
    }

    $itemsToRetrieve = [
            'id'                => 'get_id',
            'status'            => 'get_status',
            'shipping.name'     => 'get_shipping_name',
            'shipping.street'   => 'get_shipping_street',
            'shipping.city'     => 'get_shipping_city',
            'shipping.state'    => 'get_shipping_state',
            'shipping.postcode' => 'get_shipping_postcode',
            'shipping.country'  => 'get_shipping_country', // get_shipping_country()
        ];

    function get_formatted_items ($orders, $itemsToRetrieve = []) {
            $orders_with_items = [];

            foreach ($orders as $order) {
                $order_items = [];
                foreach ($itemsToRetrieve as $key => $func) {
                    $order_items[$key] = $func($order); // This is where get_shipping_country() is called
                }
                $orders_with_items[] = $order_items;
            }
            return $orders_with_items;
        }

Just out of curiosity, is there a way to pass the $countries variable as the second parameter of get_shipping countries() inside get_formatted_items() where it is called?

Cheers,

Stefan

In my opinion, the first solution doesn’t really make sense and in the light of what your are doing further down, even less. So I’d recommend you go with the second approach, it is the cleanest, instead of using global variables.

That’s what I will do.

Thanks again for your help! I really appreciate it.