0

I am having some trouble implementing a class structure to use for plugins I am developing. What I am trying to do is create a class I can just re-use for each plugin.

I want it to be able to be extendable so that if I need specific output to change I can just do so from that specific plugin and not have to worry about changing the base class(es).

The biggest issue I seem to be having is with calling the callback functions if they are located in another class.

Here is a general idea of what my base class is looking like:

class Register_Settings {

// This stores all the saved settings to fill in the form fields with saved values
protected $saved_settings = array();

...

// This for loop runs through the settings array that is passed in to create everything
foreach ( $options as $option => $v ) {
    add_settings_field(
        $section . '[' . $v['id'] . ']',
        $v['name'],
        method_exists( $this, $v['type'] . '_callback' ) ? array( $this, $v['type'] . '_callback' ) : array( $this, 'missing_callback' ),
        $section,
        $section,
        $this->get_settings_field_args( $v, $setting )
    );
}

...
}

This works great if I keep the callbacks in the base class. What I actually want to do is use another class for all of the callbacks though. Something like this:

class Register_Settings_Callbacks extends Register_Settings {

public function text_callback( $args ) {

    $value = $this->settings[ $args['id'] ];

    echo '<input type="text" value="' . esc_attr( $value ) . '" />';
}

...
}

Once I try to do this it stops working. The issue I know from the above examples is this line:

    method_exists( $this, $v['type'] . '_callback' ) ? array( $this, $v['type'] . '_callback' ) : array( $this, 'missing_callback' ),

I have tried doing several different things to fix this:

    method_exists( 'Register_Settings_Callbacks', $v['type'] . '_callback' ) ? array( 'Register_Settings_Callbacks', $v['type'] . '_callback' ) : array( 'Register_Settings_Callbacks', 'missing_callback' ),

This fixes some of the errors, but then I get some errors about the class being called statically and I don't want that.

That leads me to try something like this:

   $test_class = new Register_Settings_Callbacks();

which turns the questioned line into:

    method_exists( $test_class, $v['type'] . '_callback' ) ? array( $test_class, $v['type'] . '_callback' ) : array( $test_class, 'missing_callback' ),

This does get rid of all the errors, but when I do it this way my class variables don't get inherited.

Could this be because of a mistimed hook? Am I not understanding the variables passing over between the two correctly?

Any thoughts?

If you need to see more of my class then let me know and I can try and lay some more of it out.

Thanks!


Edit:

Thanks to @toscho for getting me going in the right direction so far.

I have changed my trouble line above to this now:

    method_exists( new Settings_Callbacks( $this ), $v['type'] . '_callback' ) ? array( new Settings_Callbacks( $this ), $v['type'] . '_callback' ) : array( new Settings_Callbacks( $this ), 'missing_callback' ),

And my class that uses this is setup like this:

class Settings_Callbacks {

public function callback_A( $args ) { }

public function callback_B( $args ) { }

public function callback_C( $args ) { }

...
}

As pointed out below I opted not to use an Interface for this part because I don't want to redefine every function. What I instead want to do is have a base set of callbacks here that I commonly use for all my plugins, but if I need a specific functionality I can do something like this:

class Settings_Callbacks_Child extends Settings_Callbacks {

public function callback_D( $args ) { }

public function callback_E( $args ) { }

public function callback_F( $args ) { }

...
}

The problem with this boils back down to the callback function looking for a specific method. Since this is a child class it doesn't actually find the method in question, even if I have defined it here.

So I guess is there some way to check also for an unknown child class name and check it's methods as well?

  • 1
    Welcome to inheritance hell. Use composition, not inheritance when you want to write OOP. – fuxia Feb 22 '15 at 6:08
  • Define "stops working" please. :) – Rarst Feb 22 '15 at 10:15
  • @Rarst If it is all in one class then the options save and output correctly, but if I put it into two classes with the callbacks separated then the options no longer save or output correctly. – Nick Young Feb 22 '15 at 17:38
  • @toscho I just read the article you linked to and that's very interesting. Thanks for the link. So going by the article if I make an Interface I can just implement that instead of extending a class, is that how it works? I don;t have much experience with Interfaces. Thanks! – Nick Young Feb 22 '15 at 17:47
  • @NickYoung Yes, you pass an extra object for the callback handler into the main class. – fuxia Feb 22 '15 at 17:49

Your Answer

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

Browse other questions tagged or ask your own question.