1

This drove me crazy for hours now... Please tell me why the $ppk_fields array is empty in the ppk_field_callback function? Note that it returns the correct values in the ppk_default_id function but that is not a callback function. Thank you!

ppk.php

class Ppk {

    public function ini() {
        add_action( 'admin_menu', array( $this, 'add_ppk_p_menu' ) );
    }

    public function add_ppk_p_menu() {
        add_submenu_page( 'tools.php', 'PPK PLUGIN', 'PPK PLUGIN', 'manage_options', 'ppk_p', array( $this, 'ppk_build_dashboard' ) );
    }

    public function ppk_build_dashboard() {
        require_once plugin_dir_path( __FILE__ ) . 'ppk-builder.php';
    }

}

if ( class_exists( 'Ppk' ) ) {
    $ppk = new Ppk();
    $ppk->ini();
} 

ppk-builder.php

$ppk_sections = [
    'section_1' => [
        'title' => 'Group One'
    ]
];

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

register_setting( 'ppk-builder', 'ppk-builder', 'ppk-builder_validate' );

    foreach ($ppk_sections as $id => $value) {
        add_settings_section( $id, $value['title'], 'ppk_section_callback', 'ppk_p');
    }

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

function ppk_section_callback() {return null;}

function ppk_default_id( $id ) {
    global $ppk_fields;

    return $ppk_fields[ $id ]['default'];
}

function ppk_field_callback($id) {
    global $ppk_fields;

    $option = get_option('ppk-builder');
    $id_field = isset($option[$id]) ? $option[$id] : ppk_default_id($id);

    switch ($ppk_fields[$id]['type']) {
        case 'text':        
            echo '<input type="text" name="ppk-builder[' . $id . ']" value="' . $id_field . '"/>';
        break;
    }
}


settings_fields( 'ppk-builder' );
do_settings_sections( 'ppk_p' ); 
  • Where do you set the $ppk_fields variable as a global? – Tom J Nowell Nov 15 '17 at 1:06
  • @TomJNowell inside the ppk_field_callback function, no where else. Why is it even when it's set as global i can't access the array values? – mrKC.988 Nov 15 '17 at 1:28
2

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

  • 1
    Didn't thought i could build this into a class since the file is required in another class method! Yes, it seems I can and this is way easier and better for me. Thank you so much for looking into my issue :) – mrKC.988 Nov 15 '17 at 18:04

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.