Callback is not called in add_settings_field() when passed as part of an array, but recognises that it’s there. It’s passed Class to Class using OOP

Question

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 BlocksPagesSettingsAPI;
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 endresult, 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.

And because that’s a lot of code, pasted the relevant code into the online editor for you to look at even better: https://repl.it/@Braweria/Callback-Problems

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.

0
Mahnenwolf 8 months 2020-11-25T12:10:20-05:00 0 Answers 15 views 0

Leave an answer

Browse
Browse