[PHP] TwitterのユーザアイコンURLをキャッシュする

Twitterのユーザアイコンを表示するケースはよくあると思いますが、素直にAPIを使ってしまうとIPアドレス単位で150回/時APIのアクセス制限にひっかかったりして、厄介です。

また、ドキュメントを見ると、<img src=”画像APIのURL” />とかで直接リダイレクトさせて使うのはやめてね、みたいなことも書いてあって、さらに厄介です。

https://dev.twitter.com/docs/api/1/get/users/profile_image/%3Ascreen_name

 

そんな中で、tweetimag.esというサービスはいけていて、ユーザIDを渡せば画像が返ってくるAPIを無料で提供してくれています。

レスポンスも速いので、小規模なサービスや個人用途あればこのAPIを使わせてもらうのがベターだと思います。

 

ただ、ある程度の規模やTwitterクライアントみたいなものになると、無料の外部APIに頼るのはちょっと・・・という場合がありそうです。

多くのサービスは裏でうまく対応しているんだと思いますが、公開されているものでいい感じのライブラリが見つからなかったので、過去に自前で対応していた時のやり方をベースにPHPのライブラリをつくってみました。

twicon

memcachedを使ってURLをキャッシュするようにしていて、ざっくり以下の仕様です。

  • ユーザIDとサイズを指定して、関数を呼び出す
  • 過去のキャッシュがある → そのままURLを返す
  • 過去のキャッシュがない → TwitterAPIに画像URLを取得しにいき、キャッシュを保存

SSLのURLも取得でき、memcachedサーバの指定、キャッシュ時間の変更、キー名のprefix変更に対応しています。

<img src="/twicon.php?id=XXXXX" alt="icon" />

みたいな使い方もOKです。

対象ユーザIDが存在しない場合や、API接続失敗したときなどは1px×1pxの透明gifを返すので、最悪とれなくても画像取得がエラーになることはない安心仕様になってます。

 

ちょっと気になる、という方でmemcachedサーバ用意できる方は、サンプルを参考に使ってみてもらえれば幸いです。

(何かおかしかったら、コメントかpull requestください)


[PHP] PHP5.4でmemcacheモジュールをインストール

trait、array()の[]表記など、個人的には積極的に使っていきたいPHP5.4ですが、環境移行には何かと問題がつきものです。

私の場合は、PHPのsession管理でも利用していた「memcache」(dがつかないほう)を導入する際に問題が発生しました。

情報がまとまってるところが見つからず、それなりに面倒だったので、手順をまとめておきます。

実施した環境

  • CentOS 6.2
  • memcached 1.4.4
  • Apache 2.4.1 / Apache 2.2.2 (※どちらでもOKでした)
  • [php]memcache2.2.6 (※patchの関係で3.0.6だと入りませんでした)

先にやっておくこと

  • memcachedをインストール
  • Apacheをインストール
  • PHPをインストール

1. re2cのインストール(入ってない場合)

yum --enablerepo=rpmforge install re2c

2. memcacheモジュールの取得&patchあて

cd /usr/local/src
wget http://pecl.php.net/get/memcache-2.2.6.tgz
tar -xvzf memcache-2.2.6.tgz
cd memcache-2.2.6
mv memcache.c memcache.c.org
mv php_memcache.h php_memcache.h.org
wget -O memcache.c http://svn.php.net/viewvc/pecl/memcache/trunk/memcache.c?revision=319585
wget -O php_memcache.h http://svn.php.net/viewvc/pecl/memcache/trunk/php_memcache.h?revision=323682

3. memcacheモジュールのインストール

phpize
./configure
make
make test
make install

4. php.iniに拡張読み込みの追記

extension=memcache.so

5. Apache再起動

 

ポイントは言うまでもなく、SVNのtrunkからもってきた「memcache.c」「php_memcache.h」の2ファイルです。

 

https://bugs.php.net/bug.php?id=61289

http://grokbase.com/t/php/pecl-cvs/11bm5hxyv7/svn-pecl-memcache-trunk-memcache-c-php-mem

あたりの情報を元に、PHP5.4対応済みのファイルに差し替えた結果うまく通りました。

今回は元々利用していた「memcache」モジュールを使ったので罠にハマってますが、「memcached」のほうならすんなり通るのかもしれないです。

とは言え、プログラム内で使用していて簡単にモジュールを差し替えられない、という場合もあると思うので、今回のケースが参考になれば幸いです。


[CSS] ファイルアップロードボタンをデザイン

フォームの実装でファイルアップロードボタンを組み込む際、通常だと表示を変更することはできません。

<input id="file_upload" name="file_upload" type="file" />

のように書いた場合、例えばChromeだと下の画像みたいな表示になります。

ファイルを選択

 

input要素にスタイルを効かせようとしても、margin指定くらいしか見てくれず、これはどうしようもないのかなーと思っていたところ、他のサイトさんを見ているとちらほら、見慣れない「ファイルを選択」ボタンを使っているところがあります。

これは・・・と思い、cssを探ってみたところ、ボタンの上にopacityの指定を0にしたinputをかぶせるというハックで対応していることがわかりました。

ボタンをクリックすると、見えないボタン(=ファイルアップロードのinput)をクリックしていることになり、ファイル選択の画面が表示される、という流れです。

 

ということで、サンプルを作ってみました。

<div class="button_wrapper">
    <div class="button">
    ファイルを選択
    </div>
    <input id="file_upload" name="file_upload" type="file" />
</div>

 

.button_wrapper {
    position: relative;
}
.button_wrapper .button {
    width: 150px;
    height: 150px;
    color: #fff;
    line-height: 150px;
    text-align: center;
    background: #666;
}
.button_wrapper input {
    top: 0;
    left: 0;
    width: 150px;
    height: 150px;
    opacity:0;
    position: absolute;
    cursor: pointer;
}

 

表示させると以下のようになると思います。
(ファイルはアップロードできませんが、選択画面まではいけます)

 

ファイルを選択

 

opacityがうまく動かない古いブラウザだと問題が出るかもしれませんが、多くのブラウザで対応したやり方だと思います。

ファイルアップロードボタンもデザインしたい!という方はお試しあれ。


[SQL] 誕生日から現在の年齢を算出

ユーザーの年齢を取得したいという場合に、データベース場では年齢ではなく誕生日を持っておいて、取得時に計算する、というのが一般的だと思います。

表示で使う際は、プログラム側で関数を作っておいて計算すればいいですが、分析用途やリストの出力のためにSQLでさくっと年齢を出したい!という場合に使えるのが以下の方法。

 

誕生日を数値化して、10000を引いて、余りを切り捨てる

 

日付を「2012-01-01」→「20120101」みたいな形で数値化して、10000を引くと、年の単位で引き算したことになります。
小数点が1年に満たない分なので、切り捨てれば現在の年齢になります。

 

MySQLの場合のクエリーはこんな感じになると思います。

(usersテーブル、誕生日の日付がbirthday_dateに入ってると仮定)

SELECT
    birthday_date AS '誕生日',
    TRUNCATE((CAST(CURDATE() AS SIGNED) - CAST(birthday_date AS SIGNED)) / 10000, 0) as '年齢'
FROM
    users
;

 


[Rails3] Windows7にRmagickをインストール

Rails3から登場のBundlerはgemの管理がわかりやすい上に依存gemも一緒にインストールしてくれて、新しい環境で動かすときなど、非常に楽なのですが、「with native extensions」がでてくると曲者です。

OSが変わると、大きなハマりポイントになってきます。

 

今回は、Windows7(64bit)でRmagickをいれようとしたときに、「Image Magick」の依存でハマりポイントがありました。

CentOSではエラーが読み解きやすく「PKG_CONFIG_PATH」にソースディレクトリの/magick下を指定してからbundle installすることですんなりいけたので、Windowsもそれにならって・・・と思ったのですが、エラーが読み解けず、PATH指定もLinuxのソレとは趣が異なるので苦戦・・・。

最終的には以下のブログにたどり着いて、ハマりポイントを脱出することができました。
感謝です。

Windows7 で RMagick をインストールする手順

結局は環境変数の指定が鍵になってきます。
Rails3でやる場合の手順として、以下にまとめ直します。

  1. Ruby1.9をインストール
  2. ImageMagickのWindows用インストーラーをダウンロードしてインストール
  3. ImageMagick のインストールディレクトリを環境変数の PATH に追加
  4. ImageMagick のインストールディレクトリ内にある include ディレクトリのパスを環境変数 CPATH に追加
  5. ImageMagick のインストールディレクトリ内にある lib ディレクトリのパスを環境変数 LIBRARY_PATH に追加
  6. Gemfileに以下を追加
    gem 'rmagick'
  7. bundle install を実行

 

エラーなく通れば成功です!


[Ruby] 変数、定数の文字列展開

hoge = 'hoge'
HOGEHUGA = 'hogehuga'
p hoge + huga + HOGEHUGA #=> hogehogehogehuga

とかは

p "hoge#{huga}#{HOGEHUGA}" #=> hogehogehogehuga

と書ける。
後者であればIntegerの場合にto_sなくても展開してくれたり、すっきり見せれたりと、利点は多いのかも。

この辺は好みなのか、それともスタンダードがあるのか。


データのパーティション化を考える

ユーザーをある規則で10個くらいに分類したい、
処理を分割しておこないたい。

サービス運用していると、わりとよくある話ではないでしょうか。

 

ユーザーIDであれば、1から999をAグループ、1000から1999をBグループ、、、など一定数増加ごとに分割するパターンも考えられます。

このやり方であれば、IDが増えればパーティションも増えるわけですが、
場合によっては偏りがでたり、処理を分割しておこなう場合には、分割数を変えたくない、という場合もあると思います。

 

そこで便利なのが、

IDをパーティション数で割った余り+1をパーティション番号

として使うやり方。

 

データ分析の現場で頻繁に使われてるのを見てから、なにかとこの手法に頼っているのですが、
プログラム的には例えばパーティション数を10とすると

ID % 10 + 1

という形で非常にシンプルかつデータの偏りもおきにくいという利点もあります。

パーティション数が変わらない、というのがポイントです。
(もちろんデータ数の増加に合わせたパーティション数の見直しは必要だと思います)