0

I'm working on a plugin where the user can build a form and then display that form on the front end using a shortcode name of their choice.

In the database I have a list of form names, and the necessary data to render them, but I can't figure out how to dynamically register the shortcode function.

Below is some psudeo code that shows what I want to do. In it I query my database and pull out an object which contains the name of the form and a some json strings which I can parse and use to call a premade function with parameters:

foreach ($dbQuery as $row){
  function $row->formName(){ // I know I can't do this
    $internalFunction = json_decode($row->json)->internalFunctionName; // dynamically refrence predefined function
    $internalFunction(json_decode($row->json)->params); // call the function defined above
    // do other things with the string from the database
  }
  add_shortcode( $row->formName, $row->formName );
}

I looked up if php supports dynamic function names, and I found this SO post which says it only supports dynamic closures. I tried using them but wordpress throws an error saying the shortcode doesn't have a proper callback function. So I think it wants a real function.

I also found a similar question on this site, but didn't see how this would let me define my own code in the function.

Any help would be much appreciated!

2

Assuming the $row->internalFunction is a function, or the name of a function which already exists, then you can do something like so:

foreach ( $dbQuery as $row ) {
    add_shortcode( $row->formName, $row->internalFunction );
}

So if the formName (shortcode tag) is foo and internalFunction is foo_func, then [foo] will be handled by the foo_func() function:

// The standard/non-dynamic way.
function foo_func( $atts = array() ) {
    return 'something good..';
}
add_shortcode( 'foo', 'foo_func' );

See the Codex for further details/guide.


Or here's an example of using closure:

foreach ( $dbQuery as $row ) {
    $func = $row->internalFunction;
    add_shortcode( $row->formName, function ( $atts = array() ) use ( $func ){
        return $func( $atts );
    } );
}

Or did I misunderstand your concept?

UPDATE

is there a way I can pass parameters into the internal function

Yes, you can pass custom parameters to the internal function (internalFunction); but you'll do it via the closure:

foreach ( $dbQuery as $row ) {
    $func = $row->internalFunction;
    $params = json_decode( $row->json )->params;
    add_shortcode( $row->formName, function ( $atts = array() ) use ( $func, $params ){
        return $func( $params );
    } );
}

Basically, use the use keyword to make variables in the foreach scope be available in the closure.

And you could even pass the entire $row object..

foreach ( $dbQuery as $row ) {
    add_shortcode( $row->formName, function ( $atts = array() ) use ( $row ){
        $func = $row->internalFunction;
        // Here you can pass $row->formName to the function.
        return $func( json_decode( $row->json )->params );
    } );
}
| improve this answer | |
  • That's almost perfect, but is there a way I can pass parameters into the internal function? Sorry I didn't specify that, edited my question. – YAHsaves Mar 24 '19 at 6:56
  • Also just to clarify, I don't want the parameters sent to the internal function to be shortcode defined attributes. I really just need the name of the form sent to that function so I know which form I am rendering. – YAHsaves Mar 24 '19 at 7:12
  • 1
    Please check the revised answer. – Sally CJ Mar 24 '19 at 7:34

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.