2016.4.29
0からはじめるPHP#90【cronによる自動ツイート#3】
ということで、具体的にプログラムを書くワケですね。
まず、SQLiteを使うための準備をしなくてはいけません。
SQLiteを使うのに必要なのは
「sqlite3.def」「sqlite3.dll」「sqlite3.exe」の3つのファイルです。PHPから使う場合はsqlite3.dllがあれば良いみたいな書き方されてたりするんですが、僕はよくわからないので全部入れといていいんじゃないでしょうか。たかだが1MB弱のファイルですし。
ダウンロードは
公式ページからできるんじゃないですかね。
Precompiled Binaries for Windowsのとこから落とすと良いんじゃないかなと思います。
まぁ正直
僕の環境ではこれだけでは足らなかったんですが、上の3つが揃えば多分動くと思うので何とかして探したら良いと思います。
どこにあったかは忘れちゃいました。
SQLiteの操作は基本的にはコマンドラインから行うみたいですが、割とめんどくさいのでphpMyAdminみたいなGUIを導入したいところですね。
ということで僕は
PupSQLiteというフリーソフトを推しときます。まぁやってることはSQL直打ちとあんま変わんないんですけど、視覚的にわかりやすいですしね。
で、プログラムの方は、こんなんフレームワーク使うまでもないのでPHPを生で書きます。
生で書くということは、データベース操作も自前で用意しなくてはいけませんね。ということで
PDOを使うことにします。
try {
// 接続
$pdo = new PDO('sqlite:データベース名.sqlite');
// SQL実行時にもエラーの代わりに例外を投げるように設定
// (毎回if文を書く必要がなくなる)
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
// デフォルトのフェッチモードを連想配列形式に設定
// (毎回PDO::FETCH_ASSOCを指定する必要が無くなる)
$pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
// 選択 (生SQL)
$r = $pdo->query("SELECT * FROM テーブル名 WHERE id='1'")->fetchAll();
} catch (Exception $e) {
echo $e->getMessage() . PHP_EOL;
}
使い方はこんな感じです。簡単ですね。
PDOオブジェクトを用意し、あとは必要なオプションを設定すれば良いです。
エラーなんてそうそうでないと思うんですけど、とりあえずtry~catch構文を使うとすっきりするので、エラーが出たら例外を投げてもらいます。
フェッチモード、つまり結果を配列で受け取ると視覚的にわかりやすいのでそちらも設定します。まぁ基本的には上のプログラムはコピペです。
見たら分かると思いますが、setAttributeという関数でこういったオプションを設定します。第一引数に項目名、第二引数に具体的な設定を書き込むわけですね。まぁ具体的にはリファレンス引いて下さいって感じですね。
今回は特にユーザーからの入力を使わないので、プリペアドステートメントは要らないかなと。idも1固定です。レコード1つしかないのでidなんてカラムも実は要らないんですけど、更新に失敗してレコードが増殖したら鬱陶しいし
(いやたぶんそんなこと起こんないと思いますけど)idカラムがあった方が書きやすいと思われるのでとりあえずくっつけてみました。
これでrにデータベースのレコードが無事格納されるわけですね。
ちなみにこれ、SQLiteでもMySQLでも同じ書き方できまして、それがPDOの素晴らしさでもあります。
/*処理実態*/
//if:前回updateより1時間経過
$datetime1 = new DateTime($r[0]["Datetime"]);
$datetime2 = new DateTime("-1 hour");
if($datetime1>$datetime2){
//終了
throw new Exception('前回ツイートより1時間未経過');
}
//$search=DBの日付をstrtotime
$search=new DateTime($r[0]["date"]);
while($search<new DateTime()){//ループ開始
//+1day
//if:翌日->終了
//if:当日
//~23時->終了
//date->配列に分解
//記事の存在チェック
//if:存在->ループを抜ける
//if:存在しない
}//ループ終了
//更新処理
で、今書いてるのがこんな感じのプログラムです。
いい加減オブジェクトの使い方にも慣れましょうということで、タイムスタンプではなくDatetimeオブジェクトを使ってますが、使い慣れると便利かも知れないです(笑)
こいつを参考に組み立ててます。
今までの反省を活かして
まずはコメントでちゃんと組み立ててから実装しようという意識をしてます。すると使う関数の方に意識を集中できるのでおすすめです。
ちなみに現時点ではこんな感じです。はい。あとはDB更新部分が完成すれば、cron実行およびtwitter連携の話に進めますね。
それはともかくとして、Datetimeオブジェクト、使い慣れると結構便利そうですね。
この日記のシステムもDatetimeオブジェクト使って実装したらコード量が半減ぐらいするしバグも減ったろうになーとか思ってたりしますが、まぁ書き直すほどのことでもないし放置かな・・・・・・。
新しい知識はこうやって吸収していきたいところですね(・ω・)はい。