web-dev-qa-db-ja.com

このグローバル配列がコールバック関数からNULLを返す理由

これで何時間もおかしくなりました... ppk_field_callback関数で$ ppk_fields配列が空の理由を教えてください。 ppk_default_id関数に正しい値が返されることに注意してください。ただし、これはコールバック関数ではありません。ありがとうございました!

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' ); 
1
mrKC.988

ここでの問題は、あなたがグローバル変数として$ppk_fieldsを決して作成しなかったことです。

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

ここでは普通に作られ、普通のスコープ規則に従う変数を持っています。それは大域変数ではありません、そしてそれが大域変数であると誰も述べていません。

私たちが持っているファイルのさらに下に:

function ppk_field_callback($id) {
    global $ppk_fields;

しかし、グローバル変数$ppk_fieldsは未定義で、誰も定義していません。あなたはそれを使うたびにグローバルとして変数を宣言しなければなりません、そしてそれは創造と破壊を含みます。例外なく。

だからあなたがする必要があります:

  • global $ppk_fieldsを使用して定義した場合、変数はグローバルであることを宣言します

間違っている

しかし、もっと大きな問題があります。最大の問題は、あなたがグローバル変数を使ったことです。大域変数は、プログラムの構造化を避け、単体テストを破り、不要な複雑さを取り入れるための優れた方法です。

たとえば、上記のコードをすべてクラス内に配置すれば、グローバル変数は不要になります。それで、$this->fieldsはあなたが使うものになるでしょう。

これが部分的な例です。

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
}

用法:

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

代わりにOO方法を使用してPPK_FieldおよびPPK_Sectionオブジェクトを作成することで、フィールドを定義し、配列をループしてオブジェクトを作成することができます。またはメンバー変数

2
Tom J Nowell