電子書籍の厳選無料作品が豊富!

唐突に質問失礼致します。PHP修行中の者です。
自分のTwitterのタイムラインをFC2ブログに投稿するスクリプトを書きたいと思い、ここ数ヶ月、PHPの本を片手に、200以上のPHPサイトのブラウザタブ開きながら試行錯誤しているのですが暗礁に乗り上げてしまって困っています。

恐縮ながら、どうか御教授いただけたら幸いに存じ上げます。

ブログに投稿することまではできるのですが、今できなくて困っていることは、

1、2つ設置しているif 構文が1つしか動いてくれないので2つ動かしたい。
2、1日分(昨日分=24時間前)の最新(更新分)のテキスト(ツイート)のみ抽出して1日毎に投稿するようにしたい。
3、テキスト(ツイート)の時間のならびを昇順(古い順)にしたい。

の3つです。
改善法をご存じの方がいらっしゃいましたら1~3のいずれか1つだけでもいいので御教授いただけたら幸いに存じ上げます。

今は下記のように書いています。↓

/////////////////////////////////

$url = "http://api.twitter.com/1/statuses/user_timeline. …(ユーザー名)&page=".$_POST['page'];
$tweets = json_decode(file_get_contents($url));

$str = '';
$pat1='/^RT/';
$pat2='/@/';
$m1 = preg_match($pat1, $str);


foreach ($tweets as $val) {

if ($pat1 && $pat2){
echo
$str .= $val->retweeted_status->text;
}
if (!$pat1){
echo
$str .= $val->text;
}


$str .='<br />'
.date('Y-m-d H:i:s', strtotime($val->created_at) + 9*3600)
.'<br /><br />'."\n";
}

var_dump($tweets);


try{
$bm->postEntry("ユーザー名".date("Y年m月d日", $timestamp .= strtotime("-1 day"))."のつぶやきまとめ",
" [". $str ."]");

/////////////////////////////////

これで実行すると、

1、if 構文に関しては、最初の「if ($pat1 && $pat2){echo $str .= $val->retweeted_status->text;」は読み込んでくれますが、次のif構文の「if (!$pat1){echo $str .= $val->text;」は読み込まれずに、「空白」が出力されてしまいます。
やりたいことは文頭がRTで始まる場合は$val->retweeted_status->textで、それ以外は$val->textにしたいのです。
(全てval->textに指定すれば空白なく全て表示できるのですが、RTが文頭につくval->textのものは文末が省略されてしまっているので、全文が書かれているretweeted_status->textに変えたいのです)


2、テキスト(ツイート)の最新のものを抽出するためには「$url = "http://api.twitter.com/1/statuses/user_timeline. …(ユーザー名)&page=".$_POST['page'];」のどこかを書き加えればいいとは思うのですが、どう書き加えれればいいか分からなくて困っています。
Twitter API仕様書によれば
http://watcher.moe-nifty.com/memo/docs/twitterAP …
(転載はじめ)
////////////////////////////////
user_timeline
自分の過去24時間以内に update されたステータスから最大20件(count引数使用時は最大200件)を取得する。
引数 id を指定すれば、その id のユーザのステータスを取得できる

URL: http://twitter.com/statuses/user_timeline.format
http://twitter.com/statuses/user_timeline/id.for …
(format は xml, json, rss, atom のうちのいずれかを指定)

since=日時 (オプション)
指定した日時以降に update されたステータスを取得する
指定した日時以降に update されたステータスを取得する
日時のフォーマットは RFC822(の「5. 日付と時刻仕様」) に従う
なお、本オプションの代わりに http リクエストヘッダで
If-Modified-Since
を明示することで、日時を指定することもできる

例:
http://twitter.com/statuses/user_timeline.rss?si …
2007年3月27日22時55分48秒GMT以降に update されたステータスを RSS 形式で取得する
////////////////////////////////
(転載終わり)

…と記載してありますが、実際に.jsonでフォーマットしてデフォルトで20件分の取得だったとしても、「過去24時間以内」ではなく、それより前(1日以上前)のものまで取得されてしまいます。

これをどのように書き変えればいいのでしょうか?


3、最後にこの上記のテキスト(タイムライン)を昇順(古い順)で出力したいのですが、urlからの入力書き換えで可能でしょうか?
あるいは今回だと降順(新しい順)しか出力できず、昇順にするためには後から並び替えなければならないのでしょうか?
その並び替え方を教えていただきたいです。


質問が多くて誠に申し訳ございません。
改善法をご存じの方がいらっしゃいましたら1~3のいずれか1つだけでもいいので御教授いただけたら幸いに存じ上げます。

A 回答 (3件)

回答No.1に補足。



とりあえず Q.1 に関しては…

━ ココから ━━━━━━━━━━━━━━━━━━━━━━━━
foreach ( $tweets as $val ) {

/* 文頭に「RT」が含まれる */
if ( 1 === preg_match( "/^RT/s", $val ) )
{
echo "<p>これはRTです。</p>\n";
}

/* 文内に「@」が含まれる */
else if ( 1 === preg_match( "/\B@\w+/", $val ) )
{
echo "<p>これは@です。</p>\n";
}

/* 上記のいずれにも属さない */
else {
echo "<p>これはその他です。</p>\n";
}

}
━ ココまで ━━━━━━━━━━━━━━━━━━━━━━━━

~こんな感じの振り分けでOKなはず( $tweets が事前に配列化されてるという条件で)。実際の具体的な処理内容は、そちらでアレンジしてください。

すごく長ったらしい正規表現じゃなければ、直に関数内に正規表現は含んでいた方が、後々のメンテとか楽だと思うかな??後、理由は不明だけど、正規表現を変数にして扱うと、物によっては動作が変になるんで。直書きの方が間違いない(キリッ!

P.S.
特筆してない場合は「PHP:v5.3x」という前提で話してますんで、そのつもりで。

この回答への補足

4017Bさん。再度の丁寧なコメントありがとうございます。

本当に初心者の私にも分かりやすく見やすく頂いて恐悦至極の極みです。
そしてメンテの考慮や直書きのアドバイス、とても参考になります。
バージョンを書き忘れていて申しわけございません。v5.3.5です。

御教授頂いたように下記のように書き直し、実行しましたところ、誠に残念ながら状況は同じく変わらず、「/* 文頭に「RT」が含まれる */」も「/* 文内に「@」が含まれる */」の処理が拾われずに「Warning: preg_match() expects parameter 2 to be string」のエラーを出して飛ばされ、「/* 上記のいずれにも属さない */」の処理のみが実行されました。

foreach ($tweets as $val) {
/* 文頭に「RT」が含まれる */
if ( 1 === preg_match( "/^RT/s", $val ) )
{
echo $str .= $val->retweeted_status->text;
}
/* 文内に「@」が含まれる */
else if ( 1 === preg_match( "/\B@\w+/", $val ) )
{
echo $str .= $val->retweeted_status->text;
}
/* 上記のいずれにも属さない */
else {
echo $str .= $val->text;
}

おそらく、4017Bさんがカッコ書きで仰られていたように「( $tweets が事前に配列化されてるという条件で)」ということなのかな…?
と思い、foreach の前に、$tweets = array( );を書き加えて配列化しようとしているのですが、array( )内を、($str)や($val)や($val->retweeted_status->text)や($val->retweeted_status->text, $val->retweeted_status->text)等々を入れて試したのですが、どれも 1 => nullで通りませんでした。

もしお手数でなければ、後見の方のことも含めて引き続き加筆していただけたら幸いに存じ上げます。

補足日時:2012/10/10 03:08
    • good
    • 0

>エラー


"Warning: preg_match() expects parameter 2 to be string"

~て言うのは意訳すると、「警告: preg_match() を実行したら、2番目の変数にPHP的に期待した物じゃない変なのがあるよ?」って意味。いちいちウルサイ奴と思われるでしょうが、エラー表示には全て意味があり、そこには最も役に立つ手掛かりと答えがある。ちゃんと自分の目で見て聞いて考えるべし。

PHPに限らず、プログラム側から表示されるエラーは、非常に簡単な中学英語レベルです(世界中の技術者に向けて書いてあるので、非英語圏のネイティブじゃない人の事も考慮してる)。PHPみたいなメジャーな開発言語なら、エラーをそのままコピペしてGoogle検索するだけで2秒以内にエラーの意味くらい分ります。

ちなみに上記エラーはテンプレみたいな物で、だいたいは引数(この場合は第2変数)の中身がnull値になってる時に良く表示されます。多分、回答文をそのままコピペしたんじゃないかな?ちゃんとアレンジしろと書いて置いたのに…。見てないケド、$tweets の中身が空っぽなんで、そこから引っ張って来る $val の中身も空になってて、それでエラーになってると思われ…。

P.S.
補足でもお礼にでも良いので、何をどうしたいのか箇条書きでお願いします。優先順位も付けて。

前にも言った通り、こちらはあくまでも手弁当なので、そちらの都合に合わせては回答出来ない。この質問を締めずに開けて置いてくれれば、そのうち暇を見て回答するかもしれないし、これっきりかもしれない。他の誰かが通りすがりに回答してくれるかもしれない。
    • good
    • 0
この回答へのお礼

4017Bさん本当にありがとうございます!

更に半月ほど格闘して、やっと自力で解決しました。

「どうしたいか」は質問文にて優先順位も箇条書きで明確に書いてありましたが、

>答えてあげたいけど他人の書いたコードは常に意味不明瞭なので、解読に時間が掛かる。勘弁。
>当然ながら質問文は前半しか読んでないので
>何をどうしたいのか箇条書きでお願いします。優先順位も付けて。

と4017Bさん自身が仰るように、4017Bさんは問題に対して「面倒なので質問文は読まない」という前提(癖?)があるのに、二度も同じこと(質問文にある箇条書きと優先順位)を重複して書いても、読まないつもりなら仕方ないと思いました。


「警告」に関しても、もちろん先んじて調べていましたが、せっかく4017Bさんがif (preg_match())の書き方を教えて下さったにも関わらず、
それでエラーが出たこと自体の方(次の警告文の英語が読めるかどうかではなく、4017Bさんの最初の御教授がなぜ間違っていたのか)が気になって補足で質問した次第です。

まず1に関しては

foreach ($tweets as $val)
のすぐ後に
if(isset(($vall->))
$val =
でisset()は引数に指定した変数が定義されているかどうか調べ、定義されていればTRUEを返すようにすることで解決しました。

2に関してはif (preg_match())を参考にstrtotime()とdate()でタイムスタンプを取得してその文字列をcreated_atから拾うことで解決しました。

3に関しては、先んじてarray_reverse()を用いて順番をひっくり返すことで解決しました。

if (preg_match()は配列でなくて、文字列でなくてはならないので、通りでif (preg_match()で$valをそのまま入れても動かないはずでした。エラーでの「警告文」はこれが原因です。

しかし、私は、手弁当でありながらも、きっかけとしてのif (preg_match)のヒントを下さった4017Bさんに心より感謝しております。

動機がなんであれ、求めるものに与えようとする姿勢は素晴らしいと思います。
今後の人生においても大切になさってください。磨けば身を結ぶものであると思います。

重ねますが報告も兼ねて御礼申し上げます。

お礼日時:2012/10/28 23:08

え~っと、とりあえず Q.1 に関しては当たり前。



つ~か if文の前で、条件式に使ってる変数 $pat1 と $pat2 にそれぞれ値が事前に代入されてるから。従って何をどうやっても、このプログラム内では常に、

> $pat1 == '/^RT/' == true

~となり、常に if(!$pat1){...} が "偽(false)" となるので if文自体が意味を持たない。同様にその前の if($pat1 && $pat2){...} も意味無し(やはり常に "真(true)" となる)。

P.S.
全部、答えてあげたいけど。他人の書いたコードは常に意味不明瞭なので、解読に時間が掛かる。手弁当なので勘弁。

プログラム系の質問は面倒でも常に一問一答の形で。複数の質問を混ぜると、回答者側も無用の混乱誤解を招くだけなので。またそうする事によって、質問者側も自身の問題点が整理し易くなるので。

と言う訳で当然ながら質問文は前半しか読んでないのであしからず…

この回答への補足

4017Bさん。コメントありがとうございます。

なるほど。御指摘のおかげでTrueになってしまっている現状が分かりました。ありがとうございます。

とりあえず構文が間違っているということが分かったのでよかったです。

補足日時:2012/10/10 02:37
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!