第二回 自作スクリプト発表会【PHP】
自分が書いたPHPスクリプトを発表するスレ。 初心者が書いた入門スクリプト、ベテランが書いたすげースクリプトを発表してね。 予めスクリプトの内容を明記してURLを貼り付けるのがよろしいかと。 マターリ進行でいきませう。 【PHP】自作スクリプト発表会 http://pc8.2ch.net/test/read.cgi/php/1017456911/all Warning: 発表の場は、学びの場。クレクレ君は他所へ。 じゃあ、 【PHP】下らねぇ質問はID出して書き込みやがれ 76 http://pc11.2ch.net/test/read.cgi/php/1226517332/ このスレッドを1時間に1回監視して、 書き込みがあったら、 番号、名前、さげ、年月日時間、ID、内容 をテキストファイルに追記していく。 アボーンがあったら、何番がアボーンになったと記録する。 そんな、PHPスクリプトを自作してここで発表して下さい。 お願いします!! >>68 それって、スレを丸ごとファイルに保存するのと何か違うの?? >>69 ・PHPの技術力が違う ・エレガントさが違う それに一番大事なのは、 1日1回、スレを丸ごと保存し、古いのを捨てる、ってやり方があるけど、 それだと、アボーンに何が書いてあったかわからないのです。 よろしくお願いします!! >>70 要するにあぼーんされた部分を残しときゃいいってこと? あぼーん以外を保存しときゃあとから参照できるような気がするけど・・・ ■番号、名前、さげ、年月日時間、ID、内容をテキストファイルに追記していく。 ■アボーンがあったら、何番がアボーンになったと記録する。 ↑この2つはフォーマットが全然違うと思うけど、そのへん何か考えてます? あと、1時間に1回って処理をしようと思ったらcronとか使うと思うけど大丈夫ですか? >>71 > 要するにあぼーんされた部分を残しときゃいいってこと? そうです。 > ■番号、名前、さげ、年月日時間、ID、内容をテキストファイルに追記していく。 > ■アボーンがあったら、何番がアボーンになったと記録する。 > > ↑この2つはフォーマットが全然違うと思うけど、そのへん何か考えてます? いえ、考えてません。 > あと、1時間に1回って処理をしようと思ったらcronとか使うと思うけど大丈夫ですか? cronを知らないのでなんとも言えません。 ただ、winXPのパソコンを24時間立ち上げておくことは可能です。 >>72 http://lcdata.ddo.jp:8080/2ch/1156116687/68/ ↑ここで作ってます。 7時までにできなかったら仕事に出動orz ニートになって趣味プログラミングに没頭したいなぁ。 メアドがテスト用にあぼーんになってたことに気づいたorz >>74 ごめん、あぼーんって動作テストできないってことに気づいた。 肝心のあぼーん部分がほとんど検証できてないです。 一応ソース↓ http://lcdata.ddo.jp:8080/2ch/1156116687/68/index.phps 1.自分のPCにWeb鯖を立てる。 2.↑のスクリプトを設置する。 3.ブラウザから何度かアクセスして、以下のCSVファイルを吐くことを確認する。 (1)現在のスレの内容(ただしあぼーん以外/あぼーんされたレスは「あぼーん」って文字が追加される) (2)前回のアクセスから増えているレスの内容 4.cronが使えない環境みたいなので、「コントロールパネル>タスク」を使って1時間ごとにアクセスするようにがんばる。 スクリプトがまともに動くなら、CSVファイルからあぼーんされたレスを 抽出するスクリプトを組むのは簡単だと思う。 ごめん、あぼーんのとこミスしてた。 たぶんもう大丈夫だと思います。 ソースは↑のやつを更新しました。 >>75 おお、有り難うございます。すごいですね。 なにはともあれ、1226517332_new.txtというファイルが出来て、そこにデータが全部入ってるみたいです。感謝、感謝です。 ただ、↓のエラーがどっちゃりでてます。 Notice: Undefined offset: 1 in C:\php\ThreadKeep.php on line 34 Notice: Undefined index: abone in C:\php\ThreadKeep.php on line 72 $new_csv[$num]["mail"] = $matches[1]; これが34行目です。 if (!$value["abone"]) { これが72行目です。 >>77 Noticeなのでエラーではなく通知ですね。 PHPの設定で、エラーを拾うレベルが高すぎるんだと思います。 php.iniの「error_reporting」の箇所を↓に修正して、Noticeがでないようにできます。 error_reporting = E_ALL & ~E_NOTICE エラーはふつうに表示されるのでご安心を。 ホントはNoticeも出ないように作るべきなんだろうけど時間切れです、すいません。 >>79 了解しました。有り難うございました。感謝、感謝です。 >>81 まだ作りはじめたとこで、アップローダのアもできてない状態です。 おもっくそスレ違いで申し訳なかったです。 >>80 あぼーんされたレスだけを別ファイルに保存するようにしてみた。 ソースは同じとこです。 Noticeが出るのは放置してます。 ファイルアップローダ程度でDB使うのってどう思いますか? できるだけ環境を選ばず設置できるようにしたいので使いたくないんですが、 コーディングの煩雑さとパフォーマンスの誘惑に負けそうです。 僕もそうだったけど、「DBって何?聞いたことあるけど」って人は多いですよね。 敷居下げるならDBなしなのかなぁ・・・。 ファイルベースが特段煩雑とも思わんが・・・。 素人向けのレンタルスペースでも動くスクリプトを配布したいんなら無しでしょうね。 ただPHPが動くレンタルサーバでDBが入ってないとこなんてあんの?知らないけど。 どちらも押さえときたいなら両方作って配布するとか。 >>85 なるほど。 でもやっぱSELECTの手軽さは魅力だと思います。 DBばっか使ってるからファイルベースだとCSVしか思いつかなくて・・・。 ただ、アップローダは自鯖ってのが基本だと思ってます。 XAMPPとか使ってとりあえずDB入れたけど、使い方はさっぱりって人は多いと思うなぁ。 ってことでファイルベースでやってみます。 どうでもいいけど、前スレ見てたら以前もアップローダ作ってたこと思い出したw 完成したんだっけかなぁ・・・。 ものすごくどうでもいいことですが、 ルータを買ったらDDNSに対応してたので、URLを変更しちゃいました。 >>65 のアップローダは↓で作成中です。 ttp://lcdata.ath.cx:8080/2ch/upload/ >>88 すいません、またまたURLを変更しました。 ttp://lcdata.ath.cx/2ch/upload/ こっちでやってます。 まだ作りかけです。 なんでポート80番が使えないんだろ? とか思ってたんですが、スカイプが使ってることに気づいたのでorz // レスごとに分解 $thread = @file_get_contents($url); preg_match_all("/<dt>(.*)/", $thread, $matches); $res = $matches[1]; if ($res) { foreach ($res as $key => $value) { // レス番号 preg_match("/^(\d*)/", $value, $matches); $num = $matches[1] - 1; $new_csv[$num]["num"] = $matches[1]; // メールアドレス preg_match("/<a href=\"mailto:([^\"]*)/", $value, $matches); $new_csv[$num]["mail"] = $matches[1]; // 名前 preg_match("/<b>([^<]*)/", $value, $matches); $new_csv[$num]["name"] = $matches[1]; // 名前 preg_match("/<b>([^<]*)/", $value, $matches); $new_csv[$num]["name"] = $matches[1]; // 時刻 preg_match("/(<\/a>|<\/font>):(.[^I]*)ID:/", $value, $matches); $new_csv[$num]["time"] = $matches[2]; // ID preg_match("/(ID:)(.*?)<dd>/", $value, $matches); $new_csv[$num]["id"] = $matches[2]; // レスの内容 preg_match("/<dd>(.*)/", $value, $matches); $new_csv[$num]["res"] = $matches[1]; $abone = preg_match("/あぼ.*?ん<\/b><\/a>:あぼ.*?ん<dd>/", $value, $matches); if ($abone) { $new_csv[$num]["abone"] = true; }}} >>90 は>>75 さんのhttp://lcdata.ddo.jp:8080/2ch/1156116687/68/index.phps のソースの一部分です。 で、 preg_match_all("/<dt>(.*)/", $thread, $matches); この行で1レスづつ、配列に入れる。 で、 $res = $matches[1]; この行の意味がわからないです。 $matchesの変数、$matches[1]の変数、$resの変数のそれぞれの違いがわからないのです。 >>90-91 いやあの晒されると恥ずかしいですが。 特にそこ適当なんでw http://jp2.php.net/manual/ja/function.preg-match-all.php 意味はマニュアルに書いてあるとおりです。 どっか動きがおかしいのを修正したいのか、改造したいのか、単純に意味がわからなかったのか、 コードが汚すぎて読みにくいって指摘なのか、PHPを覚えてみようと思ってるのか、 いったいどれでしょうか? ふと思い出したけど、php.iniのerror_reportingを書き換えなくても、 ---------------------------------------- <?php error_reporting(0); ←これ追加 ---------------------------------------- だけでNoticeは出なくなると思います。 超適当に説明しておくと・・・ まず、このスレのソースコードを見てみてください。 各レスが「<dt>〜」って1行になってるのがわかると思います。 まず、$matchesにその各レスが入ります。 $matches[1]には、「"/^(\d*)/"」などの1番目のカッコの中身が入ります。 そんでもって、さらにそのレスに対してpreg_matchをすることによって、 レス番号とか名前とかを切り出してるんです。 $matches[1]をわざわざ$resって変数に入れてるのは特に意味はありません。 >>92 有り難うございます。 確かに、http://jp2.php.net/manual/ja/function.preg-match-all.php に ↓が書いてありました。 すみません。 >$matches[0] はパターン全体にマッチした文字列の配列 >$matches[1] は第 1 のキャプチャ用サブパターンにマッチした文字 > どっか動きがおかしいのを修正したいのか 動きは、ちゃんと動いてくれて感動しました。 >単純に意味がわからなかったのか、 はいそうです。 >PHPを覚えてみようと思ってるのか そうです、これがメインで1行づつ読み解かしてもらってます。 > ふと思い出したけど、php.iniのerror_reportingを書き換えなくても、 > ---------------------------------------- > <?php > error_reporting(0); ←これ追加 > ---------------------------------------- > だけでNoticeは出なくなると思います。 有り難うございます。 俺はこれ error_reporting(E_ALL); 面倒だけど変数をまとめて設定する癖がつくから後々楽だぞ >>95 僕も余裕があればデバッグ中はそうするように心がけてみます。 PHPしか知らないから、変数の宣言とか型とかいい加減な扱いするクセついちゃったなぁ。 >>97 そうですね。 他に何に使ってるわけでもないWeb鯖だし、それでいいと思います。 僕はいつも、↓みたいな感じでログを流しながら作業してます。 tail -f /apache/log/error_log Windowsで似たようなことってできるのかなぁ。 Cygwinとか試してみよう。 【設置場所】 http://u9.getuploader.com/kiren/ 【ソース】 http://u9.getuploader.com/kiren/download/1/chat.7z 【プログラミング経験】 3ヶ月 【希望評価スタイル】 悪い部分を指摘して欲しい 【自分の性格】 またーり 【備考】 表示部分はJQUERYで、サーバーの部分はPHPで作りました。どうも保守性が悪いような気がするので、 悪い部分があったら指摘してほしいです。 >>99 HTMLのエスケープはPHP側でやったほうがいいよ あとちゃんと見てないからよくわからんが、今HTTPヘッダで取ってくるログを判別してるみたいだけど、 それもPHP経由で重複したデータを取ってこないように。 >99 暇だから見てみるか。 とりあえず3秒見たところだが、enter.phpにXSSな。htmlspecialchars()かけろ。 load_namefile(&$a, $b)は、$aをそのまま返せばいい。参照渡しで値を返すと可読性が激しく低下する。返り値$iはcount($a)に等しいはずだ。 変数名が手抜きすぎる。$aとか$bとか$cとか$vとかなんの拷問だ。 append_namefile($name, $last_talk_time, $room_number)にするだけで10,000倍読みやすくなる。foreach()とかで使う一時変数も同じ。 「保守性の高いコード」はアーキテクチャが生むんじゃなくて、変数名やインデントなどのミクロな部分が生むんだ。神は細部に宿る。 $_POST["state"]での処理の振り分けは、明らかにifではなくcaseにすべき箇所。 名簿ファイルのロック処理が半端。flock()を信用するならbegin_lock()は不要。 信用しないならflock()が正常に動く事を前提としているbegin_lock()も同じく信用ならない事になるので意味がない。 信用しないならmkdirロックを使うべき。SQLiteかなんかを使ったほうが手っ取り早いが。 flock($fp, LOCK_UN)してはいけない。「鍵を開けた後、ファイルを閉める」までの間にファイルが破壊される。 単に閉じれば安全な形でロックが開放される。 メイン処理($_POST["state"]を見て実行される場所)のひとつひとつを関数ないしクラスにした方が、可読性が向上する。 意図をそのまま関数名にしろ。例えば最初のブロックは、そのまま読むと 「ロックを取り、ユーザー名簿を取得し、名簿に書いてある数字がいまの時刻より$_keep_time小さかったら名簿を削除し、名簿を再度書き出す」 わけだが、お前はトップレベルのコードを読んでる時はそうは思考しないだろ? 「長時間退席しているユーザーを蹴る」とか、そういう粒度でこの処理を見るはずだ。ならこの処理は「kick_afk_users()」と関数化すべきなんだ。 トップレベルでやってる処理は多岐に渡るんだから、詳細はいったん別の場所においておくべき。 kick_afk_users(); if($_POST["state"] == "enter"){ enter_room(); }else if($_POST["state"] == "quit"){ quit_room(); }else if($_POST["state"] == "sid"){ if(!in_room($name)){ enter_room(); } rotate_log(); add_talk(); とかなってれば、この部分をざっと見るだけでおおざっぱな処理の流れが見て取れるようになる。 >>103 99じゃないけど > flock($fp, LOCK_UN)してはいけない。 これは以外だった。ちょっと調べてみよ。 ∧_∧ ( ・∀・) 人 ガッ ( つ―-‐-‐-‐-‐-‐○ < >__Λ∩ 人 Y ノ. V`Д´)/ し(_) / ←>>21 >大阪府三島郡島本町の小学校や中学校は、暴力イジメ学校や。 島本町の学校でいじめ・暴力・脅迫・恐喝などを受け続けて廃人になってしもうた僕が言うんやから、 まちがいないで。僕のほかにも、イジメが原因で精神病になったりひきこもりになったりした子が何人もおる。 教師も校長も、暴力やいじめがあっても見て見ぬフリ。イジメに加担する教師すらおった。 誰かがイジメを苦にして自殺しても、「本校にイジメはなかった」と言うて逃げるんやろうなあ。 島本町の学校の関係者は、僕を捜し出して口封じをするな 子供の時に受けた酷いイジメの体験は、一生癒えない深い傷になる 「暴力とイジメと口裏合わせと口封じ」の町やそういう町に巣食うヤクザ・チンピラ・ゴロツキ・不良・ いじめっ子・殺人鬼・ダニ・ノミ・シラミなどを監視して非難するのは暮らしやすい町を作るのに必要だ 誰でも簡単にネットで稼げる方法など 参考までに、 ⇒ 『半藤のブブイウイウレレ』 というサイトで見ることができます。 グーグル検索⇒『半藤のブブイウイウレレ』 AO0UH9L8HP read.cgi ver 07.5.1 2024/04/28 Walang Kapalit ★ | Donguri System Team 5ちゃんねる