Why this global array is returning NULL from a callback function

The problem here is that you never created $ppk_fields as a global variable.

$ppk_fields = [
    'field 1' => [
        'title'   => 'Fieald One',
        'type'    => 'text',
        'section' => 'section_1',  
        'default' => 'default'
    ]
];

Here we have a variable that is created normally, and obeys normal scoping rules. It isn’t a global variable, and nobody has stated it’s a global variable.

Further down the file we have:

function ppk_field_callback($id) {
    global $ppk_fields;

But, the global variable $ppk_fields is undefined, nobody defined it. You have to declare the variable as a global every time you use it, and that includes creation and destruction. No exceptions.

So you need to:

  • declare that the variable is a global when you define it using global $ppk_fields

Doing it Wrong

But there’s an even bigger problem. The biggest problem is that you used global variables at all. Global variables are a great way to avoid structuring your program, break unit tests, and introduce unnecessary complexity

For example, the global variables would be unnecessary if you’d placed all of the above code inside a class. Then, $this->fields would be what you’d use.

Here’s a partial example:

ppk_settings.php:

class PPK_Settings {
    private $sections;
    private $fields;

    function __construct() {
        $this->sections = [
            'section_1' => [
                'title' => 'Group One'
            ]
        ];
        $this->fields = [
            'field 1' => [
                'title'   => 'Fieald One',
                'type'    => 'text',
                'section' => 'section_1',  
                'default' => 'default'
            ]
        ];
    }

    function register() {
        register_setting( 'ppk-builder', 'ppk-builder', 'ppk-builder_validate' );

        foreach ($this->sections as $id => $value) {
            add_settings_section( $id, $value['title'], array( $this, 'section_callback' ), 'ppk_p');
        }

        foreach ($this->fields as $id => $value) {       
            add_settings_field( $id, $value['title'], array( $this, 'ppk_field_callback' ), 'ppk_p', $value['section'], $id );
        }
    }

    // etc... other methods go here
}

usage:

require_once( 'ppk_settings.php' );    
$settings = new PPK_Settings();
$settings->register();

You could instead go the OO way, and have PPK_Field and PPK_Section objects, so that you can define your fields, then loop over the array creating objects, with no problems or troubles accessing them, and no need for globals or member variables