2

I hope you all having a great day. I'm developing a video player plugin with custom shortcodes and stuff but I'm having a problem with the shortcode render. Currently, my shortcode content is rendered with echo which works fine but it doesn't render inside the page content so I have to change it to return method somehow but it has foreach loops and if else statements inside it so I can't just do return '<ul> '.foreach($x as $s){}.' </ul> '; and stuff, do you guys know a workaround for this? I've also tried to place everything inside a function and tried to render it inside return like this: return ' '.renderdata().' '; which works but again it doesn't render inside the content.

Here's my shortcode function

function myshortcode( $atts = array() ) {
    $data = ['some array with video data'];
    
    foreach($data as $d){
        echo "<div>$d</div>";
    }
}
add_shortcode('someshortcode', 'myshortcode'); 

Any help is much appreciated, thank you.

EDIT: I was able to handle the problem with PHP Output Buffering, thanks to WordPress Codex.

Solution:

function myshortcode() {
    ob_start();
    // HTML here
    return ob_get_clean();
}
0

1 Answer 1

3

Good to hear that you managed to solve the problem already. Here's a few examples on how you could also return html from a shortcode.

As you already found out, you can use ob_start() and ob_get_clean() to buffer the html. Inside it you can echo the markup or drop out of PHP and write plain HTML.

function my_shortcode() {
    ob_start();
    echo '<div>some HTML here</div>';
    ?>
    <p>Or outside of the PHP tags</p>
    <?php
    return ob_get_clean();
}

If the shortcode is within a theme, then you could also use get_template_part() with the output buffering. This way you can make the shortcode callback a little cleaner looking as the HTML will find its home in a separate file. You can also pass data to the template part, if needed.

function my_shortcode() {
    $template_part_args = array(
        'key' => 'value',
    );
    
    ob_start();
    get_template_part(
        'path/to/template/part',
        'optional-name', // use null, if not named
        $template_part_args // access with $args in the template part file
    );
    return ob_get_clean();
}

As Rup noted in the comments, one option is to concatenate the html to a string variable and then return that.

function my_shortcode() {
    $output = '<div>';
    $output .= 'Some HTML here';
    $output .= '</div>';
    return $output;
}

Personally, I like to use sprintf() for returning in a similar situation. I think it makes the code clean looking and makes adding escaping a breeze.

function my_shortcode() {
    return sprintf(
        '<div>
            <p>%s</p>
            <div>%s</div>
        </div>',
        esc_html('Some HTML here'),
        esc_html('Additional nested HTML')
    );
}

Especially with lists, I tend to build an array of the list items, which are imploded into a string. But you can use the same idea to push various HTML strings into an array, which is turned into one string on output return.

function my_shortcode() {
    $list_items = array();

    foreach ($some_array as $value) {
        $list_items[] = sprintf(
            '<li>%s</li>',
            esc_html($value)
        );
    }

    return '<ul>' . implode('', $list_items) . '</ul>';
}
2

Your Answer

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

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