2

So, I've been staring at this problem for a few days now. I am attempting to push my skills further in PHP development, and decided to tackle a WP plugin with an OOP approach. I know that WP isn't necessarily the best choice for this, but I love a good challenge.

I am writing a Helper class, as I intend to use some functions fairly regularly, but I am running into a little bit of an issue.

Helper Class

Class Helper implements HelperInterface
{

/**
 * Default Options for making an admin page
 *
 * @var array
 */
public $default_options = [
    'slug'          =>      '',
    'title'         =>      '',
    'page_title'    =>      '',
    'parent'        =>      null,
    'id'            =>      '',
    'capability'    =>      'update_core',
    'icon'          =>      'dashicons-admin-generic',
    'position'      =>      null,
    'file_name'     =>      null,
    'desc'          =>      '',
];

/**
 * Store options passed in by user.
 *
 * @var array
 */
public $options = [];

public $parent_id;

public $settings_id;

/**
 * Stores the media type for a stylesheet
 *
 * @var string
 */
public $media_type;

public function __construct(  )
{

}

public function add_new_page( $opt )
{   
    $this->options = array_merge( $this->default_options, $opt );
    add_action( 'admin_menu', function() {
        
        add_menu_page(
            $this->options['page_title'],
            $this->options['title'],
            $this->options['capability'],
            $this->options['slug'],
            array($this, display_page_template),
            $this->options['icon'],
            $this->options['position']
        );
    } );

}

Helper Class Usage

Class GoogleMaps 
{

protected $helper;

public function __construct()
{
    $this->helper = new Helper;
    $this->helper->add_new_page([
        'slug'          =>      'google-maps',
        'title'         =>      'EdsGoogleMaps',
        'page_title'    =>      'EdsGoogleMaps',
        'capability'    =>      'update_core',
        'icon'          =>      'dashicons-admin-generic',
        'position'      =>      null,
        'file_name'     =>      'GoogleMapsHome.php',
    ]);
    
    $this->helper->add_new_page([
        'slug'          =>      'google-maps-2',
        'title'         =>      'EdsGoogleMaps2',
        'page_title'    =>      'EdsGoogleMaps2',
        'capability'    =>      'update_core',
        'icon'          =>      'dashicons-admin-generic',
        'position'      =>      null,
        'file_name'     =>      'GoogleMapsHome.php',
    ]);

    $this->helper->add_new_page([
        'slug'          =>      'google-maps-3',
        'title'         =>      'EdsGoogleMaps3',
        'page_title'    =>      'EdsGoogleMaps3',
        'capability'    =>      'update_core',
        'icon'          =>      'dashicons-admin-generic',
        'position'      =>      null,
        'file_name'     =>      'GoogleMapsHome.php',
    ]);
    
    }
}

Current Output

enter image description here

Things I've tried

  1. Putting the array into a foreach loop. Not working because, will either return the first one twice or return all three again.
  2. Original route was as a pass by reference type of thing. Passing the variables from the function and storing them in global vars within the class. Still not working due to same issue as described

My current thoughts are that it is something to do with the use of the add_action and an anonymous function alongside the fact that the add_action gets called everytime the helper function is called.

Hopefully someone has some sort of idea of a solution for this, and hopefully I have been clear enough in my issue.

Thanks :)

3

the call at the anonymous function is done after all the executions of add_new_page. then you need to store all elements to create menu items.

try to modify the class Helper like that

public function __construct() // method to modify
{

    add_action("admin_menu", [$this, "add_admin_menu_items"]);

}

public function add_new_page( $opt ) // method to modify
{
    $element = array_merge( $this->default_options, $opt );

    $this->options[] = $element;

}


public function add_admin_menu_items() // method to create
{

    $helper = $this;


    foreach ($this->options as $element) {

        add_menu_page(
            $element['page_title'],
            $element['title'],
            $element['capability'],
            $element['slug'],
            function () use ($helper, $element) {

                $helper->display_page_template($element);

            },
            $element['icon'],
            $element['position']
        );

    }


}


public function display_page_template($itemDatas)
{

    ?>

        <pre><?php
            echo htmlspecialchars(var_export($itemDatas, TRUE));
        ?></pre>

    <?php

}

}
| improve this answer | |
  • Thanks, this worked. Can you explain a little further as to why moving it into the construct works as opposed to where I had it in the beginning? – EBennett Apr 1 '18 at 20:05
  • Could someone explain why this: array(array($this, 'display_page_template'), array($element['file_name'])), would not work as the callback function for the above? the function display_page_template requires a parameter to work. Current error is: call_user_func_array() expects parameter 1 to be a valid callback, first array member is not a valid class name or object – EBennett Apr 1 '18 at 21:57
  • to pass parameters you need to set the callback differently, I have edited my answer. for more informations about callbacks look the exemples here : secure.php.net/manual/en/language.types.callable.php – mmm Apr 1 '18 at 22:34
  • Thank you for this. While I am not having this particular issue, your answer may actually provide me with a solution to a different problem :) – Cedon Apr 1 '18 at 22:42

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.