0

mySQLの制御フロー関数で嵌まる

node.jsでmySQLを使ってると非同期コールバックだらけでselectしてupdateしてまたselectしてといったように処理が煩雑になりがちです。
joinを避けてクエリーを発行していくとなおさら。

そういった事を極力避ける為、制御フロー関数(IF)なんかを使い倒して一つのクエリで処理させる事が多いのですが、このIFの挙動で嵌まってしまった。

やりたい事は、member_idが0だったら、更新したばかりのupdated_idの値でmember_idで更新してやる。それ以外だったら99を入れる。

元々のデータはこんな感じ。
mysql> select updated_id, member_id from sample where id = 5;
+------------+----------------+
| updated_id | member_id |
+------------+----------------+
|      10      |           0         |
+------------+----------------+

下記のようなIFを使ったクエリでUPDATEしてみると、member_idに10が入ると思いきや77が入った。
mysql> UPDATE sample SET updated_id = 77, member_id = IF(member_id=0, updated_id, 99) WHERE id = 5;

mysql> select updated_id, member_id from sample where id = 5;
+------------+----------------+
| updated_id | member_id |
+------------+----------------+
| 77 | 77 |
+------------+----------------+

なんでもう77入ってるの?
updated_id = 77としてるものが先に更新されてるような結果になった。
されてるようなでなくて更新されてた。

クエリを少し変えて、updated_id = 77を後にもってきたら想定してた通りの動きになった。
mysql> UPDATE sample SET member_id = IF(member_id=0, updated_id, 99), updated_id = 77 WHERE id = 4;

mysql> select updated_id, member_id from sample where id = 4;
+------------+----------------+
| updated_id | member_id |
+------------+----------------+
| 77 | 10 |
+------------+----------------+

同じクエリを続けて発行すると、すでに77が入ってるupdated_idの値がmember_idに入った。これは当然だし納得。
mysql> UPDATE sample SET member_id = IF(member_id=0, updated_id, 99), updated_id = 77 WHERE id = 4;

mysql> select updated_id, member_id from sample where id = 4;
+------------+----------------+
| updated_id | member_id |
+------------+----------------+
| 77 | 77 |
+------------+----------------+

クエリが実行される前に、値が更新されてるというのが理解できなかったけど、そういうものらしい。
やはり内部の動きまで知らないとこういうところで無駄な時間を食ってしまう。
phpの挙動がおかしいなと思ったらcのコード追って原因を究明するくらいにならないとダメと言われた事があったけど、今回の一件で納得した。

0

evernoteAPIをphpで使う(userstore)

EvernoteAPIは、ユーザーに関するデータの取得・更新の場合はuserstore、ノート(ノートブックやタグを含む)に関するものの場合はnotesoreというサービスを使います。

■ユーザーデータの取得する場合、userstoreのインスタンスを生成します。
$userStoreTrans = new THttpClient('sandbox.evernote.com', 80, '/edam/user', 'https');
$userStoreProt = new TBinaryProtocol($userStoreTrans);
$userStore = new UserStoreClient($userStoreProt, $userStoreProt);

開発中なので、sandbox.evernote.comへ接続してるけど本番なら勿論evernote.comへ接続するようにします。

userstoreのもつメソッドはnotestoreに比べるとかなり少なくて5つ。oauthで認証されたユーザーに関しては実質3つ。

* authenticate
* checkVersion
* getPublicUserInfo
* getUser
* refreshAuthentication

userstoreのインスタンスができたらユーザーに関するデータの取得を行う。
$user = $userStore->getUser($_SESSION['accessToken']);
引数はoauthで認証した際に取得したアクセストークン。

$userはオブジェクトとなっているので、
ユーザー名の取得
$user->username;

メールアドレスの取得
$user->email

ユーザーID
$user->id

のようにして取得する。
他にも基本的なものは取得できるけど、ノート数とかタグ数とかそのようなものは取れない。
取得できるものはこちら

jsonやxmlが返ってくるRESTなAPIと違い、基本的にオブジェクトを操作する感覚でできます。

0

ブログとかtwiterとか

なぜ今、ブログなのか

ともだちだけが社会ではありません。人は、自分の興味があること、自分が専門としていることを通じて、もっと社会とつながりたいと思っています。ともだち以外の人とつながりの生まれる場所に行きたいと感じています。

ソーシャルネットワークは、”social”という言葉を持ちながら、あまりこういうニーズには応えていません。既に知り合ったソーシャルな関係を定着させることには使えても、新たなソーシャルネットワークを開拓する事には使えません。

はてながブログを始めた際の近藤社長のエントリー。
新たなソーシャルネットワークをを開拓するのがブログかどうかはわからないけどテクノロジー一本で今後解決できる問題でもないだろうし今はこれが一番正しい気がする。
ブログで個を形成して、twitterの緩やかな繋がりの中に身を投じてソーシャルネットワークを開拓。素晴らしい。

そいうえば、同じ興味をもったものが繋がりあえるサイトの決定版のようなものはまだない。
あわせて読みたいにソーシャル性を加えたサービスでもでてこないかな。
そういう意味では出会い系サイトというのはなんとも先進的であった。

0

evernoteAPIをphpで使う(oauth)

oauthのログインはサンプルを参考にするのが一番だけど、そのままだと動かない。(11/14現在)
やるべき事は3つ。
環境はmacOS10.7.2。php5.3.6。
■peclのoauthをインストールする。
$ sudo pecl install oauth

/usr/include/php/ext/pcre/php_pcre.h:29:18: error: pcre.h: No such file or directory
In file included from /private/tmp/pear/temp/oauth/php_oauth.h:47,
from /private/tmp/pear/temp/oauth/oauth.c:14:
/usr/include/php/ext/pcre/php_pcre.h:37: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘*’ token
/usr/include/php/ext/pcre/php_pcre.h:38: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘*’ token
/usr/include/php/ext/pcre/php_pcre.h:44: error: expected specifier-qualifier-list before ‘pcre’
make: *** [oauth.lo] Error 1
ERROR: `make' failed

で止まる。
pcreというのが入ってないかららしいので、macportsでインストール。
$ sudo port install pcre

インストールが完了したので再度挑戦。
が、同じところで同様のエラーが発生。

pcre.hが読み込めてないので、コピーで済ます。
$ sudo cp /opt/local/include/pcre.h /usr/include/

$ sudo pecl install oauth
はい、これで無事インストールされたので、php.iniにextensionを追記してapacheを再起動。
extension=oauth.so

■ショートタグを有効にする
ショートタグ(php_flag short_open_tag On

■config.phpを編集する。
evernoteから送られてきたキーを入力する。
sample/oauth/config.php
define('OAUTH_CONSUMER_KEY', 'hogehoge');
define('OAUTH_CONSUMER_SECRET', 's42fefc90ff2vf');
 
本番環境移行時は、EVERNOTE_SERVERも変更する必要がある。
define('EVERNOTE_SERVER', 'https://sandbox.evernote.com');

サンプルには、詳細版ログインと簡易版ログインが用意されてる。
– 詳細版ログイン(1ステップずつ動作を確認できる。)
sample/oauth/sampleApp.php
– 簡易版ログイン(実際のアプリでも使える。)
sample/oauth/index.php

どちらかのスクリプトにブラウザからアクセスして無事接続できたらとりあえずは安心。

ここからは他のAPIでoauthを使ったことある人なら、全然難しくない。
基本的に処理はすべてfuncion.phpに書かれている。

リクエストトークンとリクエストトークンシークレットを取得しにいく。
oauth_tokenとoauth_token_secretという名前になってるけど要はリクエストトークン。

$requestTokenInfo = $oauth->getRequestToken(REQUEST_TOKEN_URL, getCallbackUrl());
 
if ($requestTokenInfo) {
$_SESSION['requestToken'] = $requestTokenInfo['oauth_token'];
$_SESSION['requestTokenSecret'] = $requestTokenInfo['oauth_token_secret'];
$currentStatus = 'Obtained temporary credentials';
}


evernoteの認証画面(getAuthorizationUrl)にリダイレクト

リダイレクトから戻ってきたら、今度はaccess_tokenを取得させるためにリダイレクト。
oauth_verifierをsessionにセット
if (isset($_GET['oauth_verifier'])) {
$_SESSION['oauthVerifier'] = $_GET['oauth_verifier'];
$currentStatus = 'Content owner authorized the temporary credentials';
return TRUE;
}



アクセストークンをsessionにセット
$oauth->setToken($_SESSION['requestToken'], $_SESSION['requestTokenSecret']);
$accessTokenInfo = $oauth->getAccessToken(ACCESS_TOKEN_URL, null, $_SESSION['oauthVerifier']);
if ($accessTokenInfo) {
$_SESSION['accessToken'] = $accessTokenInfo['oauth_token'];
$_SESSION['accessTokenSecret'] = $accessTokenInfo['oauth_token_secret'];
$_SESSION['shardId'] = $accessTokenInfo['edam_shard'];
$currentStatus = 'Exchanged the authorized temporary credentials for token credentials';
return TRUE;
}

この$_SESSION[‘accessToken’]がeveronteAPIでデータを取得する度に必要です。
access_tokenは認証画面ででた期間中は変わることはないのでこれを使いまわします。

次はnoteStoreやuserStoreを使うサンプル予定。

0

evernoteAPIをphpで使う(序章)

phpでのevernoteAPIの使い方を数回に分けてツラツラと書いていきます。
まずそもそものevernoteAPIの話。


この画面はよくみるけど、


この画面を見たことがない人も多いと思う。
evernoteをけっこう使ってる自分でも2年間の間に1度しか見たことがないです。

evernoteAPIを利用したwebサービスは少ないです。一概には比べられてないけど、twitterなんかと比べれば圧倒的に少ない。

原因は思うに2つあって、1つ目が解説する書籍やブログ等情報が少ないという事。

もちろんゼロではないけど、androidやiOSでの利用が多い為が言語もそっちに偏りがちで、phpやperl等のweb系の言語に関してはさらに少ない印象。
公式ドキュメントの入り口までは日本語で書かれてるが、肝心の公式ドキュメントフォーラムはすべて英語となっているので敷居が高かったりする。
Thriftもそうだけど、実際はそんなに敬遠する所ではないけどやはり敷居は上がる。

もう一つはAPIのインターフェイスにThriftを採用してる事。
単純なHTTPの呼び出しでリソースにアクセスできるREST APIがwebでは主流の中、Thrift名前は聞いたことあるけど…って人は多い。

curlとかコマンドラインでtwitterAPIをサクッと試す事ができても、thriftだとそういうわけにはいかない。

evernoteがThriftを採用したかはdeveloper blogでも詳しく紹介されてるけど、

twitterAPIはREST APIということ非常にシンプルだけど、仕様の変更に弱かったりバイナリデータのやりとりには不向きであったりするけど、Thriftはその点をカバーできるようになってる。
Thriftを調べるのはこれはこれで面白そうだけど、単にevernoteAPIを使いたいだけであれば、SDKを通してThriftは透過的に扱えるのでそんなに意識する事もない。

何が言いたいかというと、別に難しくもなんともないのでPHPな人もやってみるといいよ!ということです。

開発を始めるにはまずディベロッパーサイトからAPIキーを申し込む必要があります。

申込み時に認証方法をクライアントアプリケーション用ウェブアプリケーション用から選択する必要があります。
phpでwebサービスとなればもちろんウェブアプリケーション用(oAuth)を選択します。

APIキーは即時発行されるのではなく1〜2日要して、登録したメールアドレスに飛んできます。

本番と同じ仕様のサンドボックスが用意されてるのでここで開発を進める、ある程度動くものができてきたら本番環境で動かしたいです、とevernoteに連絡して本番で動かせるパーミッションをもらうという流れです。

次に、サンプルコードも含まれてるAPI SDKをダウンロードする。

ウェブアプリケーションはtwitterやFacebookと同じくoAuthを採用している。

oAuthで承認されたaccess tokenを使ってノートブックを作ったり、ノートを編集したりする。
twitterは一度access tokenを取得すると永遠に使えるけど、evernoteの場合、有効期限は1日〜1年(サンドボックスは1日)なので切れると再度取得する必要があります。

次は実際のコード編。

0

リモートとローカルのコミットを分ける

前回gitlogを汚さない方法とか書いたけど、実はpush時に問題があって-fオプションを使う必要があったりで実はもう使ってない。
これはこれでいいのかもしれないけど、そもそもやりたかった事は以下の二つ。

  • ローカルのリポジトリは俺俺ハックや中途半端なものも置いておきたい。デイリーのバックアップ用途としても使いたい。
  • リモートのリポジトリはいつpullされるか分からないのでちゃんと動くものだけを置いておきたい。

未だやり方が定まったわけではないけど2つの方法を試し中。
■merge –squashを使う。
開発はmaster以外で必ず行い、リモートへプッシュできるものをmasterへ置く。

ここではdevというブランチで開発を行う。
$ git checkout -b dev

人にはみせれないようなcommitをたくさんする。
$ /Users/aokitakashi/gittest% git log --pretty=oneline
0fcbf10805bfca369ea39d32a3e280c59c5c0093 8割動いてきた
a987a670a442c7dc39db955e16c2f51bf1917413 4日修正分
3ec6ad445ab9bda66f05e00ecde6c1bea0615b8b 3日修正分
d319dbca73bc44d9412b22952674011d72d9560e 2日修正分

マスターに戻る
$ git checkout master

ここで–squashオプションを付けてマージするとコミット前のステージングに反映される。devブランチでのcommitログはなくなる。
devでの4つのcommit分を合わせて改めてcommitする。
$ git commit -m "ログイン用プラグイン実装"
$ git push

■ひたすらstashする。
masterでもok。
stashは一つしか保存できないと思い込んでいたけど、そんな事はない。
適当にバックアップとりたい時にstashする
$ git stash
$ git stash apply

履歴も見れる
$ git stash list

ワーキングディレクトリが最新なのでcommit。
$ git commit -m "ログイン用プラグイン実装"
$ git push

ちなみに前の状態に戻すのも簡単。
$ git checkout -b temp stash@{3}

参考: 6. 鎖をつなぐ最後の輪: stash と reflog

今のところ前者の方が扱いやすい感はある。
後者は名前・コメントがつけれなかったり、git stash/git stash applyの連打が気持ち悪い。