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

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

新規登録して質問してみよう
ただいま回答率
85.50%
WordPress

WordPressは、PHPで開発されているオープンソースのブログソフトウェアです。データベース管理システムにはMySQLを用いています。フリーのブログソフトウェアの中では最も人気が高く、PHPとHTMLを使って簡単にテンプレートをカスタマイズすることができます。

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

プラグイン

プラグイン(plug-in)は、ソフトウェアアプリケーションの機能拡張の為に開発された、一組のソフトウェアコンポーネントのことを指します。

Q&A

解決済

1回答

862閲覧

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

ayala

総合スコア6

WordPress

WordPressは、PHPで開発されているオープンソースのブログソフトウェアです。データベース管理システムにはMySQLを用いています。フリーのブログソフトウェアの中では最も人気が高く、PHPとHTMLを使って簡単にテンプレートをカスタマイズすることができます。

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

プラグイン

プラグイン(plug-in)は、ソフトウェアアプリケーションの機能拡張の為に開発された、一組のソフトウェアコンポーネントのことを指します。

0グッド

0クリップ

投稿2020/01/10 09:42

編集2020/01/11 10:02

前提・実現したいこと

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

###質問

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

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

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

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

#####エラーメッセージ

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

該当のソースコード

PHP

1<?php 2/* 3Plugin Name: Extraction_Text_Test 4Description: テキストを抽出するプラグイン 5Author: ayala 6Version: 0.1 7Author URI: 8*/ 9 10function extraction_test_func($atts) { 11 12 $html = $atts[html]; 13 $start_leng = $atts[start]; 14 $end_leng = $atts[end]; 15 16 $ch = curl_init(); 17 curl_setopt($ch, CURLOPT_URL, $html); 18 curl_setopt($ch, CURLOPT_HEADER, false); 19 curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); 20 curl_setopt($ch, CURLOPT_TIMEOUT, 60); 21 $json = curl_exec($ch); 22 curl_close($ch); 23 $result = json_decode($json, true); 24 25 $start = mb_strpos($json,$start_leng); 26 $end = mb_strpos($json,$end_leng); 27 $extraction = mb_substr($json, $start, $end-$start); 28 29 // echo $json; 30 31 echo $extraction; 32 33} 34add_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

1<?php 2/* 3Plugin Name: Extraction_Text_Test 4Description: テキストを抽出するプラグイン 5Author: ayala 6Version: 0.1 7Author URI: 8*/ 9 10function extraction_test_func($atts) { 11 12$html = 'https://www.yahoo.co.jp/'; 13$start_leng = '<tr><td>・<a href'; 14$end_leng = '<tbody><tr>'; 15 16$ch = curl_init(); 17curl_setopt($ch, CURLOPT_URL, $html); 18curl_setopt($ch, CURLOPT_HEADER, false); 19curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); 20curl_setopt($ch, CURLOPT_TIMEOUT, 60); 21$json = curl_exec($ch); 22curl_close($ch); 23$result = json_decode($json, true); 24 25 26 27$start = mb_strpos($json,$start_leng); 28$end = mb_strpos($json,$end_leng); 29$chushutu = mb_substr($json, $start, $end-$start); 30 31// echo $json; 32 33echo $chushutu; 34 35} 36add_shortcode( 'extraction_test', 'extraction_test_func' ); 37

試したこと2

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

PHP

1var_dump($atts['start']); 2var_dump($start_leng); 3var_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 テーマ)

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

CHERRY

2020/01/10 21:49

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

2020/01/11 09:44

質問ありがとうございます。 echo $json; var_dump $json; ともに表示されましたので、入っていると思います。
guest

回答1

0

ベストアンサー

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/10 13:10

編集2020/01/13 09:21
退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ayala

2020/01/10 15:29

返答ありがとうございます!  return $extraction; 試したのですが変わらず何も表示されません。 ちなみに「きちんと表示されるソースコード」で表記したコードでは 「return」ではなく「echo」を使っていますが、表示されました。
退会済みユーザー

退会済みユーザー

2020/01/11 00:15

追記しました
ayala

2020/01/11 09:56

ありがとうございます。 修正しても表示はされませんでした。 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) 表示されました。
ayala

2020/01/11 10:03

returnの件、了解いたしました。
退会済みユーザー

退会済みユーザー

2020/01/11 23:26

>mb_strpos を通るところで駄目になっていると思うのですがいかがでしょう。 多分そうですね。 デバッグモードを有効にすればどこかでエラーが出ていると思うので試してみてください。
退会済みユーザー

退会済みユーザー

2020/01/12 08:17

よく見たら無意味なHTMLタグや閉じられていないHTMLタグが問題なんでしょうね。 ショートコードに渡す値はメタボックスを設けてカスタムフィールドを使った方が無難でしょう。
ayala

2020/01/12 10:21

デバックモードは以下のやり方で良いでしょうか? wp-config.phpに↓を記述 define('WP_DEBUG', true); if (WP_DEBUG) { //デバッグモードの場合 define('WP_DEBUG_LOG', true); //debug.logファイルに記録 define('WP_DEBUG_DISPLAY', true); //エラーをブラウザに表示 } これを試した所、ブラウザの表示は変わらずエラーは表示されませんでした。 /wp-content/ ディレクトリにも debug.log はありませんでした。
退会済みユーザー

退会済みユーザー

2020/01/12 11:17

デバックモードの方法は間違っていないと思います。 エラーは無いとの事ですが『該当のソースコード』で提示されたショートコードを実行してみましたがmb_strposの行でエラーになります。 原因は先のコメントに書いた通りHTMLタグの問題で$attsの中身が不足しています。 とりあえずカスタムフィールドを利用した方が無難かと思いますが『該当のソースコード』で提示されたショートコードを実行した際の$attsの中身はどうなっていますか?
ayala

2020/01/12 14:30

$html = $atts['html']; $start_leng = $atts['start']; $end_leng = $atts['end']; で記述するとエラーが表示されない $html = $atts[html]; $start_leng = $atts[start]; $end_leng = $atts[end]; で記述すると、12,13,14行で 「Use of undefined constant html - assumed」 というエラーが表示される状態です。 これより↓の検証は、どちらの記述でも同じ結果が返ってきました。 var_dump ($html); var_dump ($start_leng); var_dump ($end_leng); を試した所 string(24) "https://www.yahoo.co.jp/" string(33) "<tr><td>・<a href" string(23) "<tbody><tr>" と表示されました。 var_dump ($atts); を試した所 array(3) { ["html"]=> string(24) "https://www.yahoo.co.jp/" ["start"]=> string(33) "<tr><td>・<a href" ["end"]=> string(23) "<tbody><tr>" } と表示されました。
ayala

2020/01/12 14:32

Space-Monkey様が仰っていた、カスタムフィールドを利用したやり方をやってみたところ 無事表示されました! 以下のプラグインを作成し、カスタムフィールドを使って文字を入力しました。 <?php /* Plugin Name: Extraction_Custom_Filed Plugin URI: Description: テキストを抽出するプラグイン Author: my name Version: 0.1 Author URI: */ function getExtraction() { $html = get_post_meta(get_the_ID(), 'html', true); $start_leng = get_post_meta(get_the_ID(), 'start', true); $end_leng = get_post_meta(get_the_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); // echo $json; return $extraction; } add_shortcode('viewExtraction', 'getExtraction');
ayala

2020/01/12 14:38

最初の問題は解決していませんが、質問の目的は達成したのでとりあえずお礼をさせていただきます。 この度は、親身に長く対応していただき深く感謝しています。 長く悩んでいた問題ですが、とりあえずの着地点を見つけられました。 Space-Monkey様の、カスタムフィールドの助言のコメントをベストアンサーにしたいのですがコメント欄での返答に対してははできないようです。 ですので今一度、解答欄にて記載いただければベストアンサーとしたいと思います。
ayala

2020/01/12 15:20

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

退会済みユーザー

2020/01/13 09:28

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

2020/01/14 09:34

わざわざ、新たにコードも書いていただいてありがとうございます! 試した所、ダブルクオーテーションが含まれるワードを入れるとそこからはじかれるようです。 なるほど、一度で済ましたほうが効率的ですね。 本当にありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問