web-dev-qa-db-ja.com

Wordpressショートコードは値の配列を渡します

私はいくつかのWordPressページ(多くのコンテンツセクションとそれ自身のメニューを含む1ページ)の内部ナビゲーションを提供することを目的としたショートコードを作成しています。

これは私が持っているものです:

//menu
function internal_menu($atts) {
  extract(shortcode_atts(array(
   'href1' => '#jl1',
   'href2' => '#jl2',
   'href3' => '#jl3',
   'href4' => '#jl4',
  ), $atts));
  return '<div id="internalPageMenu">
    <ul>
        <li><a href="' . $href1 . '"><i class="fa fa-bars"></i>link 1</a></li>
        <li><a href="' . $href2 . '">link 2</a></li>
        <li><a href="' . $href3 . '">link 3</a></li>
        <li><a href="' . $href4 . '">link 4</a></li>
    </ul>
    </div>';
}
add_shortcode('internal-menu', 'internal_menu');

//menu target
function internal_menu_target($atts) {
  extract(shortcode_atts(array(
   'id' => 'jl1',
   'text' => '',
   ), $atts));
   return '<h3 id="' . $id . '">' . $text . '</h3>';
}
add_shortcode('internal-menu-target', 'internal_menu_target');

そしてこれを私のWordpress管理パネルで使用する:

[internal-menu]
[internal-menu-target id="jl1"]
Some content
[internal-menu-target id="jl2"]
...etc...

メニューを動的にするにはどうすればよいですか(メニューのアイテム数に制限されません)。たとえば、ショートコードは次のようになります。

[internal-menu targets="jl1, jl2, jl3, jl4, jl5, ...etc..."]
10
mcneela86

foreachがここでの答えになります。私の意見では、これが最も簡単でクリーンなものになるでしょう。コード例を示す前に、コードを分析して、すべての欠陥と、それらを修正する方法を見てみましょう。

欠陥

  • extract()は絶対に使用しないでください。 exctract()は、問題のある変数をその場で作成します。 extract()できれば)を適切にデバッグすることはできません。そのため、失敗した場合は、不必要に作業を切り詰めてしまいます。これらの理由により、コアとコーデックスから完全に削除されました。 trac ticket 224 を参照してください。 _query_posts_とextract()が上位2つの位置にある邪悪なリストがあるはずです。これは、これら2つがどれほど悪いかです。

  • サイトをハッキングするためにハッカーがコードにjqueryを挿入する可能性のある入力データをサニタイズおよび検証していません。 決してユーザー側とURLからのデータを信頼しないでください。感染している可能性があります。

  • すでにご存知のように、コードから取得したショートコードは配列値を除くことはできません。値は文字列である必要があります。あなたの場合、文字列値から配列を作成する必要があります。繰り返しになりますが、カンマの前後にスペースを使用しないことをユーザーに信頼することはできないため、explode関数が配列を正しく作成するために、空白がある場合はすべて削除することをお勧めします。

  • この新しいアプローチでは、文字列の値が正しい順序であり、文字列が正しい長さであることを確認する必要があります。そうでない場合は、予期しない出力が得られます

最初のショートコードに取り組みましょう:(注意:すべてのコード以下はテストされていません。バグがあるか、構文エラーがある可能性があります

_internal-menu_

_//menu
function internal_menu( $atts ) 
{
    $attributes = shortcode_atts(
        array(
           'href' => '',
         ), 
        $atts
    );

    $output = '',
    // Check if href has a value before we continue to eliminate bugs
    if ( !$attribute['href'] )
        return $output;
    // Create our array of values
    // First, sanitize the data and remove white spaces
    $no_whitespaces = preg_replace( '/\s*,\s*/', ',', filter_var( $attributes['href'], FILTER_SANITIZE_STRING ) ); 
    $href_array = explode( ',', $no_whitespaces );

    $output .= '<div id="internalPageMenu">';
        $output .= '<ul>';

            foreach ( $href_array as $k => $v ) { 
                // From your code, link 1 is different, so I kept it as is
                if ( $k == 0 ) {
                    $output .= '<li><a href="#' . $v . '"><i class="fa fa-bars"></i>link 1</a></li>';
                } else { 
                    $output .= '<li><a href="#' . $v . '">link ' . ($k + 1 ) . '</a></li>';
                }
            }

        $output .= '</ul>';
    $output .= '</div>';

    return $output;
}
add_shortcode( 'internal-menu', 'internal_menu' );
_

その後、次のようにショートコードを使用できます

_[internal-menu href='jl1, jl2, jl3, jl4']
_

_internal-menu-target_

_//menu target
function internal_menu_target($atts) 
{
    $attributes = shortcode_atts(
        array(
           'id' => '',
           'text' => '',
         ), 
        $atts
    );

    $output = '',
    // Check if href has a value before we continue to eliminate bugs
    if ( !$attribute['id'] || !$attribute['text'] )
        return $output;

    // Create our array of values
    // First, sanitize the data and remove white spaces
    $no_whitespaces_ids = preg_replace( '/\s*,\s*/', ',', filter_var( $attributes['id'], FILTER_SANITIZE_STRING ) ); 
    $ids_array = explode( ',', $no_whitespaces_ids );

    $no_whitespaces_text = preg_replace( '/\s*,\s*/', ',', filter_var( $attributes['text'], FILTER_SANITIZE_STRING ) ); 
    $text_array = explode( ',', $no_whitespaces_text );

    // We need to make sure that our two arrays are exactly the same lenght before we continue
    if ( count( $ids_array ) != count( $text_array ) )
        return $output;

    // We now need to combine the two arrays, ids will be keys and text will be value in our new arrays
    $combined_array = array_combine( $ids_array, $text_array );
    foreach ( $combined_array as $k => $v )
        $output .= '<h3 id="' . $k . '">' . $v . '</h3>';

    return $output;
}
add_shortcode('internal-menu-target', 'internal_menu_target');
_

このショートコードは次のように使用できます。

_[internal-menu-target id='1,2,3,4' text='text 1, text 2, text 3, text 4']
_
16
Pieter Goosen

問題:

Wordpressのショートコードには、渡すことができるデータの形式にいくつかの厄介な制限があります...

スペース区切り変数:

_[shortcode a="1 2"]_

結果:_$atts=['a'='"1', 0='2"']_

']'はショートコードを閉じます:

_[shortcode b=[yay]]_

結果:_$atts=['b'='[yay']_

解決:

urlencode()を使用すると、これを回避できます。

_[shortcode atts=a=1+2&b=%5Byay%5D]_

そのように解析します:

parse_string($atts['atts'],$atts);

結果:_$atts=['a'=>'1 2', b=>'[yay]']_

それはあなたが望む配列通過をあなたに与えるでしょう。

次に、メニューの作成について:

_function internal_menu($atts) {
  // allow passing + and ] in the text of the links:
  parse_string($atts["links"],$links);

  // the defaults, verbatim from the question:
  if (!count($links)) $links=[
    'href1' => '#jl1',
    'href2' => '#jl2',
    'href3' => '#jl3',
    'href4' => '#jl4',
  ];

  foreach ($links as $text=>$href) $ul=."<li><a href=\"$href\">$text</a></li>";

  return '<div id="internalPageMenu"><ul>'.$ul.'</ul></div>';
}

add_shortcode('internal-menu', 'internal_menu');

//menu target

function internal_menu_target($atts) {
  // allow passing + and ] in the text:
  if (@$atts[text]) $atts['text']) = urldecode($atts['text']);

  // the defaults, verbatim from the question:
  $atts=array($atts)+['text'=>'','id'=>'jl1'];

  return '<h3 id="' . $link['id'] . '">' . $link['text'] . '</h3>';
}

add_shortcode('internal-menu-target', 'internal_menu_target');
_

そしてそれをそのように供給します:

_[internal-menu links=First+Link=#jl1&Second+Link=#jl2&Google=https://google.com]

[internal-menu-target text=Section+1 id=jl1]
_

等.

ところで、extract()は、責任を持って使用すればまったく問題ありません。

_/* concatenates 3 words of wisdom into a polite policy direction
 *
 * @param $attr: hash of function args
 *          foo = the first Word (Kindly)
 *          bar = the second Word (ignore)
 *          baz = the third Word (totalitarians)
 */

function excellent_policy($attr){
  $defaults=['foo'=>'Kindly', 'bar'=>'ignore', 'baz'=>'totalitarians'];
  extract((array)array_intersect_key($attr,$defaults)+$defaults);
  echo "$foo $bar $baz!";
}
_

これにより、$ foo、$ bar、および$ bazが$ attrからローカルスコープに読み取り可能で予測可能な方法でインポートされ、渡されなかった場合にこれらの変数のデフォルトが提供され、予期しない変数が作成されるのを防ぎます。

言語機能を使用する良い方法と悪い方法があります。 禁止誰かが言語機能をうまく使用しない可能性があるため、誰もが言語機能を使用することを禁止するのは、誰かがゼリーを吸い込もうとする可能性があるため、誰もが呼吸を禁止するようなものです。

1
Wil

私が使用する簡単な方法:

[my param="key1=value1&key2=value2"]

ショートコードコールバックでは、次のようにします。

parse_str( str_replace("&amp;", "&", $attrs['param']), $array);
// var_dump( $array );
0
T.Todua