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

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

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

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

正規表現

正規表現とは特定の文字列によるパターンマッチングを行う際に用いられる宣言型プログラミングです。

HTML

HTMLとは、ウェブ上の文書を記述・作成するためのマークアップ言語のことです。文章の中に記述することで、文書の論理構造などを設定することができます。ハイパーリンクを設定できるハイパーテキストであり、画像・リスト・表などのデータファイルをリンクする情報に結びつけて情報を整理します。現在あるネットワーク上のほとんどのウェブページはHTMLで作成されています。

Q&A

解決済

3回答

2546閲覧

PHP テキストエリアに入力された内容にURLの正規表現を行う

退会済みユーザー

退会済みユーザー

総合スコア0

PHP

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

正規表現

正規表現とは特定の文字列によるパターンマッチングを行う際に用いられる宣言型プログラミングです。

HTML

HTMLとは、ウェブ上の文書を記述・作成するためのマークアップ言語のことです。文章の中に記述することで、文書の論理構造などを設定することができます。ハイパーリンクを設定できるハイパーテキストであり、画像・リスト・表などのデータファイルをリンクする情報に結びつけて情報を整理します。現在あるネットワーク上のほとんどのウェブページはHTMLで作成されています。

0グッド

0クリップ

投稿2017/12/20 03:11

お世話になります。
下記につきまして、お知恵をお借りできますと幸いです。
宜しくお願い致します。

1、やりたいこと
別htmlファイルのテキストエリア(name="comment")に入力しsubmtした文字列から、
URLの部分を正規表現で抽出(該当する部分全て)し、画像アドレスか通常の
URLか分岐をさせた上で処理を行うこと
※hatenaやガールズちゃんねるの引用機能のようなものを
機能要件としてイメージしております

2、問題、つまづいている点
テキストエリアにURLを1つだけ(他には文字列を入力しない)入力した場合はちゃんと
最後まで処理ができるのですが、複数のURLをテキストエリアに入力した場合、
正規表現で抽出できない(//URLかどうかチェックでURLとして抽出できない)状況でございます。

3、お伺い自体事項
上記やりたいことに対して、どこを修正すると解決できるのか、
もしよろしければご教示頂けますと幸いでございます。
宜しくお願い致します。

<?php //画像と引用に関しての分岐処理 $base = htmlspecialchars($_POST['comment'],ENT_QUOTES,'utf-8'); $base = nl2br($base); //URLかどうかチェック if (preg_match_all('/^(https?|ftp)(://[-_.!~*\'()a-zA-Z0-9;/?:\@&=+$,%#]+)$/', $base , $result)) { //URL認識 $path = $result[0][0]; //URLが生きているかどうかチェック $response = get_headers( $path ); if( strpos( $response[0],'OK' ) ) { $a = (get_headers($path,1)); //画像ファイルかどうかチェック if($a['Content-Type']=='image/jpeg' or $a['Content-Type']=='image/png' or $a['Content-Type']=='image/gif' or $a['Content-Type']=='image/svg+xml') { //画像ファイルとして格納 $img_url = $path; $img_output = "<img src='$img_url' style='width:300px; height:200px; border-radius:5px; margin:10px;'>"; $pattern = '/^(https?|ftp)(://[-_.!~*\'()a-zA-Z0-9;/?:\@&=+$,%#]+)$/'; $img_last = preg_replace($pattern,$img_output,$path); echo $comment."<br>"; echo $img_last; $comment = $img_last; }else { //引用として処理 echo "引用処理"; require_once("phpQuery-onefile.php"); $html = file_get_contents($path); $doc = phpQuery::newDocument($html); $content = $doc['body']->text()."\r\n"; $description = $doc['meta[name=description]']->attr('content'); //識別可能なURLへ転換 $quote_url = $path; $quote_output = "quotedone:".$quote_url; $quote_pattern = '/^(https?|ftp)(://[-_.!~*\'()a-zA-Z0-9;/?:\@&=+$,%#]+)$/'; $quote_last = preg_replace($quote_pattern,$quote_output,$quote_url); echo $quote_last; } }{ //URL Not Found } } ?>

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

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

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

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

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

guest

回答3

0

ベストアンサー

正規表現の複数行用の修飾子/正規表現/mを使用すれば簡単に複数行に対応できます。1行目に改行が入っていても対応できます。

php

1$base = <<<EOF 2 3https://teratail.com/questions/105625 4http://example.com/?a=1&b=2 5ftp://example.com 6 7EOF; 8 9//m修飾子をつける 10preg_match_all('/^(https?|ftp)(://[-_.!~*\'()a-zA-Z0-9;/?:\@&=+$,%#]+)$/m', $base , $result); 11 12var_dump($result);

ただし、質問文のコードは$result[0][0]なので、最初のマッチ1個目のみ処理するようになっています。質問のために編集したのであれば問題はありませんが、いちおうサンプルを載せておきます。よくわからない変数が突然出てきたりしているので、関数**linkPathParser()**内は単純にコピーしただけです。

POSTを受け取る場合はfilter_input()を使うようにしたほうがよいと思います。PHPのPOST処理などは非常に便利です。フォーム処理はブラザーだけから値を渡すだけではなく、プログラムコードからも値を渡すことができますので。
http://php.net/manual/ja/function.filter-input.php
http://php.net/manual/ja/filter.filters.sanitize.php

また、strpos()で文字列マッチを行う場合は、必ずfalse !== strpos()またはstrpos() !== falseとします。こうしないと、ゼロ文字目(最初文字)と一致した場合はゼロを返すので、比較結果はfalseになってしまいます。

php

1//** 注意 ** 2//POSTを受け取る場合は`filter_input()`を使うようにしたほうがよいです 3//画像と引用に関しての分岐処理 4$base = filter_input(INPUT_POST, 'comment', FILTER_SANITIZE_FULL_SPECIAL_CHARS); 5//$base = htmlspecialchars($_POST['comment'],ENT_QUOTES,'utf-8'); 6 7//** 注意 ** 8//↓ここでnl2br()すると正規表現にマッチしなくなります 9//$base = nl2br($base); 10 11//URLかどうかチェック 12if (preg_match_all('/^(https?|ftp)(://[-_.!~*\'()a-zA-Z0-9;/?:\@&=+$,%#]+)$/m', $base , $result)) 13{ 14 foreach ($result[0] as $path) { 15 linkPathParser($path); 16 } 17} 18 19/** 20 * linkPathParser 21 * 22 * @param $path string URLパスまたは画像パス 23 * @return ??? 24 */ 25function linkPathParser ($path) 26{ 27 //URLが生きているかどうかチェック 28 $response = get_headers( $path ); 29 30 //** 注意 ** 31 //↓strpos()で文字列一致を行う場合は必ず「false !==」で比較します。 32 if( false !== strpos( $response[0],'OK' ) ) 33 { 34 $a = get_headers($path,1); 35 36 //画像ファイルかどうかチェック 37 if($a['Content-Type']=='image/jpeg' or $a['Content-Type']=='image/png' or $a['Content-Type']=='image/gif' or $a['Content-Type']=='image/svg+xml') 38 { 39 //画像ファイルとして格納 40 $img_url = $path; 41 $img_output = "<img src='$img_url' style='width:300px; height:200px; border-radius:5px; margin:10px;'>"; 42 $pattern = '/^(https?|ftp)(://[-_.!~*\'()a-zA-Z0-9;/?:\@&=+$,%#]+)$/'; 43 $img_last = preg_replace($pattern,$img_output,$path); 44 45 //???? 46 echo $comment."<br>"; 47 echo $img_last; 48 $comment = $img_last; 49 } else { 50 //引用として処理 51 echo "引用処理"; 52 require_once("phpQuery-onefile.php"); 53 $html = file_get_contents($path); 54 $doc = phpQuery::newDocument($html); 55 $content = $doc['body']->text()."\r\n"; 56 $description = $doc['meta[name=description]']->attr('content'); 57 58 //識別可能なURLへ転換 59 $quote_url = $path; 60 $quote_output = "quotedone:".$quote_url; 61 $quote_pattern = '/^(https?|ftp)(://[-_.!~*\'()a-zA-Z0-9;/?:\@&=+$,%#]+)$/'; 62 $quote_last = preg_replace($quote_pattern,$quote_output,$quote_url); 63 echo $quote_last; 64 } 65 } else { 66 //URL Not Found 67 } 68 69}

投稿2017/12/20 06:06

Tomak

総合スコア1652

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

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

退会済みユーザー

退会済みユーザー

2017/12/20 07:17

早々にありがとうございます! 早速組み込みまして、画像を1つ拾うことができるようになりました、 ありがとうございます!! 因みに、テキストエリアにサンプルとして以下を打ち込みまして、 プログラム中程にある echo $img_lastで表示をさせてみた所、一番最下行の画像だけブラウザに表示がされております。 <サンプルでテキストエリアに打ち込んだ内容> http://up.gc-img.net/post_img/2017/12/Ae5kSniH8SOmEhB_tjl69_17.jpeg, http://up.gc-img.net/post_img/2017/12/Ae5kSniH8SOmEhB_yvrLd_53.jpeg, http://up.gc-img.net/post_img_web/2017/12/d884640bee13f399ed74366de060a2c0_16640.jpeg 上記のように複数個画像URLを改行して打ち込んだ場合でも 全て表示するようにしてみたいのですが、プラスαですると良いこと等ございますでしょうか? 恐らく正規表現で3つ目のURLのみ合致してしまっている形になっていると想定しているのですが... 度々大変恐れ入ります.... 宜しくお願い致します。
Tomak

2017/12/20 08:08 編集

画像のURL最後に「,」を入れてPOSTしているため、画像のパスが下記のようになっているため画像として認識できていないためです。 ---- http://up.gc-img.net/post_img/2017/12/Ae5kSniH8SOmEhB_tjl69_17.jpeg, どうしても複数パスの場合は末尾に「,」を入れてPOSTしたいのであれば、下記のようにしてみてはいかがでしょうか。 ---- //画像ファイルとして格納 $img_url = preg_replace('/,$/', '', $path); あと、関係ないですが、気になったのでコメントしておきます。「preg_replace()」は画像のHTMLの画像ソースを入れ込むためだけに使っているように見えます。下記のような文字列連結でよいと思います。 ---- //画像ファイルとして格納 $img_url = $path; echo $img_last = '<img src="'.$img_url.'" style="width:300px; height:200px; border-radius:5px; margin:10px;">'."<br>\n";
退会済みユーザー

退会済みユーザー

2017/12/20 08:59

早速ご教示頂きありがとうございます! URL末尾の「,」を削除してsubmitしてみたのですが、 1つしか正規表現に引っかかりませんでした... もしかすると、上記3URLを1つの文章として捉えてしまっているので、1つしか 正規表現で合致しないのかなと思ったのですが、別の方がご回答頂いたように、 改行単位で文章を区切った上で(explodeなどで)、それぞれに対して正規表現をかけて処理を行う 必要があるんでしょうか?
Tomak

2017/12/20 10:06

nl2br()は削除しましたでしょうか? 回答に書いたようにパスの末尾に「<br>」がついてしまい、下記のようなパスになってしまいます。 ---- http://up.gc-img.net/post_img/2017/12/Ae5kSniH8SOmEhB_tjl69_17.jpeg<br> 私の手元のテストコードではきちんと画像が3つ表示されているので、どこかに不具合があるはずです。 まずは、生のPOSTデーターとpreg_match_all()後の$resultのダンプをみて何がどうなっているのか順を追って調べてみてみるとよいと思います。
退会済みユーザー

退会済みユーザー

2017/12/20 11:56

ご返信ありがとうございます! ご教示頂いた事項を修正し作動するようになりました!
guest

0

コードを読ませていただいた感じでは、恐らくURLかどうかチェックしている正規表現の指定が問題かと思います。

PHP

1preg_match_all('/^(https?|ftp)(://[-_.!~*\'()a-zA-Z0-9;/?:\@&=+$,%#]+)$/', $base , $result)

PHP

1preg_match_all('/^(https?|ftp)(://[-_.!~*\'()a-z0-9;/?:\@&=+$,%#]+)$/im', $base , $result)

のように、変更してみて下さい。
パターン修飾子の追加、大文字[A-Z]のマッチング指定を除去しています。

各パターン修飾子指定による挙動は下記の通りです。
・パターン修飾子 i : 大文字/小文字不問
・パターン修飾子 m : 複数行の検索を行う

パターン修飾子についての詳細は、PHPマニュアル「パターン修飾子」をご確認下さい。
http://php.net/manual/ja/reference.pcre.pattern.modifiers.php

投稿2017/12/20 05:13

編集2017/12/20 05:16
momoya

総合スコア29

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

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

0

たぶんスペースか改行かでURLが区切られていると思います。$baseを直接処理するのではなく、スペース改行で分解し、分解された結果のひとつづつについて「URLかどうかチェック」以下を実行するループを作ればいいのではないでしょうか。

投稿2017/12/20 03:31

KojiDoi

総合スコア13671

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

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

退会済みユーザー

退会済みユーザー

2017/12/20 08:26

ご教示いただきありがとうございます! 参考にさせていただきます!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.49%

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

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

質問する

関連した質問