Search code examples
phparraysfor-loopnestednested-for-loop

Accessing key values of nested associative array


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
                        )
                    );
                }
            }

Solution

  • 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']);
                         }
                        );
                    );