【PHP】idiormで「以上」や「以下」の条件式を使って検索!
簡単にDBを操作できるPHPライブラリ「idiorm」で、whereの条件式を使って「~以上」や「~以下」の値のレコードを検索する方法です。
以下のようなPHPコード実行すると、各条件でレコードを検索できます。
//idiorm読み込み! require_once dirname(__FILE__).'/lib/idiorm/idiorm.php'; //DBファイル読み込み! $db_path = dirname(__FILE__).'/db/hogege.db'; ORM::configure('sqlite:'.$db_path); //DBはSQLiteを使用 //ageが10よりも小さいデータを取得 $records = ORM::for_table('tweets')->where_lt('age', 10)->find_many(); //ageが10よりも大きいデータを取得 $records = ORM::for_table('tweets')->where_gt('age', 10)->find_many(); //ageが10以下のデータを取得 $records = ORM::for_table('tweets')->where_lte('age', 10)->find_many(); //ageが10以上のデータを取得 $records = ORM::for_table('tweets')->where_gte('age', 10)->find_many();
以上!
Phirehoseを使ってTwitter Streaming APIでツイートを取得してみた!
「Phirehose」というPHPライブラリを使って「Twitter Streaming API」のリアルタイムのツイートを取得してみました。
以下その手順です。
■「Phirehose」をインストール!
以下のGithubの「Phirehose」のページからファイルをダウンロードして、zipを解凍してください。
https://github.com/fennb/phirehose
解凍すると「lib」のディレクトリがあるので、それをお目当てのwebサーバーにまるごと移動します。
■「Phirehose」でツイート取得!
以下のようなPHPコードで「Twitter Streaming API」の「statuses/sample」のリクエストを使って、リアルタイムのツイートを取得します。
このコードはPhirehoseのexampleディレクトリにある「sample.php」のサンプルコードを真似して作ったものです。
<?php require_once('./lib/Phirehose.php'); require_once('./lib/OauthPhirehose.php'); class SampleConsumer extends OauthPhirehose { public function enqueueStatus($status) { $data = json_decode($status, true); if (is_array($data) && isset($data['user']['screen_name'])) { print $data['user']['screen_name'] . ': ' . urldecode($data['text']) . "\n"; } } } define("TWITTER_CONSUMER_KEY", "hogegegegegege"); define("TWITTER_CONSUMER_SECRET", "fugagagagaga"); define("OAUTH_TOKEN", "testestestestes"); define("OAUTH_SECRET", "123456789123456798"); // Start streaming $sc = new SampleConsumer(OAUTH_TOKEN, OAUTH_SECRET, Phirehose::METHOD_SAMPLE); $sc->setLang('ja'); $sc->consume(); ?>
このコードを叩くとプロセスが走り出し、延々とツイートを標準出力で吐き出し続けます。
体感としては、だいたい秒速10~20ツイートくらいの勢いです。
ほとんど負荷がなくて、バックグラウンドで動かしていても全然平気です。
途中で接続が切れてしまった場合も、ちゃんとリトライで再接続をしてくれるお利口さんのようです。
以上!
【CakePHP3】マイグレーションのDB変更が反映されない!
先日CakePHP3の「Migration機能」で、あるテーブルに変更を加えたんです。
以下のような感じで「tweet_type」というカラムをテーブルに追加する変更をやりました。
class AddTweetTypeProducts extends AbstractMigration { public function change() { $table = $this->table('tweets'); $table->addColumn('tweet_type', 'integer', ['default' => 1, 'null' => false,]) ->update(); $table = $this->table('draft_tweets'); $table->addColumn('tweet_type', 'integer', ['default' => 1, 'null' => false,]) ->update(); } }
上記をマイグレーションコマンドで実行すると、たしかにテーブルに新しくカラムが追加されます。
でも「Table->find」でデータを取得すると「tweet_type」のない古い状態のレコードが取得されてしまうんです・・。
これはどうもCakePHPのキャッシュに、古いテーブルのスキーマ情報が保存されてしまっていることが原因っぽいです。
「tmp/cache/models/」のディレクトリがありますよね。ここにあるファイルを全部削除して空にしてみたところ、新しいスキーマが反映されてちゃんと「tweet_type」のカラムを操作できるようになりました。
DBに変更を加えたら「models」のキャッシュを削除しなくてはいけない、こんな決まりがあるとは知りませんでした。
CakePHPはなかなか甘くないですね・・。
以上です・・。
ツイッターカードの画像が表示されないときはしばらく待つこと!
自分のサイトに「ツイッターカード」をセットすると、サイトをツイートしたときに「画像付き」で表示させることができます。
自分のサイトのツイッターカードがうまく機能しているかどうかは、この「カードバリデーター」にURLを入れてチェックすることができます。
↓
https://cards-dev.twitter.com/validator
ときどきちゃんとツイッターカード情報を設定したつもりなのに、このチェッカーで調べると、なぜか画像がグレーになって表示されていないときがあります・・。
そういうときは、小一時間ほど待ってみましょう。
特になにもしていないのに、しばらく経つとなぜか画像が表示されるようになります。
特になにもしていないのに、しばらく経つとツイッターカードが正常に利用できるようになります。
そう、なにもしていなくても、じっと待っていれば時間が解決してくれるのです・・。
【CakePHP3】AWS SDK for PHPでS3サーバーにファイルをアップロード!
「AWS SDK for PHP」というアマゾン公式ライブラリを使うと、PHPを使ってアマゾンのS3サーバーにファイルをアップロード・ダウンロードすることができます。
今回は「CakePHP3」でS3サーバーにファイルをアップロードする方法を説明します。
■「AWS SDK for PHP」のインストール
AWS SDK for PHPのインストールは「Composer」を使ってワンタッチでできます。
cakePHP3のディレクトリで以下のコマンドを打つとインストールされます。
php composer.phar require aws/aws-sdk-php
■ファイルをアップロード
ファイルをアップロードするコードは以下のような感じです。
自分のディレクトリにあるファイル「hogege.jpg」を、S3サーバーにアップップロードしています。
use Aws\S3\S3Client; public function initialize() { $this->config = [ 's3' => [ 'key' => 'hogehogehogegege', //S3アクセスのためのキー 'secret' => 'fugafugafugaga', //S3アクセスのためのシークレットキー 'bucket' => 'image.hogege.com', //S3バケット名 ] ]; $this->s3 = S3Client::factory([ 'credentials' => [ 'key' => $this->config['s3']['key'], 'secret' => $this->config['s3']['secret'] ], 'region' => 'ap-northeast-1', //リージョンは日本 'version' => 'latest' //バケットのバージョニングは最新 ]); } public function upload_img($post_id) { //アップロードするファイルのパス $filepath = dirname(__FILE__)."/temp/hogege.jpg"; //AWSに登録するオブジェクト・キー名 $keyname ="hogege.jpg"; //アップロード! try{ $result = $this->s3->putObject([ 'Bucket' => $this->config['s3']['bucket'], 'Key' => $keyname, 'SourceFile' => $filepath, 'StorageClass' => 'REDUCED_REDUNDANCY' //低冗長化モードを指定 ]); } catch (Exception $ex) { return false; } return true; }
ちなみに、他のサイトにあるファイルをかっぱらってきてS3にアップロードする場合は、以下のような感じでできます。
ちゃんとMIMEタイプを指定してあげないといけないのがポイントです。これをしないとMIMEタイプが「application/octet-stream」でアップロードされてしまいます・・。
//testes.jpgを取得する $img_data = file_get_contents("http://fugaga.com/testes.jpg"); //mime typeを判別 $finfo = finfo_open(FILEINFO_MIME_TYPE); $mime_type = finfo_buffer($finfo, $img_data); finfo_close($finfo); $keyname = 'testes.jpg'; //S3にアップロード $result = $this->s3->putObject([ 'Bucket' => $this->config['s3']['bucket'], 'Key' => $keyname, 'Body' => $img_data, 'ContentType' => $mime_type, 'StorageClass' => 'REDUCED_REDUNDANCY' //低冗長化モードを指定 ]);
アマゾンの公式ページにも詳しい解説が載ってるので、ぜひ見てみてください。
http://docs.aws.amazon.com/ja_jp/AmazonS3/latest/dev/UploadObjSingleOpPHP.html
以上!
【Javascript】iPhone Safariで時刻のソートが効かない!
Javascriptを使って、オブジェクトが入ってる配列を「時刻文字列」順にソートしようとしたんです。
そうしたら、PCの「Chrome」ではちゃんと動作したコードが「iPhone Safari」では動作しませんでした・・。
コードは以下のようなもの(time_listの配下にある「timestamp」の時刻でソートします)
time_list.sort(function(a,b){ var t1 = new Date(a.timestamp); var t2 = new Date(b.timestamp); if( t1.getTime() > t2.getTime() ) return 1; if( t1.getTime() < t2.getTime() ) return -1; return 0; });
エラーとなる原因は、iPhone Safariで使える時刻フォーマットに厳しい制限があるためでした。例えば私が使っていた「2016-11-20 12:00:00」みたいな「-」が入った時刻表記はNGみたいです。
(※各種ブラウザで使える時刻フォーマットは以下)
Dateオブジェクト (日付と時刻) | JavaScript プログラミング解説
しょうがないので、私はその場しのぎで「-」を「/」に変換して「2016/11/20 12:00:00」という時刻表記にして対処しました。この表記ならiPhone SafariではOKみたいです。
time_list.sort(function(a,b){ var t1_str = a.timestamp; var t2_str = b.timestamp; t1_str = t1_str.replace(/-/g, "/"); t2_str = t2_str.replace(/-/g, "/"); var t1 = new Date(t1_str); var t2 = new Date(t2_str); if( t1.getTime() > t2.getTime() ) return 1; if( t1.getTime() < t2.getTime() ) return -1; return 0; });
この方法でもアンドロイドで大丈夫なのかとか、他のPCブラウザで大丈夫なのかとか、いろいろ心配ですね・・。
もっとちゃんと確認した方がよいとは思いますが、当面はこれでよしとしておきます・・。
以上です!