1

I am building a plugin, I created a new admin page and subpage, and inside that subpage, I want to add some Settings. That's why I'm building them using the Settings API.
I am using Composer and Object-Oriented Programming. I have a folder called SettingsAPI, with the following namespace namespace Blocks\Pages\SettingsAPI;
Inside that folder, I have three files: AddSettings.php, Settings.php and SettingsLayout.php. All three of them are correctly connected. The files have the case-sensitive names of the Classes. Settings.php has a Class named Settings, and so on.

SettingsAPI Folder Structure

Content

  • Some Context to my Structure
  • What I have already tried
  • What to do?

Some Context to my Structure

Inside Settings.php I have a function that holds a variety of arrays, inside of those arrays are the values I want to use for the Settings API. This means I have arrays that are used for register_setting(), add_settings_section() and add_settings_field().
Inside AddSettings.php I have the three functions just mentioned. Both register_settings() and add_settings_field() work great. I have problems with add_settings_field().
Inside SettingsLayout.php I have a very simple layout for where the form should be printed, which is also shown on the Subpage. Just the inputs are missing.

Inside AddSettings.php I used a foreach() to loop over the array, if I need to. Which is used for both register_setting() and add_settings_field(), that's because both of those arrays have arrays inside of them. I'll show some code used for register_setting() and the foreach().

Settings.php

$configs = [
      [ // Icon
        "option_group"    =>    "iw_" . $n,
        "option_name"     =>    "iw_icon_" . $n,
        "args"            =>    $iconConfigs
      ],
      [ // Titel
        "option_group"    =>    "iw_" . $n,
        "option_name"     =>    "iw_title_" . $n,
        "args"            =>    $titleConfigs
      ],
      [ // Beschreibung
        "option_group"    =>    "iw_" . $n,
        "option_name"     =>    "iw_description_" . $n,
        "args"            =>    $descriptionConfigs
      ],
      [ // Farbauswahl
        "option_group"    =>    "iw_" . $n,
        "option_name"     =>    "iw_colour_" . $n,
        "args"            =>    $colourConfigs
      ]
    ];

The array above is being passed, alongside the other arrays, to the AddSettings Class and the next function that will process them.

$this->add_settings->setForm( $configs, $segments, $inputs )->register();

setForm() does the following with the arguments.

AddSettings.php

public  function  setForm(  array  $configs,  array  $segments,  array  $inputs )  {
    $this->settings =  $configs;
    $this->sections =  $segments;
    $this->fields =  $inputs;
    return  $this;
}

The variables $settings, $sections and $fields have been created at the beginning of the class as public and empty arrays.

public $settings = array();
public $sections = array();
public $fields = array();

Which then gets registered with the following function:

public function functionToAdd()  {
return  $this->registerForm($this->settings,  $this->sections,  $this->fields);
}

registerForm() hold all the Settings API functions from WP, here is register_setting().

foreach( $this->settings as $setting ) {
      register_setting( $setting["option_group"], $setting["option_name"], isset( $setting["args"] ) ? $setting["args"] : "" );
    }

This part works great. It also works with add_settings_section(). What doesn't work, are the inputs. Which I will present now as well:

Settings.php

Inside this Class is the function/method setForm( $n = NULL ), that's where all the arrays are, like the one I showed above. Right now $n has no meaning, but it's going to be a number, so I can loop all over those arrays and settings to create more forms. Whether I keep it at NULL or I change it to 1, has no effect on the end-result, same thing.
Here is the array for the fields.

$inputs =  [
    [
        "id"  =>  "iw_icon_"  .  $n,
        "title"  =>  "Icon Auswahl",
        "callback"  =>  function()  use($n)  {  return  $this->iconInput(  $n );  },
        "page"  =>  "info_kreis_bearbeiten",
        "section"  =>  "iw_item_"  .  $n,
        "args"  =>  [  "label_for"  =>  "iw_icon_"  .  $n ]
    ],
    [
        "id"  =>  "iw_title_"  .  $n,
        "title"  =>  "Titel",
        "callback"  =>  function()  use($n)  {  return  $this->titleInput(  $n );  },
        "page"  =>  "info_kreis_bearbeiten",
        "section"  =>  "iw_item_"  .  $n,
        "args"  =>  [  "label_for"  =>  "iw_title_"  .  $n ]
    ],
    [
        "id"  =>  "iw_description_"  .  $n,
        "title"  =>  "Kurz Beschreibung",
        "callback"  =>  function()  use($n)  {  return  $this->descriptionInput(  $n );  },
        "page"  =>  "info_kreis_bearbeiten",
        "section"  =>  "iw_item_"  .  $n,
        "args"  =>  [  "label_for"  =>  "iw_description_"  .  $n
    ],
    [
        "id"  =>  "iw_colour_"  .  $n,
        "title"  =>  "Farbe auswählen",
        "callback"  =>  function()  use($n)  {  return  $this->colourInput(  $n );  },
        "page"  =>  "info_kreis_bearbeiten",
        "section"  =>  "iw_item_"  .  $n,
        "args"  =>  [ "label_for"  =>  "iw_colour_"  .  $n ]
    ]
];

So this is an array with three arrays inside of it. This array has callbacks, and it's the callbacks that do not work at all. No matter where I put them or how I write them, they are not being echo'd. At the bottom I will list all of the things I have tried.
Like with the settings arrays, they are allso processed like this:

$this->add_settings->setForm( $configs, $segments, $inputs )->register();

AddSettings.php

And then

public function setForm(array  $configs,  array  $segments,  array  $inputs)  {
    $this->settings =  $configs;
    $this->sections =  $segments;
    $this->fields =  $inputs;
    return  $this;
}

and

public function functionToAdd() {
    return  $this->registerForm($this->settings,  $this->sections,  $this->fields );
}

Which then gets passed to registerForm() with the following function:

foreach(  $this->fields as  $field)  {
    add_settings_field( $field["id"], $field["title"], isset( $field["callback"] ) ? $field["callback"] : "", $field["page"], $field["section"] = 'default', $field["args"] = array() );
}

And then nothing. No inputs on my Subpage. Everything but the fields are being echo'd. Form on Subpage
As you can see, the callback used by the section works and shows me the title and description. But the inputs are missing. To show some context on how I called the callback for the sections, here is the one line with the callback from the section array, inside Settings.php:

"callback"  =>  function()  use($n)  {  echo  "<p>Bearbeite hier die Info Nummer "  .  $n .  "</p>";  }

And the function add_settings_section() inside AddSettings.php, no foreach() was used for this one:

add_settings_section( $sections["id"],  $sections["title"], isset(  $sections["callback"] )  ?  $sections["callback"]  :  "",  $sections["page"]  );

It's being called the same way like the fields. But the fields still do not echo anything. Any before anyone says I am echoing inside the anonymous callback function instead of returning another function:

What I have already tried

I have tried a few things. One of the first things I tried was to edit the way the callback is written. So instead of a function that returns another function I wrote something simple.

"callback"  =>  function() { echo "Echo this please."; },

Didn't work.

"callback"  =>  array( $this, "iconInput" ),

Also not working I also tried

"callback"  =>  $this->iconInput( $n ),

Which then called the function and echo'd the inputs, but not in the right position. They were at the very top of the page. And if I loop everything, all inputs will be at the top, with the sections below in the right print order. So that's not the solution either.
What I also tried was to move the callback to AddSettings.php and call it like that.

add_settings_field(  $field["id"],  $field["title"],  function()  { return $this->iconInput();  },  $field["page"],  $field["section"]  =  'default',  $field["args"]  = array()  );

Didn't work either. When I tried to just directly write the function in there, like so

add_settings_field(  $field["id"],  $field["title"],  function()  { echo "Please echo this";  },  $field["page"],  $field["section"]  =  'default',  $field["args"]  = array()  );

Didn't work either. I also always put die; at the end, just to see if it's being called at all, and it has not been. It's like the function doesn't exist.
I have also tried to immediately run the function by adding () to it:

add_settings_field( $field["id"], $field["title"], isset( $field["callback"] ) ? $field["callback"]() : "", $field["page"], $field["section"] = 'default', $field["args"] = array() );

Same result like earlier. It echo'd the inputs, but not in the right position.

I tried looking for an answer, but couldn't really find one that was similar to mine. I found these questions and solution, tried them, and that also didn't work: How to pass arguments from add_settings_field() to the callback function? and Add_settings_field() parameterizing callback?

And for clarification, my SettingsLayout.php is build like this:

<form  method="post"  action="options.php"  id="iw_form_<?php  echo  $i?>">
    <?php
        settings_fields( "iw_"  .  $i );
        do_settings_sections(  "info_kreis_bearbeiten"  );
        submit_button( $text  =  NULL,  $type  =  "primary",  $name  =  "submit_"  .  $i );
    ?>
</form>

$i is the same as $n.

What to do?

I have run out of options to try. At least of options, I know of. If anyone has any kind of solution, I would be HAPPY to hear them. I also explained myself as best as I could.

Edit

Which I forgot to mention, inside my foreach() I also echoed field["id"] to see if that works, and it does echo the right ID.

1 Answer 1

1

From what I could see, the problem is not with the field callback, but it's the section ID whereby you're setting it to default — see $field["section"] = 'default' below:

// In the foreach in AddSettings.php
add_settings_field( $field["id"], $field["title"], isset( $field["callback"] ) ? $field["callback"] : "", $field["page"], $field["section"] = 'default', $field["args"] = array() );

So you'd only to correct that (typo?) and the fields would show up as expected, or that the field callback would run properly. And you should also correct the $field["args"] = array()..

1
  • 1
    I can't believe that was the problem. I removed = 'default' from the code and it shows up. I am so relieved. Now I am trying to loop it, hopefully, that will work. Commented Nov 26, 2020 at 7:51

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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