すっきり書くにはどうしたらいいですか? - PHPプロ!Q&A掲示板

1998

  • 300P

すっきり書くにはどうしたらいいですか?

質問日時 / 2009年4月28日 14:42 (最終編集:4月28日 16:05)    回答数 / 17件

Questioner:  yumisaiki  このエントリーをはてなブックマークに追加 

キーワード / twitter   

参加者のそれぞれのtwitter の最新のつぶやきを表示させるようなページを作ろうと思って、twitter の rss を利用して作ることができました。

http://ikekumi.lovepop.jp/bg/twitter.php


  1. <?php 
  2. // URLの指定  ここは人によって違います。
  3. $rdf_url = "http://twitter.com/statuses/user_timeline/26451428.rss"
  4.  
  5. // RSSを取得 
  6. $content = file_get_contents($rdf_url)
  7.  
  8. // 文字列を変換 
  9. mb_internal_encoding("EUC")
  10.  
  11. // rdfを解析する (下の関数で処理) 
  12. $datas = analyze_rdf($content)
  13.  
  14.  
  15. // rdf ファイルを解析するための関数 
  16. function analyze_rdf($cnt) { 
  17. // <item> ~ </item> を切り出す 
  18. $ptn = '/<item[^>]*>(.+)</item>/sU'
  19. preg_match_all($ptn$cnt$matches)
  20.  
  21. // マッチしてれば 
  22. if (count($matches) > 0) { 
  23. // 配列に入れる 
  24.  
  25. $items = $matches[1]
  26. } else { 
  27. return FALSE
  28. } 
  29.  
  30. // パターンの指定 title のところに ikekumi: などユーザー名がつきここも違います
  31. $ptns["title"] = '/<title>ikekumi:(.*)</title>/sU';
  32. $ptns["link"] = '/<link>(.*)</link>/sU'
  33. $ptns["time"] = '/<pubDate>(.*)</pubDate>/sU';
  34.  
  35. $return_array = array()
  36.  
  37. // 各 img / title / link の抜き出し 
  38. foreach ($items as $val) { 
  39. $res = array()
  40.  
  41. preg_match($ptns["title"]$val$matches)
  42. $res["title"] = $matches[1]
  43.  
  44. preg_match($ptns["link"]$val$matches)
  45. $res["link"] = $matches[1]
  46.  
  47. preg_match($ptns["time"]$val$matches)
  48.  
  49. $res["time"] = $matches[1]
  50. //時間を短くトリム
  51. $res["time"] = mb_strimwidth($res["time"] ,0,25);
  52.  
  53. $return_array[] = $res
  54. } 
  55.  
  56. // 配列を返す 
  57. return $return_array
  58. } // function analyze_rdf($content) 終了 
  59.  
  60. // HTML に整形するための関数 
  61.  
  62. function make_html($data) { 
  63. $str = "<p><a target="_blank" href="";
  64. $str .= $data["link"] . "">";
  65. $str .= $data["title"] . "</a><br /><small>" .$data["time"] . "</small></p>n"
  66. return $str
  67. } // function make_html($data) { 終了 
  68.  
  69. // 表示するところ 表示を増やすときは 続いてprint make_html($datas[1]); と増やしてください
  70.  
  71. print make_html($datas[0])
  72.  
  73. ?>


twitter のアカウント毎にこれを書くのは面倒なので、なんとかカッコよく切り替えができないかなと思います。

twitter の rss のアドレスと

title のところの ikekumi: 以外は全部同じなのです。

なんかいいアイデアないでしょうか?

この質問への意見の募集は締め切られ、ポイントは既に配分されました。
意見を投稿することはできますが、ポイントを受け取ることはできません。



ツリー一覧

┣A01yakou850>twitter の rss のアドレスと >title のところの
┃┗A01-1yumisaikiすみません。logic.php には 私が上記で書いたfuncti
┃ ┗A01-1-1yakou850>>CODE function view_twitter($rss_url, $user_name
┃  ┗A01-1-1-1yumisaiki私の頭の中では、function をどんどん書いてというの
┃   ┗A01-1-1-1-1yakou850>私の頭の中では、function をどんどん書いてという
┃    ┗A01-1-1-1-1-1yumisaikiそうか!とわかって、logic.php の内容を >>CODE f
┃     ┗A01-1-1-1-1-1-1yakou850ここも意識すべきなのは同じです。 「関数analyze_
┃      ┗A01-1-1-1-1-1-1-1yumisaiki初期化するといのもよくわからずすみません なんか、
┃       ┣A01-1-1-1-1-1-1-1-1magicflute2>>CODE <?php function analyze_rdf($cnt) $pt
┃       ┃┗A01-1-1-1-1-1-1-1-1-1yumisaikiまた暇なとき…というより必要に迫られていろいろまさ
┃       ┗A01-1-1-1-1-1-1-1-2yakou850その正規表現の前で、 >>CODE print '$name='.$name
┃        ┗A01-1-1-1-1-1-1-1-2-1yumisaikiyakou850様 $name=ikekumi となりますので、初期
┣A02mgngmgngついでに、 simplexml使うと 幸せになれる気がしま
┃┗A02-1yumisaikiこれを参考に書きなおしてみたいと思います。 いいこ
┣A03NurseAngel作り方はyumisaiki様、mgngmgng様の内容で十分ですの
┃┗A03-1yumisaikiなんか、クォーテーションについては\がコピペすると
┗A04yumisaiki例えば 同窓会のホームページであなたのtwitter のR

回答一覧

並び替え:

A01 満足
answereryakou850 [4月28日 15:43]

>twitter の rss のアドレスと
>title のところの ikekumi: 以外は全部同じなのです。

じゃあ実際の処理も関数にしてしまって、引数にRSSのURLとタイトルに組み込む文字列を設定してはいかがでしょう?
あと、自分の感覚ですが、変更する設定ファイルとロジックファイルをわけると感覚的にすっきりします。

twitter.php ←logic.phpに定義されたメインの関数を呼び出す
logic.php ←関数をどんどん定義していく

とやると、twitter.phpは
  1. require_once(dirname(__FILE__).'/logic.php');
  2.  
  3. $rss_url = "http://twitter.com/statuses/user_timeline/26451428.rss"; // RSSのアドレス
  4. $user_name = "ikekumi"; // タイトルに表示するアカウント名?
  5.  
  6. view_twitter($rss_url, $user_name); // 適当につけたメインの関数名です
とかやるだけでどんどん表示できるのではないでしょうか?
メインの関数を作っておけば複数ユーザになってもforeach等で簡単に処理できる可能性がありますし。

この意見に回答する

ツリーへ TOPへ

A01-1
replyeryumisaiki [4月28日 16:10] (最終編集:4月28日 16:21)

すみません。logic.php には 私が上記で書いたfunction を入れたらいんでしょうが、
ikekkumi: という title 部分の処理とかはどうしたらいいんでしょうか?

php 何年もやっているのに、今だに簡単なことしかわからず
こういう関数の作り方がわかりません。

お手数ですが、もう少し具体的にしていただけるとありがたいです。


$rss_url をそのまま入れたらいいんですかね。

この意見に回答する

ツリーへ TOPへ

A01-1-1 参考になった
replyeryakou850 [4月28日 16:32]

  1. function view_twitter($rss_url, $user_name) {
  2. (略)
  3. $ptns["title"] = '/<title>'.$user_name.':(.*)</title>/sU';
  4. (略)
  5. }
とすれば$user_name='ikekumi'で同じ処理が動くかと思います。
要はいままで固定で埋め込んでいた部分を変数にして、変更しやすくしただけですね。

# あくまで前のソースのままなので、
# mgngmgngさんのおっしゃるようにSimpleXMLを使ったあとのソースはちょっと違うと思いますが
# やることはほぼ同じだとおもいます。
# (<title>のタグはふくまないと思いますので、ソースの改変は必要と思います)

この意見に回答する

ツリーへ TOPへ

A01-1-1-1
replyeryumisaiki [4月28日 22:04]

私の頭の中では、function をどんどん書いてというのがわかりません。

logic.phpを
  1. <?php 
  2.  
  3. //変数指定の関数?
  4. function view_twitter($rss_url$user_name) {
  5.     // URLの指定 
  6.     $rdf_url = $rss_url
  7.     // RSSを取得 
  8.     $content = file_get_contents($rdf_url)
  9.       
  10.     // 文字列を変換 
  11.     mb_internal_encoding("EUC")
  12.       
  13.     // rdfを解析する (下の関数で処理) 
  14.     $datas = analyze_rdf($content)
  15. }
  16.   
  17. // rdf ファイルを解析するための関数 
  18. function analyze_rdf($cnt) { 
  19.           // <item> ~ </item> を切り出す 
  20.           $ptn = '/<item[^>]*>(.+)<\/item>/sU'
  21.           preg_match_all($ptn$cnt$matches)
  22.         
  23.           // マッチしてれば 
  24.           if (count($matches) > 0) { 
  25.               // 配列に入れる 
  26.               
  27.               $items = $matches[1]
  28.           } else { 
  29.               return FALSE
  30.           } 
  31.  
  32.           $return_array = array()
  33.           
  34.           // パターンの指定 
  35.             $ptns["title"] = '/<title>$user_name:(.*)<\/title>/sU';
  36.             $ptns["link"] = '/<link>(.*)<\/link>/sU'
  37.             $ptns["time"] = '/<pubDate>(.*)<\/pubDate>/sU';
  38.     
  39.         
  40.           // 各 img / title / link の抜き出し 
  41.           foreach ($items as $val) { 
  42.               $res = array()
  43.         
  44.               preg_match($ptns["title"]$val$matches)
  45.               $res["title"] = $matches[1]
  46.         
  47.               preg_match($ptns["link"]$val$matches)
  48.               $res["link"] = $matches[1]
  49.               
  50.                preg_match($ptns["time"]$val$matches)
  51.                
  52.               $res["time"] = $matches[1]
  53.               //時間を短くトリム
  54.               $res["time"] = mb_strimwidth($res["time"] ,0,25);
  55.         
  56.               $return_array[] = $res
  57.           } 
  58.         
  59.           // 配列を返す 
  60.           return $return_array
  61. } // function analyze_rdf($content) 終了 
  62.   
  63.   
  64. // HTML に整形するための関数 
  65.  
  66. function make_html($data) { 
  67.   $str = "<p><a target=\"_blank\" href=\"";
  68.   $str = "<p><a target=\"_blank\" href=\"";
  69.   $str .= $data["link"] . "\">";
  70.     $str .= $data["title"] . "</a><br /><small>" .$data["time"] . "</small></p>\n"
  71.     return $str
  72. } // function make_html($data) { 終了 
  73.   
  74. ?>


twitter2.phpを


  1. <?php
  2. require_once('logic.php');
  3.  
  4. $rss_url = "http://twitter.com/statuses/user_timeline/26451428.rss"// RSSのアドレス
  5. $user_name = "ikekumi"// タイトルに表示するアカウント名?
  6.  
  7. view_twitter($rss_url$user_name)// 適当につけたメインの関数名です
  8.  
  9. print make_html($datas[0])
  10.  
  11. ?>

これだと何も表示されなくなります…。

とりあえずこれで表示できるようにしてsimple XML にしてみようと思ってみたのですが。

この意見に回答する

ツリーへ TOPへ

A01-1-1-1-1 満足
replyeryakou850 [4月29日 00:11]

>私の頭の中では、function をどんどん書いてというのがわかりません。
これは書いていただいた構造で自分の考えはあっています。

自分が書くのであればview_twitterの中からmake_htmlも呼び出すつくりにします。

それと今何も表示されないということですが、
  1. print make_html($datas[0]);
この$datasという変数、どこから出現しましたか?
関数化するのであれば、変数の受け渡しをしっかり意識しなければなりません。
おそらくイメージではview_twitterで定義した変数かもしれませんが、
関数内での変数はその内部でしか基本有効になりません。
なので、必要であればreturnして呼び出した側でも受け取る必要があります。

この意見に回答する

ツリーへ TOPへ

A01-1-1-1-1-1
replyeryumisaiki [4月29日 01:21] (最終編集:4月29日 02:01)

そうか!とわかって、logic.php の内容を
  1. function view_twitter($rss_url, $user_name) {
  2.     $name = $user_name;
  3.     // URLの指定 
  4.     $rdf_url = $rss_url; 
  5.     // RSSを取得 
  6.     $content = file_get_contents($rdf_url); 
  7.       
  8.     // 文字列を変換 
  9.     mb_internal_encoding("EUC"); 
  10.       
  11.     // rdfを解析する (下の関数で処理) 
  12.     $datas = analyze_rdf($content); 
  13.     
  14. print make_html($datas[0]); // 追加しました!
  15. }

http://ikekumi.lovepop.jp/twitter2.php

ここまで関数書くと何がなんだかわからなくなりますねぇ。勉強になります。

でも、$ptns["title"] = '/<title>'.$user_name.':(.*)<\/title>/sU';

というのができません。これを入れると title が拾えないです。

最初に
$name = $user_name; と最初に宣言?を入れてみて、
$ptns["title"] = '/<title>'.$name.':(.*)<\/title>/sU';

でやってみたり、あきらめて str_replace を使ってみたりしましたが、うまくいきませんでした。  悔しいです! 

この意見に回答する

ツリーへ TOPへ

A01-1-1-1-1-1-1 満足
replyeryakou850 [4月29日 04:22]

ここも意識すべきなのは同じです。

「関数analyze_rdf内で$user_nameという変数は定義されているか」

analyze_rdfの引数から見るとview_twitterで定義されていた$user_nameは
どこにも渡されずになにも使われずに消えていきます。

PHPはよくも悪くも適当な言語で、初期化されていない変数もエラーとならずに使用することができます。
# 実際はNOTICEというレベルのエラーはでていますが、表示されないように設定している環境も多いです。
なので、変数の初期化がされているかどうかは常に意識したほうがいいと思います。
今回のように関数にした場合、その関数内で定義されていなければ初期化はされていません。
調査すべき範囲が絞りやすいのがこういった関数化のメリットの1つかと思います。

この意見に回答する

ツリーへ TOPへ

A01-1-1-1-1-1-1-1
replyeryumisaiki [4月29日 09:24] (最終編集:4月29日 10:15)

初期化するといのもよくわからずすみません
なんか、自信がなくなってしまいまいました。

 

そのあと、正規表現がおかしいのではと思いなおし、

$ptns["title"] = $name.'/:(.*)<\/title>/sU';

というように書いてみたらいけました~!
初期化は

 view_twitter($rss_url,$user_name)

 に

$name = $user_name;
$rdf_url = $rss_url;

といたしました。 またひとつ山を登った気がします。ありがとうございました。

この意見に回答する

ツリーへ TOPへ

A01-1-1-1-1-1-1-1-1 満足
replyermagicflute2 [4月29日 11:37] (最終編集:4月29日 11:40)

  1. <?php
  2. function analyze_rdf($cnt)
  3.     $ptns["title"] = '/<title>$user_name:(.*)<\/title>/sU';
  4. ?>
ここで、変数$user_nameを展開させようとせず、
Twitterユーザー名の正規表現パターンを書いてもいいと思う。

そして、$user_nameの値は、もっと別の目的で使用すれば効果的だと思う。

例えば、グループに登録されている人だけ表示したいといった場面で。
  1. <?php
  2. function in_group($user_name)
  3. {
  4.     // グループを設定
  5.     $gp_arr = array( "yamada""tanaka001" );
  6.     // グループに登録されているか
  7.     return in_array( $user_name$gp_arr );
  8. }
  9. function view_twitter($rss_url,$user_name)
  10. {
  11.     // グループに登録されている人だけ以下を処理する
  12.     if ( in_group( $user_name ) ) {
  13.         $datas = analyze_rdf($contents);
  14.     }
  15. }
  16. ?>

この意見に回答する

ツリーへ TOPへ

A01-1-1-1-1-1-1-1-1-1
replyeryumisaiki [4月29日 12:56]

また暇なとき…というより必要に迫られていろいろまさぐってみたいと思います。
まだまだわかっていないので。

twitter は工夫でいろんなことができるみたいで、今回これがわかって本当にうれしいです。

ありがとうございました。

この意見に回答する

ツリーへ TOPへ

A01-1-1-1-1-1-1-1-2 参考になった
replyeryakou850 [4月29日 15:31] (最終編集:4月29日 15:35)

その正規表現の前で、
  1. print '$name='.$name;
とやってみてください。
自分の予測だと「$name=」と表示されているだけだと思います。
「$name=ikekumi」と表示されるようなら自分の認識違いですので謝ります。
もし「$name=」と表示されたのならば、
$nameの中身には何も設定されていない=初期化されていない
ということになります。

あともう1点。
  1. $ptns["title"] = '/<title>$user_name:(.*)<\/title>/sU';

  1. $ptns["title"] = '/<title>'.$user_name.':(.*)</title>/sU';
は同じように見えて動きが違います。
「'」で囲んだ場合は中の変数を展開して文字列にしないのです。
ためしに両方のコードを使って
  1. echo $ptns["title"];
とやってみてください。
# こんな細かい部分でも動きは異なってしまうのです。

この意見に回答する

ツリーへ TOPへ

A01-1-1-1-1-1-1-1-2-1
replyeryumisaiki [4月30日 20:29]

yakou850様

$name=ikekumi となりますので、初期化とかする必要もなく(正式にはあるのでしょうけど)表示されるようです。


最初表示されないときに、ここを読み直してアドバイスしていただいたことを気がついて、

$ptns["title"] = '/<title>$user_name:(.*)<\/title>/sU'; 

というようにも書いてみたのですが、

Warning: preg_match() [function.preg-match]: Unknown modifier 't' in /home/sites/lolipop.jp/users/lovepop.jp-ikekumi/web/logic.php on line 35

という警告が出ました。これは 定義してないtがありますということですが、なんでそれが出るのかもわかりません。

そこでハタと気がついき、$ptns["title"] = $name.'/:(.*)<\/title>/sU'; という形にしてみたら書きだせたわけです。 


今回、関数化を勉強でき次のアイデアもわいてきてとてもよかったです。ありがとうございました。

この意見に回答する

ツリーへ TOPへ

A02 満足
answerermgngmgng [4月28日 16:03]

ついでに、
simplexml使うと
幸せになれる気がします。

http://jp2.php.net/manual/ja/function.simplexml-load-file.php

  1. <?php
  2. $xml = simplexml_load_file('http://twitter.com/statuses/user_timeline/26451428.rss');
  3. foreach($xml->channel->item as $item) {
  4.   echo
  5.     (string)$item->title       . "\n".
  6.     (string)$item->description . "\n".
  7.     (string)$item->pubDate     . "\n".
  8.     (string)$item->link        . "\n".
  9.     "--------------------\n";
  10. }

この意見に回答する

ツリーへ TOPへ

A02-1
replyeryumisaiki [4月28日 16:11]

これを参考に書きなおしてみたいと思います。
いいこと教えてもらいました。

この意見に回答する

ツリーへ TOPへ

A03 満足
answererNurseAngel [4月28日 17:57] (最終編集:4月28日 18:23)

作り方はyumisaiki様、mgngmgng様の内容で十分ですので重箱の隅を。

表示部分を作成する際は、必ずhtmlspecialcharsを通します。

  1. $str = htmlspecialchars($data["title"]); 
  2.   echo htmlspecialchars((string)$item->title);


さもないと、たとえば下記のようなRSSが送られてきたときに困ります(下記は適当なので動かない&SimpleXMLはデフォルトではCDATAを無視しますが、似たような感じで変なことをされる可能性があります)
  1. <title>
  2.   <![CDATA[
  3.     ">
  4.     <span onload="while(1){alert('1');}" />
  5.   ]]>
  6. </title>

あと63~64行目、クォーテーションの入れ子は正しくないのでエスケープするか別のクォーテーションを使用しましょう。

  1. //どちらかを使用
  2. $str = "<p><a target=\"_blank\" href=\""; 
  3. $str = '<p><a target="_blank" href="';

この意見に回答する

ツリーへ TOPへ

A03-1
replyeryumisaiki [4月28日 21:36]

なんか、クォーテーションについては\がコピペするとき落ちていたみたいです。
でも”いっぽんやりで書いていたのですが 'も使えるんですね。 こっちの方が楽かもしれません。

SimpleXML 便利ですね。 勉強しました。 ありがとうございました。

この意見に回答する

ツリーへ TOPへ

A04
answereryumisaiki [4月30日 11:14] (最終編集:4月30日 11:19)

例えば 同窓会のホームページであなたのtwitter  のRSSとIdを登録してください。
とかいうフォームを作って、
それで自動的に 

卒業年度 |名前 | twitterコメント


みたいな感じで一覧表にできたら最高ですね。この関数化を見ていてできるじゃないかなと思いました。 

 00年卒業順番に表示させたり。 
 そうなってくると SQLかまさないとできないですね。まだSQLはさわったことがないのです。

また、サークルのホームページの部門別にtwitterを登録して、部署別の名簿にtwitter表示させたりとか、いろいろ便利に使えるかもとか 
個人的に今、ものすごいtwitter にはまっています。 私のtwitterは yumisaiki です!
ぜひfollowしてくださいね。

 あー。もっとPHPを勉強したいと今日も思いました。

 忙しくて、ちょこちょこしか勉強できないのですが、また質問しに来ます~! 
 ありがとうございました。

この意見に回答する

ツリーへ TOPへ

<<質問一覧へ



Pick Up Q&A

Q
ログファイルの中の空のデータ行を削除したい
 このエントリーをはてなブックマークに追加 
A
ログのデータ個数(列数)が固定で、空のログが"<><><>"だと既知であれば if ($line === "<><><>") { continue; } で読み飛ばしてもいいのでは? ...

>>続きを読む

まずは配列や文字列の扱いから、じっくり勉強して行きましょう。

▲解説者:岡本(アシアル株式会社 教育コーディネーター兼 システムエンジニア)