私はタブ付きギャラリーのためにいくつかの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要素にこれに関する問題は、メインとネストされたショートコード関数にアクセス可能な変数を必要とすることです(私は思う)。
私のショートコードプラグインでの試みは以下の通りです(インストールを試みると致命的なエラー)。私は私の既存のコードを修正するか、あるいは問題へのより良いアプローチに関するアドバイスをいただければ幸いです。
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>';
}
ちょっとした横の思考とたくさんのテストの後、私はスコープをまたぐ変数の必要性を否定する解決策を思いつくことができました。
コードは次のようになります。
$content
を使用して、ネストされたpreg_match_all
(ネストされたショートコード)を単一のショートコードに分割するdo_shortcode
を適用します。preg_match
関数によって2つのストリングに分割されるストリングを返します。1番目はメインコンテンツデータ、2番目はnav
データです。私は以下のコードのスリムダウンバージョンを提供しました。これらすべてがうまくいくためのトリックは、ショートコードを分離するための堅牢なpreg_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のタブ機能で処理する準備ができました!