質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

87.37%

【表示されない】WordPressのショートコードを利用した、外部サイトの文字列抽出プラグインの作成

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 517

score 6

前提・実現したいこと

Wordpressのショートコードを利用した、外部サイトの文字列抽出プラグインの作成。

質問

Wordpress にて上記の内容のプラグインを自作しているのですが、表示されず悩んでいます。
ご教示願えればと思います。
プログラミングはかなりの初学者なので、用語など的はずれなこともあるかと思います。

発生している問題・エラーメッセージ

自作したプラグインで、URLのHTMLから任意の範囲の文字列を取得し、投稿にて表示させることはできました。

ショートコードから、「URL」「抽出したい文字列の始まり」「抽出したい文字列の終わり」
を指定して、表示させたいのですが真っ白なままで何も表示されません。

エラーメッセージ

エラーメッセージは無く何も表示されていない状態です。

該当のソースコード

<?php
/*
Plugin Name: Extraction_Text_Test
Description: テキストを抽出するプラグイン
Author: ayala
Version: 0.1
Author URI:
*/

function extraction_test_func($atts) {

  $html = $atts[html];
  $start_leng = $atts[start];
  $end_leng = $atts[end];

  $ch = curl_init();
  curl_setopt($ch, CURLOPT_URL, $html);
  curl_setopt($ch, CURLOPT_HEADER, false);
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  curl_setopt($ch, CURLOPT_TIMEOUT, 60);
  $json = curl_exec($ch);
  curl_close($ch);
  $result = json_decode($json, true);

  $start = mb_strpos($json,$start_leng);
  $end = mb_strpos($json,$end_leng);
  $extraction = mb_substr($json, $start, $end-$start); 

  // echo $json;

  echo $extraction;

}
add_shortcode( 'extraction_test', 'extraction_test_func' );

試したこと

「投稿の編集」「ビジュアルタブ」にショートコードを

[extraction_test html='' start='' end='']

という形で記載します。
例として実際に記載した内容が以下の通りになります。

[extraction_test html='https://www.yahoo.co.jp/' start='<tr><td>・<a href' end='<tbody><tr>']

こう記載すると、何も標示されません。

echo $atts[start];

echo $start_leng;
をプラグインに書き加えると、<tr><td>・<a hrefと表示されるので
ショートコードで指定した内容は渡っているようなのですが、何が問題なのでしょうか。

以下のように、ショートコードで「URL」「抽出したい文字列の始まり」「抽出したい文字列の終わり」を指定せず、プラグイン内で指定すると
きちんと表示されます。

[extraction_test]

以下がプラグイン内の記述です。

きちんと表示されるソースコード
<?php
/*
Plugin Name: Extraction_Text_Test
Description: テキストを抽出するプラグイン
Author: ayala
Version: 0.1
Author URI:
*/

function extraction_test_func($atts) {

$html = 'https://www.yahoo.co.jp/';
$start_leng = '<tr><td>・<a href';
$end_leng = '<tbody><tr>';

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $html);
curl_setopt($ch, CURLOPT_HEADER, false);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 60);
$json = curl_exec($ch);
curl_close($ch);
$result = json_decode($json, true);



$start = mb_strpos($json,$start_leng);
$end = mb_strpos($json,$end_leng);
$chushutu = mb_substr($json, $start, $end-$start); 

// echo $json;

echo $chushutu;

}
add_shortcode( 'extraction_test', 'extraction_test_func' );

試したこと2

var_dumpで以下の物を試しました。

var_dump($atts['start']);
var_dump($start_leng);
var_dump($start);

結果は
string(33) "<tr><td>・<a href"
string(33) "<tr><td>・<a href"
bool(false)

となりました。
ショートコードで指定した値は渡っているようなのですが
mb_strpos を通るところで駄目になっていると思うのですがいかがでしょう。

試しに
$start = mb_strpos($json,$start_leng);
ではなく
$start = mb_strpos($json,"<tr><td>・<a href");
と直接、検索文字を指定し
var_dump($start);
を試した所
int(7070)
表示されました。

補足情報(FW/ツールのバージョンなど)

WordPress 5.3.2 (Twenty Nineteen テーマ)

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • CHERRY

    2020/01/11 06:49

    $json に値は入っているのでしょうか?か

    キャンセル

  • ayala

    2020/01/11 18:44

    質問ありがとうございます。

    echo $json;
    var_dump $json;

    ともに表示されましたので、入っていると思います。

    キャンセル

回答 1

checkベストアンサー

+3

echo $extraction;ではなくreturn $extraction;でしょうね

追記
ちゃんと読んでませんでした。

修正すべき点は以下

$html = $atts[html];
$start_leng = $atts[start];
$end_leng = $atts[end];
↓
$html = $atts['html'];
$start_leng = $atts['start'];
$end_leng = $atts['end'];


きちんと表示されるソースコードとの違いは変数だけみたいなので変数の中身が問題無いかvar_dumpで確認してください。

ちなみにechoでも出力されたとのことですがショートコードはreturnしてください。
関数リファレンス/add shortcode

注意: ショートコードのコールバック関数は何も出力してはいけません。ショートコードを置き換えるために使われるテキストを返す必要があります。何か出力すると予期せぬ結果につながります。これはフィルター関数についても同様です。いつ、どこから呼び出されるかをあなたは制御できないので、呼び出されたときに副作用を引き起こしてはいけません。

更に追記
かなり適当ですが、私ならメタボックスを設けてしまいます。

function extraction_test_func() {
  #$html = $atts['html'];
  #$start_leng = $atts['start'];
  #$end_leng = $atts['end'];
  $post_id = get_the_ID();
  $html = get_post_meta( $post_id, 'html', true );
  $start_leng = get_post_meta( $post_id, 'start', true );
  $end_leng =  get_post_meta( $post_id, 'end', true );

  $ch = curl_init();
  curl_setopt($ch, CURLOPT_URL, $html);
  curl_setopt($ch, CURLOPT_HEADER, false);
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  curl_setopt($ch, CURLOPT_TIMEOUT, 60);
  $json = curl_exec($ch);
  curl_close($ch);
  $result = json_decode($json, true);

  $start = mb_strpos($json,$start_leng);
  $end = mb_strpos($json,$end_leng);
  $extraction = mb_substr($json, $start, $end-$start); 

  return $extraction;

}
add_shortcode( 'extraction_test', 'extraction_test_func' );

add_action( 'add_meta_boxes', function () {
    add_meta_box(
        'custom_fields_meta_box',
        'Fields',
        'my_custom_fields_meta_box',
        'post', 
        'normal',
        'high'
    );
} );

function my_custom_fields_meta_box() {
global $post;
    $html = get_post_meta( $post->ID, 'html', true );
    $start = get_post_meta( $post->ID, 'start', true );
    $end = get_post_meta( $post->ID, 'end', true );
    ?>
    <p>HTML: <input type="text" name="html" value="<?php echo $html; ?>" style="width:30%;"></p>
    <p>START: <input type="text" name="start" value="<?php echo $start; ?>" style="width:30%;"></p>
    <p>END: <input type="text" name="end" value="<?php echo $end; ?>" style="width:30%;"></p>
    <?php
}

add_action( 'save_post', function( $post_id ) {
    if ( isset( $_POST['html'] ) ) {
        update_post_meta( $post_id, 'html', $_POST['html'] );
    } else {
        delete_post_meta( $post_id, 'html' );
    }
    if ( isset( $_POST['start'] ) ) {
        update_post_meta( $post_id, 'start', $_POST['start'] );
    } else {
        delete_post_meta( $post_id, 'start' );
    }
    if ( isset( $_POST['end'] ) ) {
        update_post_meta( $post_id, 'end', $_POST['end'] );
    } else  {
        delete_post_meta( $post_id, 'end' );
    }
} );

釈然としないようなので更に追記しおきます。
上手くいかないコードの$attsの中身はこのようになっています。

Array
(
    [html] => https://www.yahoo.co.jp/
    [start] => 
    [end] => 

<tbody>
<tr>
)


これはshortcode_parse_atts()関数によって不正なHTMLタグが切り取られた結果で
shortcode_parse_atts() | Function | WordPress Developer Resources
Reject any unclosed HTML elements.と書かれおり、仕様なので仕方ありません。

回避策は
独自にthe_contentのフィルターフックを作成しその中で独自のshortcode_parse_atts()関数もどきを作成して不正なHTMLも通してしまう方法。
または
[]内の<>&lt;&gt;に変換して保存してショートコード実行時に元に戻す方法。

が考えられますが、カスタムフィールドを使用した方が操作性はいいでしょうね。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/01/13 00:20

    ちなみにカスタムフィールドのやり方は上記の記述で特に問題ありませんでしょうか。

    キャンセル

  • 2020/01/13 18:28

    特に問題ありませんが投稿IDを複数回取るのは無駄なので変数に収めるかget_post_custom()で一度に全てのメタ情報を取って割り振りした方がいいのかもしれませんんね。追記したコードはget_post_metaを三回書いてますが・・・w

    キャンセル

  • 2020/01/14 18:34

    わざわざ、新たにコードも書いていただいてありがとうございます!
    試した所、ダブルクオーテーションが含まれるワードを入れるとそこからはじかれるようです。

    なるほど、一度で済ましたほうが効率的ですね。

    本当にありがとうございます。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 87.37%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • トップ
  • PHPに関する質問
  • 【表示されない】WordPressのショートコードを利用した、外部サイトの文字列抽出プラグインの作成