访问变量的嵌套短码函数

时间:2018-03-05 作者:Kayboy Bebop

我一直在尝试制作一个短代码函数,为选项卡式图库输出一些html,但很多天之后,我还没有走多远。下面是一个短代码示例:

[thumbTab id="test1" nav="top" shadow="off"]
    [imgTab id="1" src="source1" width="1280" height="720" ]
    [vidTab id="2" src="source2" width="1280" height="720" ]
    [htmlTab id="4" preview_src="source3"] Other HTML stuff in here [/html]
[/thumbTab]
我希望返回的html如下所示(例如简化):

<div>
    <nav>
        <img .../>    /* 1st nested shortcode */
        <img.../>     /* 2st nested shortcode */
        <img.../>     /* 3st nested shortcode */
    </nav>
    <div>
        <img.../>         /* 1st nested shortcode */
        <video.../>       /* 2st nested shortcode */
        <section.../>     /* 3st nested shortcode */
    </div>
</div>
因此,我需要嵌套的短代码将数据输出到nav 将和标记到div元素中。问题是(我认为)它需要一个可以访问main和嵌套shortcode函数的变量,这正是我一直坚持的。

下面是我尝试使用shortcode插件的情况(尝试安装时出现致命错误)。如果能对我现有的代码进行更正,或者能提供更好的解决问题的方法,我将不胜感激。

add_shortcode(\'thumbTab\', \'thumbTab_func\');

function thumbTab_func( $atts, $content = null ) {  
    $a = shortcode_atts( array(
        \'id\' => \'theID\',
        \'nav\' => \'top\',
        \'shadow\' => \'off\'
    ), $atts );

    class thumbTab_class
    {
        //Array to hold tabbed content
        $tabCon = array();

        //Array to hold navigation tabs
        $navCon = array();

        //run nested shortcodes
        do_shortcode( $content, $ignore_html = false); 

        //combine $navCon array elements into the navigation tab html
        function navCreate(){
            $navReturn = \'<div><nav><ul>\';
            for ($i = 0; $i < count($this->navCon) ; ++$i) {
                $navReturn .= $this->navCon["$i"];
            }
            $navReturn .= \'</ul></nav></div>\';
            return $navReturn;
        }
        //combine $tabCon array elements into tabbed content html
        function tabCreate(){
            $tabReturn = \'\';
            for ($i = 0; $i < count($this->tabCon) ; ++$i) {
                $tabReturn .= $this->tabCon["$i"];
            }
            $tabReturn .= \'</ul></nav></div>\';
            return $tabReturn;
        }

        // Assigning processed html code to variable
        $thumbReturn = \'<div id="\'.$a["id"].\'" class="thumbTAB">\';
        $thumbReturn .= navCreate();
        $thumbReturn .= tabCreate();
        $thumbReturn .= \'</div>\';

    }

    $thumbTab_class = new thumbTab_class();

    // output processed html
    return $thumbTab_class->thumbReturn; 

}

//One nested shortcode function for testing
add_shortcode(\'imgTab\', \'imgTab_func\');

function imgTab_func( $atts ) { 
    $a = shortcode_atts( array(
        \'id\' => \'no_order\',
        \'src\' => \'no_source\',
        \'width\' => \'100%\',
        \'height\' => \'auto\'
    ), $atts );

    //create baseline structure
    $img = \'<img src="\'.$a["src"].\'" width="\'.$a["width"].\'" height="\'.$a["height"].\'">\';

    //assign tabbed html string to tabCon array using the id number to place in order
    $this->tabCon["a[\'id\']"] = \'<section class="tabPage tabPage_\'.$a["id"].\'>\'.$img.\'</section>\';

    //same for nav html string
    $this->navCon["a[\'id\']"] = \'<li class="sDS tabHeader_\'.$a["id"].\'">\'.$img.\'</li>\';
}

1 个回复
最合适的回答,由SO网友:Kayboy Bebop 整理而成

在进行了一些横向思考和大量测试之后,我能够想出一个解决方案,消除了跨范围变量的需要,或者使用了一个全局变量。

代码如下:

拆分嵌套的$content(嵌套的短代码)到具有preg_match_alldo_shortcode 对于每个带有for循环的短码,每个嵌套的短码函数返回一个字符串,该字符串将被另一个字符串拆分为两个字符串preg_match 函数,第一个是主要内容数据,第二个是nav 数据将所有主要内容数据分配给一个数组,将导航数据分配给另一个数组,然后只需处理两个数组并返回字符串我在下面提供了我的代码的精简版本。实现这一切的诀窍是使用一个健壮的preg\\u match表达式来分离短代码,这样在输入不规则的用户数据时它们就不会中断。

<?php
add_shortcode(\'tabs\', \'tabs_func\');
//Main shortcode function
function tabs_func( $atts, $content = null ) {  
    $a = shortcode_atts( array(
        \'id\' => \'\',
    ), $atts );

    //array to store nav data
    $navCon = array();

    //array to store main content data
    $tabCon = array();

    /* 
    Preg_match_all splits $content into predefined individual shortcodes [imgTab], [vidTab] and [htmlTab][/htmlTab]

    A basic explanation of the expression I used. If you want a more detailed breakdown, plug the expression below into "https://regexr.com/"

        (?<!\\[)    <= checks if there\'s a square bracket behind the proceeding match, to avoid matching escaped shortcode
        \\[    <= matches the opening bracket
        (?:(?:imgTab|vidTab).*(?<!\\])\\](?!\\])|htmlTab[\\S\\s]*?\\[\\/htmlTab\\](?!\\]))    <= can\'t break this into parts easily, but in essence this part tries to match a string which next part goes \'imgTab\', \'vidTab\', or \'htmlTab\' (although the \'htmlTab\' is put in it\'s own non-capture group as it has to deal with possible linebreaks). It then matches the remaining characters until it gets to a closing square bracket (or in the case of htmlTab, \'[/htmlTab]. It then checks that there aren\'t two closing brackets next to each other before finishing the match. 
    */
    preg_match_all( \'@(?<!\\[)\\[(?:(?:imgTab|vidTab).*(?<!\\])\\](?!\\])|htmlTab[\\S\\s]*?\\[\\/htmlTab\\](?!\\]))@\', $content, $matches );   

    $matchLI = 1;
    //loops through each of the shortcode matches
    foreach ($matches[0] as $match) {

        //runs current shortcode and assigns to variable
        $match_processed = do_shortcode($match);

        /*
        This expression is much more simple than the last one :D

            ([\\S\\s]+)    <= this capture group basically takes all the characters that aren\'t matched by the next part of the expression. This capture group contains the main content
            (<[\\S\\s]+>)    <= this capture group matches a \'less-than\' character, a string of any characters and finally a \'greater-than\' character. Since this expression is greedy it won\'t false match any \'greater-than\' symbols in the first capture group, as it will look for the last \'greater-than\' in the string
        */
        preg_match( \'@([\\S\\s]+)(<[\\S\\s]{4,}>)@\', $match_processed, $navMatch );

        //assigns nav data of current shortcode to the $navCon array, using the $matchLI value to index it
        $navCon[$matchLI] .= "<li class=\'nav_NUM_" . $matchLI . "\'>" . $navMatch[2] . "</li>";

        //assigns main content data of current shortcode to the $tabCon array, using the $matchLI value to index it
        $tabCon[$matchLI] = "<section class=\'content_NUM_" . $matchLI . "\'>" . $navMatch[1] . "</section>";
        }

        //increments the value for the next loop
        $matchLI++;

    }

    //constructing html in $tabReturn variable
    $tabReturn = "<div id=\'" . $a[\'id\'] . "\'>";
    $tabReturn .= "<nav><ul>";
    //loops through and assigns content of $navCon array to $tabReturn
    foreach ($navCon as $navElement) {
        $tabReturn .= $navElement;
    }
    $tabReturn .= "</ul></nav>";
    //loops through and assigns content of $tabCon array to $tabReturn
    foreach ($tabCon as $tabElement) {
        $tabReturn .= $tabElement;
    }
    $tabReturn .= "</div>";

    //finished html string is returned. Mission complete!
    return $tabReturn;

}

add_shortcode(\'imgTab\', \'imgTab_func\');
function imgTab_func( $atts ) { 
    $a = shortcode_atts( array(
        \'src\' => \'\',
        \'width\' => \'100%\',
        \'height\' => \'auto\'
    ), $atts );

    //First img element is the main content, and the second is the nav preview 
    return "<img src=\'" . $a[\'src\'] . "\' width=\'" . $a[\'width\'] . "\' height=\'" . $a[\'height\'] . "\'>
    <img src=\'". $a[\'src\'] . "\' width=\'" . $a[\'width\'] . "\' height=\'" . $a[\'height\'] . "\'>";


}

add_shortcode(\'vidTab\', \'vidTab_func\');
function vidTab_func( $atts ) { 
    $a = shortcode_atts( array(
        \'poster\' => \'\',
        \'src\' => \'\',
        \'width\' => \'100%\',
        \'height\' => \'auto\'
    ), $atts );

    //vid element is the main content, and the img is the nav preview 
    return "<video width=\'" . $a[\'width\'] . "\' height=\'" . $a[\'height\'] . "\' poster=\'" . $a[\'poster\'] . "\' controls>
        <source src=\'" . $a[\'src\'] . "\' type=\'video/mp4\'>
    </video>
    <img src=\'". $a[\'poster\'] . "\' width=\'" . $a[\'width\'] . "\' height=\'" . $a[\'height\'] . "\'>";

}

add_shortcode(\'htmlTab\', \'htmlTab_func\');
function htmlTab_func( $atts, $content = null ) {   
    $a = shortcode_atts( array(
        \'poster\' => \'\',
        \'width\' => \'100%\',
        \'height\' => \'auto\'
    ), $atts );

    //$content is the main content, and the img is the nav preview.
    return $content . "<img src=\'". $a[\'poster\'] . "\' width=\'" . $a[\'width\'] . "\' height=\'" . $a[\'height\'] . "\'>";
}
以及用户将在文本编辑器中键入的短代码:

[tabs id="test1"]

//any number and combination of these elements

[imgTab src="imgTab.jpg" width="100" height="100"]

[vidTab poster="vidTab.jpg" src="vidTab.mp4" width="128" height="72"]

[htmlTab poster="htmlTab.jpg" width="100" height="100"] 
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam scelerisque maximus neque gravida gravida.</p>
[/htmlTab]

[/tabs]
输出应该是这样的:

<div id=\'test1\'>
    <nav><ul>
        <li class=\'nav_NUM_1\'> 
            <img src=\'imgTab.jpg\' width=\'100\' height=\'100\'>
        </li>
        <li class=\'nav_NUM_2\'> 
            <img src=\'vidTab.jpg\' width=\'128\' height=\'72\'>
        </li>
        <li class=\'nav_NUM_3\'> 
            <img src=\'htmlTab.jpg\' width=\'100\' height=\'100\'>
        </li>
    </ul></nav>
    <section class=\'content_NUM_1\'>
        <img src=\'imgTab.jpg\' width=\'100\' height=\'100\'>
    </section>
    <section class=\'content_NUM_2\'>
        <video width=\'128\' height=\'72\' poster=\'vidTab.jpg\' controls>
            <source src=\'vidTab.mp4\' type=\'video/mp4\'>
        </video>
    </section>
    <section class=\'content_NUM_3\'>
        <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam scelerisque maximus neque gravida gravida.</p>
    </section>
</div>
已准备好由javascript选项卡函数处理!

结束

相关推荐

在我的主题中包含一个PHP框架的正确方式是什么?

我正在使用Twitter Timeline PHP framework 显示包含收藏夹/转发交互的推文列表。目前我已经将其全部配置为独立的解决方案,我想知道将其纳入我的自定义Wordpress主题的最佳方式是什么。它是否像创建inc 文件夹,将所有文件放在其中,然后添加<?php include_once(\'inc/twitter.php\'); ?> 我希望推文显示在哪里?还是有更好的做法?