PHPでトラックバックの送受信(追加)
送る場合は、ソケットをfsockopenして、適当なヘッダ(無視されないため)を付けたPOSTデータをfputsする。
POSTするのは、前の記事に書いた4つである。
沢山サンプルがあるので、検索するとすぐに見つかるだろう。
受ける側は、$_POSTで各項目を受け、いくつかのチェックを行う。
相手のURLのページを読み込むのは次のように書く。
$buff = @file_get_contents($url);
$urlに日本語やスペースがある場合はurlencode()する必要があるが、URLの部分をエンコードするとうまく読み込めない。
また、条件を統一するために、読み込み前にいくつか設定しておくと良いかもしれない。
ini_set('allow_url_fopen', 1);
ini_set("user_agent", "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0)");
ini_set('default_socket_timeout',60);
概要の中や相手ページに日本語があるかチェックするのは、次のように書く。
if(!preg_match('/[一-龠]+|[ぁ-ん]+|[ァ-ヴー]+|[a-zA-Z0-9]+/u', $buff)){
日本語がない場合の処理
}
相手に戻すのは単純に作成したxml部分をechoで返すだけ(他にechoしない)である。
PHPでトラックバックの送受信
トラックバックを処理するようになると、もうブログである。
実は簡単に実装できる。
トラックバックは、相手がこちらの記事に対し行うもので、された方は相手先を表示、つまり相手にリンクするものである。
相手はというと、何も制限がないから、こちらとは無関係にトラックバックを送信できるようになっている。
それでは不公平であり、そのためにSPAMも多い。
相手先にこちらへのリンクを要求することが増えているのも道理だろう。
なぜこんなことになるかというと、トラックバックの送信は単なるPOSTデータだからである。
送りっぱなしでいい(エラー処理をしない)なら、HTMLだけで、サーバがなくてもできてしまう。
actionにリンクを張らせたいところのトラックバックURLを指定して、自分のURLをPOSTするだけという手軽さなのだ。
なので、トラックバック要求時に相手にこちらへのリンクがあるかチェックする。
日本語があることも条件としたい。
こちらのトラックバックURLは通常URLと同じにしたいと考えた。
便利だし、判りやすい。
通常はトラックバックを受けるプログラムを指定したURLとなっているが、記事のURLでトラックバックしようというのだ。
画期的だと思うのだが・・・どうだろう?
必要なことはふたつ。
トラックバックを受けること、トラックバックを送ることである。
前者は随時受信し、後者は記事の登録時に送信する。
まずは送信である。
必要項目は4つ。
title : 記事のタイトル url : ブログのURL ・・・ 必須 excerpt : 記事概要(本文) blog_name : ブログの名前
これを相手のトラックバック先にPOSTするのだが、ソケットを使って開き、fputsする。
このあたりは更新pingと同じである。
相手から結果が返ってくるので、エラー処理をして完了となる。
受信は通常URLにするのでトラックバックであることをチェックしなければならない。
とはいえ、必須のURLがPOSTされているかだけのこと。
URLがPOSTされていれば、トラックバック処理をして、されていなければ、通常の表示を行えばよい。
ここで問題がある。
相手が入れてきた本文に自URLがあるかチェックするのか、相手URLを開き、自URLがあるかチェックするか、である。
前者は簡単だが、確実性には乏しい。
やはり相手のURLから受信して内容を確かめるのが確実となる。
単に自URLを検索するだけだから、大した手間でもないだろう。
ということで、URLがPOSTされていたら、そのURLを開いて読み込む。
ソケットではなく、PHPではファイルとして処理できてしまう手軽さである。
その中に自URLがあるかどうか、日本語を含むかどうかをチェックする。
結果をエラーで返すが、xmlである。
とはいえ、定型でよい。
正常時 <?xml version="1.0" encoding="UTF-8"?> <response> <error>0</error> </response> エラー時 <?xml version="1.0" encoding="UTF-8"?> <response> <error>1</error> <message>元記事へのリンクが見つかりませんでした</message> </response>
この他に、送信・受信したトラックバックの管理や、記事へトラックバックを表示することもしなければならない。
こちらからは、更新の都度本文が変わっている可能性があるので送信することになる。
また、同一記事に同じURLでトラックバックがあった場合には、前のトラックバックを表示しないようにして、新しい方を表示しなければならない。
これから作るので、この記事は後で直すかもしれない。
上記は現時点での内容である。
「?id=xxx」を「xxx」にする方法
ApacheのRewriteを使って、次のようなことがしたい。
「http://cum.2box.jp/?id=xxx」あるいは、
「http://cum.2box.jp/index.php?id=xxx」というのではなく、
「http://cum.2box.jp/xxx」としたい。
拡張子がないので、フォルダに見える。
拡張子をダミーで付けても良いが、そこまではしないでいいだろう。
簡単なのは、プログラムを何も直さなくても動く方法である。
まあ、実際はクローラーやrssのために、その形にリンクを直す作業は出るのだが、受け側は変える必要がない。
何かと言うと、最初に書いてある。
入ってきたリクエストを書き換え、理解できる形に変えてからプログラムを呼び出そうというのだ。
記述はこれ。
Options FollowSymLinks
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([0-9]+)$ index.php?id=$1 [L]
実はハマった。
サブフォルダの中なのだが、サーバ設定で直接そのフォルダにリダイレクトされる。
その書き方で試行錯誤してしまった。
何が悪かったかというと、URLから見るとルートになるので、頭に「/」を付けていてうまく動かなかったのである。
何も付けないとちゃんと動いた。
ちょっとだけ解説すると、「RewriteEngine On」で書き換えを有効にする。
次の2行は、ファイルになくフォルダにもないとき、という意味で、ない場合にのみ書き換えるようにしている。
最後が実際の書き換えで、数字のみだった場合に、「?id=」に変換してから、実際に動作させるのである。
ページ内部のリンク、およびrss.xmlとsitemap.xmlも、その形に直した。
すっきりしたリンクになり、SEO対策的にも良いとされている。
ただし、今まで「?id=xxx」で作って不利だったとも思えないので、ページ内容によるのかもしれない。
「パパも」などはその形だが、ちゃんとクロールされている。
Javascriptでのz-index指定
どうしてか指定がうまくいかなかった。
「styles.z-index」と書いていたからである。
「styles.zIndex」だった。
うまくいくはずがない。
コロンビアのドメイン
コロンビアのドメインが国内限定から、地域無制限になるという。
「.co」だから、良いかもしれない。
MySQLのテキスト型
マジ覚書。
テキスト型にはBLOB型とTEXT型がある。
前者は比較時に大文字小文字の区別があり、後者にはそれがない。
特別なことがなければTEXT型の方でいいだろう。
TEXT型にはTINYTEXT、TEXT、MEDIUMTEXT、LONGTEXTがある。
文字列を格納するのは他にCHARとVARCHARがあるので、それぞれの違いも書き留めておく。
CHAR:255Bまでの固定長文字列
VARCHAR:64KBまでの可変長文字列
TINYTEXT:255Bまでの可変長文字列
TEXT:64KBまでの可変長文字列
MEDIUMTEXT:約1.6GBまでの可変長文字列
LONGTEXT:約4.3GBまでの可変長文字列
可変長接頭辞長(可変長制御部の長さ)
CHAR:なし(固定長のため)
VARCHAR:255Bまでは1B、それ以上は2B
TINYTEXT:1B
TEXT:2B
MEDIUMTEXT:3B
LONGTEXT:4B
恐らく、というか確実に、MEDIUMTEXTまでで十分だろう。
小説1冊でさえ、250KBもないのだから。
余程のことでもなければ、TEXTでもいいはずである。
VARCHARとTEXTは最大で同じ長さとなる。
VARCHARは最大文字長が指定できる点が違うが、もうひとつ決定的な違いがある。
初期値を指定できるか、できないかだ。
VARCHARには初期値が指定できるが、TEXTにはできないのである。
つまり、初期値を指定したい場合はVARCHARにするしかない。
更新pingの送信先
どこに更新pingを送るか、である。
そういうリストを探すとかなりの数を一覧表にしているところもあるが、全部に送る必要はないだろう。
数ヶ所を考えていたが、もし一ヶ所に送って、そこが各所に通知してくれたら便利である。
それがPing-O-Matic。
送り先は「http://rpc.pingomatic.com/」である。
WordPressではデフォルトでここにpingを送るようになっている。
そこから更に通知が行くので、1分以内にgoogleで検索結果に反映されるようになる。
先日は偶然見つけたが、今試したら、本当にすぐに検索結果に出た。
ここだけに通知すればいいだろう。
上記のURLから入ると、ping送信画面である。
手動でもpingできる。
便利。
先日のping送信部分のソースだが、ここ一ヶ所に限定した内容で作るなら、プログラムも簡単である。
江戸の話
疲れたので別の話でも。
「一年を二十日で暮らすいい男」というのをご存知だろうか。
1年に20日しか仕事しないで暮らしている男だということだが・・・
答えは「関取」である。
昔、本場所は春と秋に10日ずつあった。
計20日。
十両というのが関取にあるが、給金が十両だったということである。
どのくらいかというと百万円くらい。
「十両盗むと首が飛ぶ」というのが江戸である。
百万円盗むと死刑ということだ。
今の法律では、窃盗で死刑はない。
ただし、強盗殺人には死刑がある。
町奉行というのは、南町奉行・北町奉行があるが、それは大抵は知っているだろう。
南といえば大岡さま、北といえば遠山さまだが・・・ちょっと時代劇に毒されている。
大岡忠相は南町奉行を19年ほど勤めた後、蜷川新右衛門(一休さんのしんえもんさん)でお馴染みの寺社奉行になっている。
ただし、蜷川新右衛門は寺社奉行ではなかったらしいが。
遠山影元は小普請奉行から作事奉行、勘定奉行を経て北町、その後大目付から南町奉行となっている。
金さん、「最後は南だし」と言いそうである。
江戸の治安は町奉行の他に、火付盗賊改方というのがあった。
「火盗改」である。
最初は火付改と盗賊改は別々に設置されたが、後に統合された。
捜査権のみで裁判権はなかったが、町民には厳しく、非常に恐れられたという。
「間男十両」というのもある。
人の女房に手を出すと、罰金が十両だというのだ。
実は江戸は女不足であった。
「入り鉄砲に、出女」という時代である。
男は入ったり出たりできるから、気軽に入れる。
江戸の町民は非課税だったから、入りたいと思うのが当然である。
仕事をちょっとするとお金になって、真面目にひと月も働けば1両から1両5分程度になったそうだ。
蕎麦が16文だが、4000文で1両だから、かなり暮らしは楽だったようだ。
ところが女は入ると出れない。
だから女不足だったようで、離縁なども実際は少なかったらしい。
逆に女の方から逃げ出すことはあったようだが。
医者に免許などない時代である。
医者だと言えば、医者になれた。
だから藪ばかり。
店というのは、モノを見せるから来ているそうだが、店は勝手にやっていたようだ。
不定期に休む、開いている時間もまちまちだった。
現代でもひと昔前は、日曜に休みの店は多く、年末年始に開いているところも少なかった。
それより勝手にやっていたようだ。
ということで、江戸は好きである。
それと平安の、特に一条天皇の御世あたりが好きだったりする。
枕草子の頃だ。
他に「ブログ草子」というのを書いているが、その影響である。
ハマったmagic_quotes
ローカル環境とレンタルサーバの環境は極力同じにしている。
当然のことである。
向こうはLinuxで、こちらはWindowsだからファイル名は気をつけないといけないが、PHPとMySQLは同じバージョンにしてあり、設定も同じにしてある。
・・・はずだった。
ローカルで動くものが、サーバでは動かなかった。
焦ること暫し。
もしやと思って見ると、サーバのmagic_quotes_gpcがOffだった。
ローカルのphp.iniのmagic_quotes_gpcをOffにした。
何で食い違ったのか不思議である。
MySQLサブクエリによるUPDATE
記事にはカテゴリを3つまで登録できるようにしてある。
そのせいで記事数を表示するのがちょっと厄介だった。
つまり、記事データ(記事テーブル)は次のようなデータである。
(この件に関連しない項目や条件は除外してある)
ID、タイトル、記事、カテゴリ、サブカテゴリ1、サブカテゴリ2
カテゴリは必ず入る(入れないと未分類になる)が、サブカテゴリ1とサブカテゴリ2には未分類はなく、入れない場合はNULLとする。
このテーブルから、カテゴリ・サブカテゴリ1・サブカテゴリ2の中から、同じカテゴリになっている件数を求めたい。
項目名が違うから、集計するには項目名を合わせなければならない。
SELECT `Category` FROM `記事テーブル` union all SELECT `subCat1` as Category FROM `記事テーブル` Where subCat1 is not NULL union all SELECT `subCat2` as Category FROM `記事テーブル` Where subCat2 is not NULL
これで、ひとつのカテゴリのみのテーブルになった。
これをカウントする。
SELECT A.Category,count(A.Category) as cnt FROM ( SELECT `Category` FROM `記事テーブル` union all SELECT `subCat1` as Category FROM `記事テーブル` Where subCat1 is not NULL union all SELECT `subCat2` as Category FROM `記事テーブル` Where subCat2 is not NULL ) A group by A.Category
これで、3つのクエリ(SELECT文)をUNION ALLしてまとめ、それをカウントすることができた。
件数は少ないが表示のたびにカウントするのもなんだから、登録時に集計して保存しておけばシステム負荷は減る。
つまり、上記のように集計したデータで、カテゴリテーブルを更新しておきたい。
上記のクエリ結果で、UPDATEするだけである。
UPDATE `カテゴリテーブル` B left join ( SELECT A.Category,count(A.Category) as cnt FROM ( SELECT `Category` FROM `記事テーブル` union all SELECT `subCat1` as Category FROM `記事テーブル` Where subCat1 is not NULL union all SELECT `subCat2` as Category FROM `記事テーブル` Where subCat2 is not NULL ) A group by A.Category ) C on (B.Category =C.Category) set B.cnt = C.cnt
SQL文で全部できると楽である。
SQLでできることはSQLでやるのが良い。
項目編集(例えば日付編集)はSQL文で実施して、プログラム側では表示するだけにすると良い。
もし直すにしても、SQL文を直すだけになるのだから、メンテ効率も良いのである。
Smaryを使うなら尚更のこと。
SQL文であれば、プログラムを動かさなくても(動く環境がなくても)SQL文だけ実行して確認ができる。
便利なものだ。