2

I have a nested array like this:

$settings = [
            'settings_page' => [
                'page' => 'handler_environment',
                'options' => [
                    'op_1' = 'val_1',
                    'op_2' = 'val_2',
                    'op_3' = 'val_3',
                    'op_4' = 'val_4'
                ]
            ]
        ]

and id like to access the key=>val structure in a foreach to fire some functions instantiated with their values like this:

public function add_settings_page()
    {
        foreach ($this->settings['settings_page'] as $setting) {
                var_dump($setting['page']); // handler_environment 
                var_dump($setting['options']); // val_1, val_2 etc... 

                add_menu_page(
                     __(ucwords($settingNiceName), // page_title
                     __(ucwords($settingNiceName), // menu_title
                     'manage_options', // capability
                     $setting['page'], // menu_slug
                     array( $this, 'create_admin_page', $setting['options']) // callback
                    );
                );

            }
        }
    }

but the looped variable evaluates to just the values of the nested array i.e 'handler_environment' and are therefore inaccessible via key reference due to them just being strings.

should be noted the array will contain multiple pages and options for them. It may be that im structuring my initial array incorrectly to achieve what i want.

Is there a way to get the loop to return the key value arrangement of the original nested array without having to reassign each value in to a new array in the loop? Am i overcomplicating this? I am lost at this point.

EDIT: I realise my answer deviates from the original question, but my issue was a combination of both my misunderstanding of how to access array items in the loop and how to push parameters to functions with a closure.

Here is what i ended up doing. i think i was trying to traverse the array incorrectly... but I am not 100% sure on that. Thank you @Barmar for showing how to call the closure and pass the parameters. Array:

$this->settings = [
            'settings_page' => [
                'page_name' => 'handler_environment',
                'page_type' => 'page',
                'options' => [
                    'op_1',
                    'op_2',
                    'op_3',
                    'op_4'
                ]
            ],

Loop:

foreach ($this->settings as $page) {
            register_setting(
                $page['page_name'], // option_group
                $page['page_name'] . '_options' // option_name
            );

            if($page['page_type'] == 'page') {
                add_settings_section(
                    $page['page_name'] . '_setting_section', // id
                    __('Settings', TEXT_DOMAIN), // title
                    function() use ($page) {
                        $this->sectionInfo($page['page_name']);
                    }, // callback
                    $page['page_name'] // page
                );

                foreach ($page['options'] as $option) {
                    add_settings_field(
                        $option, // id
                        __($option, TEXT_DOMAIN), // title
                        function() use ($option) {
                            $this->fieldCallback($option);
                        },
                        $page['page_name'], // page
                        $page['page_name'] . '_setting_section', // section
                        array(
                            'label_for' => $option
                        )
                    );
                }
            }
  • What are you trying to do with the anonymous function? You never call it or assign it to anything. – Barmar Oct 10 '22 at 23:06
  • You need `function() use($setting) { ... }` so that it can access `$setting` – Barmar Oct 10 '22 at 23:07
  • Sorry, the anon function is just an example i threw in to show what i would be trying to do in the loop, the reality is its a named function that uses the variables. i will update it to reflect that. – user12457660 Oct 10 '22 at 23:10
  • `foreach ($settings['options'] as $option => $value)` – Barmar Oct 10 '22 at 23:10
  • Id like the `$settings['options']` to be tied to the `$settings['page']` and don't necessarily need to loop through them – user12457660 Oct 10 '22 at 23:21
  • You're trying to make a closure that captures `$setting`? I don't think each loop iteration creates a new scope. – Barmar Oct 10 '22 at 23:27
  • Yes what i want, essentially to just call a function multiple times with different parameters from each iteration of the array. – user12457660 Oct 10 '22 at 23:47

1 Answers1

1

Make the callback a closure that captures $setting

                add_menu_page(
                     __(ucwords($settingNiceName), // page_title
                     __(ucwords($settingNiceName), // menu_title
                     'manage_options', // capability
                     $setting['page'], // menu_slug
                     function() use ($setting) {
                        $this->create_admin_page($setting['options']);
                     }
                    );
                );
Barmar
  • 741,623
  • 53
  • 500
  • 612
  • My trouble isnt in the function but in accessing the correct variables of the array in the loop. On a high level i have settings i wish to bind to pages and construct the page with a unique name and settings. there could be many of them. – user12457660 Oct 11 '22 at 00:12
  • In other words forget the function in the loop, lets say i just want to get the name and all the options for that name in one iteration of the loop, and loop the iteration however many `'settings_page'` 's there are – user12457660 Oct 11 '22 at 00:14
  • I don't understand the problem. Just use `$setting` to access the settings in the loop. – Barmar Oct 11 '22 at 00:25
  • You are overlooking the settings_page value for which you have created the foreach loop. seetting_page have two sets page = 'handler_environment' which type string and options = [var1, var2, etc] type array. So to access one value from them in your current loop you need to specify their index or create another foerach for options array to go through them all – Zubair Ahmd Oct 11 '22 at 01:05
  • I need to get the value by reference, but `var_dump($setting['page_name']);` gives`: Cannot access offset of type string on string ` because for some reason the key=>val structure isnt available within the scope of the loop (at least how i am going at it) – user12457660 Oct 11 '22 at 08:05
  • `$this->settings['settings_page']` is an associative array, you shouldn't loop over it. Just use `$setting = $this->settings['settings_page']` – Barmar Oct 11 '22 at 14:32
  • You were completely right, But i just needed to reformat my array a little bit to get it going. **Thank you!** – user12457660 Oct 12 '22 at 15:21