好みの表紙について

この記事は 積読 Advent Calendar 2023 の12日目の記事です。

adventar.org

自分がどのように本を選んでいるんだろうということをさらっと(ほんとうにさらっと)書いていこうと思います。

注意) 本文中にでてくる Amazon のリンクはおそらくはてなアフィリエイトリンクになっていると思うので、そういうのが苦手な方はお気をつけください。

表紙で選んでいることが多い

自分が本を探している場合、なんとなく探していることはほとんどなく、こういうテーマで本はないかなと探していることのほうが多いのですが、そういう場合にやっぱり目にとまるのはあるパターンの表紙。

最近だと MANNING のこれ系の表紙のものはほぼ確実にポチってしまい積まれていく。

※といってもここ数年は物理本を買わない派なので、他のみなさんみたいに積んである写真があるわけではなく、kindleのライブラリに大量に積まれていく

こういう感じのものもポチってしまう。

MANNING の本はどこの出版社から出ていたとしても裏切られることがあまりないので、安心してポチってしまうというのがあるんだが、kindleに積まれたことで安心してしまい、なかなか読み始めないということが起きてしまっていることを、今回のアドベントカレンダーを書くことによって反省したので、この年末年始できちんと読ませていただこうと思います。

久々のはてな

自分がブログ的なものを最初に書いたのは「はてなダイアリー」で、そのころは毎日更新するみたいなエグいことをしていた気がするんだが、今回はてなには久々に戻ってきた感じで、久々に書くいうよりもダイアリーからブログにデータ移行したあとに初めて書いた記事がこれのようだ。(一つ前の記事が 2013/05/21 という...)

最近は X(旧Twitter) で気軽にポストできない感じがしていて、かと言って Zenn とかでしっかりと技術的な内容のものを書けるわけでもないみたいな感じでもやもやしていたので、これからははてなブログに気軽に書いていこうかな。

CakePHP 2.3.5 のメール送信で文字化けをしたら

CakePHP 2.3.5 のCakeEmailはバグっていて、ISO-2022-JPの特定の文字が入っているメールを送信しようとすると文字化け(というか、特定の文字列以降、その行がざっくりなくなる)します。

既に修正パッチを pull-request して、とりこまれているので、2.3.6 以降では治っていることになると思うんですが、取り急ぎ治したい人は以下のファイルを修正してください。

  • lib/Cake/Network/Email/CakeEmail.php の 1257 行目付近

修正前

        foreach ($lines as $line) {
            if (empty($line)) {
                $formatted[] = '';
                continue;
             } 
             if (!preg_match('/\<[a-z]/i', $line)) {

修正後

        foreach ($lines as $line) {
            if (empty($line)) {
                $formatted[] = '';
                continue;
            }
            if (strlen($line) < $wrapLength) {
                $formatted[] = $line;
                continue;
            } 
            if (!preg_match('/<[a-z]+.*>/i', $line)) {

修正ポイントは・・・

  • ISO-2022-JPの「受」のような特定の文字には「
  • このメソッドは第2引数の $wrapLength より長い場合に、その行に対してwrap処理をするためのものだから、$wrapLengthより短いならその行は処理しなくていいはず
  • そもそも「<」にエスケープいらなくね?

そもそも、wordwrap関数をかけてみたり、文字列を $line[$i] というように何バイト目?いうやり方でとってきたりと、マルチバイトで大丈夫か?という処理が行われているので、基本的にメールで送信する1行は 998 バイト以上にしないようにしといたほうがいいです。(998バイト以上になると、いろいろとヤバイ処理を通るので...)

今回はスルーした「その行にタグらしきものが入った場合」についても、おいおい処理内容をチェックして、マルチバイトでも大丈夫にしていこうかなと思っていたり、思ってなかったり...

受け身ではなく手を動かすイベントの楽しさ

もう10月ですねぇ。いよいよ開催が再来週と迫ってきた PHPMatsuri 2011の リレーブログです。

昨日の @tanakahisateru さんの PHPMatsuri 2010 からの1年を振り返って からバトンをうけて書きます。

このリレーブログ、今まで書かれている内容がかなり熱い内容なので、ぜひご一読を!

PHPMatsuriでできること

PHPMatsuriはセミナーや勉強会と違って参加者が手を動かすことを基本としたイベントです。セミナーや勉強会で自分の知らなかった情報を得るのも楽しいのですが、自分でそれを身につけるにはやはり自分で手を動かすことが一番だと思います。(PHPMatsuriではセミナー形式のセッションも並行で行われますが、それを聞くのも良し、聞かずにもくもくとコードを書き続けるもよし、それは参加するあなたの自由です)

また、普段の仕事では使っていないフレームワークやライブラリを使っていろいろ試すということをとことんできる場だと思います。ここ数年symfomy 1.XやCakePHP 1.Xを使って仕事をしてきた人(自分もそうですが)にとって、Symfony 2やSilex、CakePHP 2.XやLithiumといったこれから主力となりそうなフレームワークでいろいろ試す絶好の機会です。

そして、PHPMatsuriではこれらのフレームワークの開発者が来日→参加するので、ちょっとした疑問でもばんばん聞けてしまうというまたとないチャンスとなります。日本にいながらにしてそれぞれのフレームワークの哲学を開発者本人から聞けてしまうというのは本当にすばらしいことだと思います。

昨年のPHPMatsuri 2010では結構夜遅くまで開発者の方々がメインの部屋に残られていたので、ちょっと勇気をだせばいくらでもお話が聞けると思いますよ。

PHPMatsuriの雰囲気

自分は昨年のPHPMatsuriからの参加で、しかも午前中に別の用事があったため、午後からの参加となったのですが、会場に着いたときになんとも言えない雰囲気にびっくりした覚えがあります。全員がノートパソコンを開いて周りと時には会話をしながらそれぞれがコードを書いている姿は今でも忘れられません。

その中に一度飛び込んでしまえば好きなだけコードを書いていられるというか、それぞれ別のことをしてるはずなのに独特の一体感があってコードを書く人にはたまらない雰囲気だと思います。

結局昨年は部屋にはもどらずずっとメインとなった会場で朝までコードを書いていたのですが、もっと時間があればなぁと思うくらいの充実感でした。

関西で行われる意義

個人的には今回のイベントでうれしいと思うところ。関西出身者としては関西でのイベントが少しでもふえてほしいなぁと思っていて、こういうイベントが関西で行われるってのは本当にうれしい。

PHPMatsuriのように超大物をゲストに呼んでとかになるとスタッフの皆さんが大変ご苦労されていると思うのですが、みんなが集まって一晩中コードを書こうぜ!ということなら場所さえあればできちゃうわけで、是非ともいろんなところで開催されてほしいですね。

来年はまた違う場所で行われるといいですよね。

手を動かしたら発表しよう

PHPMatsuriのいいところは、手を動かした結果をみんなの前で発表する場があるってこと。自分が作ったモノなんてたいしたことないなんて思わずに、ひとまず発表してみるってのがいいと思います。自分が普段当たり前だと思っていることが意外と周りの人からすると当たり前でないことが多いわけで、周りの人も何より自分自身でなにか発見するモノがあると思います。

まずは参加してみよう

だらだらと書きましたが、こんな楽しそうなイベント、チケットを購入すればいつでも潜り込むことができますよ。興味を持った方は是非チケットを購入して参加してみてください。

次は @k1Low さんがいらっしゃる Fusic さんのブログにつなぎます。よろしくお願いします。

セットアップ手順(不親切版)

とりあえず試したいという人がいるかもしれないので、ある程度自力でいろいろできる人向けのセットアップ手順を書いときます。(もっと親切なものは後から書くかもしれない)

サーバを準備する

EC2やNiftyクラウド、さくらVPSとかでサーバを準備してください。注意事項としてはPHPバージョンは5.2以上じゃないといけないです。

あと、一つ前のエントリで書いたようにメールが外部に送信できるようにしておいてください。

追記
ローカル環境にセットアップして、Firefox+Firemobilesimulatorとかで動作を試してみるってのがいいと思います。

ソースをgithubからとってくる

適当なディレクトリにソースをとってきてください。(例で使っているディレクトリはあくまで例です)

  cd /home/www
  git clone https://github.com/kunit/yammer.git
  cd yammer
  git submodule init
  git submodule update

YammerからOAuthのConsumer Key/Secretを取得して設定する

YammerのAPIをたたくために以下の手順でアプリケーションの登録を行って、Consumer Key/Secret を取得してください。

  • ガラケーでアクセスしたいネットワークのアカウントでYammerにログインする(※注意1)
  • http://developer.yammer.com/api/ にアクセスする
  • その画面の右上の Register Application のリンクをクリック
  • アプリケーションの情報を入力する。Application名は「Mobile Yammer for xxx」の形式にしていると他のものとかぶらないでいいと思う。(※注意2)
  • 入力してsubmitすると Consumer Key/Secret が発行される

(※注意1) YammerのOAuthの権限はネットワーク毎に発行されます。そのためログインしないとアプリケーションの登録作業ができないです。
(※注意2) このアプリケーション登録情報は今のところ後から変更できないっぽいので適当につけると後で泣きをみます

上記の手順で登録した内容を設定ファイルを作成して記述します。

  cp app/config/yammer.php.default app/config/yammer.php

yammer.php で設定するのは以下の4つです。

Yammer.oauth_mail_from
権限設定メールを送信するときのFrom
Yammer.oauth_mail_subject
権限設定メールを送信するときのSubject
Yammer.oauth_key
取得したConsumer Key
Yammer.oauth_secret
取得したConsumer Secret

CakePHPのセキュリティーの基本設定をする

core.phpをコピーしてつくってください。

 cp app/config/core.php.default app/config/core.php

core.phpの以下の2つの値を変更してください。(これはCakePHPの通常のセットアップでやることと同じなので、なんのこっちゃと思った場合は適当にぐぐってください。すみません)

  • Security.salt
  • Security.cipherSeed

テーブルを作成する

以下のコマンドを実行してテーブルを作成してください。実行するとy/nで答えるものが2つ出ますが、それらはEnterを押してデフォルトの答えのままで大丈夫です。

  cake/console/cake schema create

書き込み権限の付与

app/tmp 以下はWebサーバから書き込みができるように権限を変更してください。

  chmod -R a+w app/tmp

Webの公開設定

app/webroot をDocument RootとなるようにWebサーバの設定をしてください。また、.htaccessで設定が上書きできるようにしてください(このあたりはCakePHPの設定と同じです)

ここまでやれば(たぶん)つかえるはず。

...と書いてみたんですが予想通りとてつもなく不親切だなぁ。ファイル展開したらすぐ使えますとかになればいいんだろうけど、いくつかは設定してもらわないといかんし。これでどれくらいの人ができるかってのを様子を見ながらセットアップ手順の簡略化は考えます。

Yammer for ガラケー でなにをやってるか?

構築手順の説明の前にこのアプリでなにをやっているかを書いときます。

YammerのAPIをたたくためにOAuthを使って権限を取得しないといけないんですが、その取得の流れのURLがガラケーからは現状たたけないので、以下のような流れにしてます。

  1. ユーザにメールアドレスとパスワードをいれてもらう(このときのメールアドレスとパスワードはこの携帯サイトへのログインで使用するためのもので、Yammerのサイトで設定してあるものとまったく別物でかまわない)
  2. 入力してもらったメールアドレス宛にYammerのauthorizeのURLが入ったメールを送信する
  3. そのメールをPCでうけとってもらって、そこに入っているURLにPC側でアクセスして、アプリのアクセス許可をだす
  4. アクセス許可を出すと4桁のverifierが入手できるのでそれを携帯サイト側で入力する

1番目で入力したメールアドレスとパスワードでこのアプリにログインするとYammer APIを使用してメッセージを取得したりできるようになるので、なんかややこしい動きなのはこの権限を取得するところだけになります。

こんな流れになっているので、このアプリに保存される(デフォルトではSQLiteに保存してる)データはこのサイトにログインするためのメールアドレス/パスワードとOAuthで使用する各種キー/シークレットだけです。今のところメッセージやユーザ一覧等はその都度APIでとってきてるので、モバツイみたいにキャッシュして賢くなんやかんややってくれるとかはしてないです。(ユーザやグループの画像はそのまま使うとでかすぎるのでリサイズをする関係上キャッシュしてる形になってます)

アプリのセットアップをするためには携帯からWebアクセスできるだけではだめで、メールを送信して権限設定をするので、サーバからメールが送信できるように設定しておかないといけないです。(今のところそのサーバで外部からメールを受け取れるようにする必要はないです。将来的にはメールを使って画像付きメッセージ投稿とかできるようにするかもしれないので、そのときには必要になると思いますが)

Yammer for ガラケー ソース公開

Twitterでちょこちょこツイートしていたんだけど、震災以後作っていたYammerにガラケーからアクセスするためのゲートウェイとなるアプリケーションのソースをgithubで公開しました。

github - Yammer for Keitai

#いろいろソースを整理したりするつもりだったけど、大江戸Ruby会議から帰ってきて爆睡をしてしまったので、もうそのままでいいやってことでpushしてます...

CakePHPでささっとつくったもので、YammerのAPIをたたいているだけで、そんなにたいしたことはやってないです。

まぁ、今までガラケーでアクセスできなかったYammerがそれなりにつかえるようになるので、自分たち的には便利に使い始めてます。

で、この公開したソースを使ってどのようにサイトを構築するかの手順ですが、さらっと書こうと思ったらなにげにいろいろやらないといけないので、きちんとまとめてあとで書きます。すみません...

ControllerからModelを使用するいくつかの方法 (CakePHP Advent Calendar 19日目)

CakePHP Advent Calendar 2010 はみなさんのノウハウがいろいろと知ることができてほんと楽しいですね。

18日目のhaltさんのauthkittenプラグインで子猫認証 (CakePHP Advent Calendar 2010 18日目) を引き継いで、19日の記事となります。


※本日の記事は CakePHP 1.3.6 がベースになっています。

ControllerからModelを使用する方法ですが、一番手軽なのはControllerの「usesプロパティ」だと思います。

usesプロパティは以下の流れでモデルをロードします。

  • Dispatcher#dispatch (webroot/index.php)
  • Dispatcher#_invoke (cake/dispatcher.php)
  • Controller#constuctClasses (cake/libs/controller/controller.php)

Controller#constructClasses のソースは以下のようになっています。

function constructClasses() {
  $this->__mergeVars();
  $this->Component->init($this);

  if ($this->uses !== null || ($this->uses !== array())) {
    if (empty($this->passedArgs) || !isset($this->passedArgs['0'])) {
      $id = false;
    } else {
      $id = $this->passedArgs['0'];
    }

    if ($this->uses === false) {
      $this->loadModel($this->modelClass, $id);
    } elseif ($this->uses) {
      $uses = is_array($this->uses) ? $this->uses : array($this->uses);
      $modelClassName = $uses[0];
      if (strpos($uses[0], '.') !== false) {
        list($plugin, $modelClassName) = explode('.', $uses[0]);
      }
      $this->modelClass = $modelClassName;
      foreach ($uses as $modelClass) {
        $this->loadModel($modelClass);
      }
    }
  }
  return true;
}

最初のif文をよく見ると「!==」でチェックをしていて、Contrrolerでモデルをロードしたくなければ、厳密に「null」か「array()」でなければならないということがわかります。(モデルを使用しないつもりで false を代入してもダメなのはこのせいです)

usesプロパティが false(usesプロパティを指定してない場合も false になる) だと $this->modelClass を使用してモデルをロードします。($this->modelClass はデフォルトでは Controller 名から作られるもので UsersController なら User になるといった規約になります)

usesプロパティに対して配列指定でモデル指定した場合、1つめに設定した値を特別扱いし、$this->modelClassを上書きしています。複数指定する場合、適当に指定していいのではなくて、1つめは特別な意味を持つことを覚えておく必要があります。

さて、モデルのロードで使用されている Controller#loadModel ですが、これはフレームワーク内部だけで使われるものではなくて、我々が普段作成しているControllerの中でモデルをロードしたいときに使えるメソッドになります。(loadModelはCakeBookの「3.5.4.4.7 loadModel」にきちんと説明されています)

class FooController extends AppController {
  public function index()
  {
   // これで $this->Bar->... という形でモデルが使用できる
    $this->loadModel('Bar');
  }
}

Controllerで複数モデルを使用するときにusesに指定してしまうと、モデルを使用しないActionでも全てのモデルをロードしてしまうので、usesに指定するのは全Actionで使用するものだけにし、それ以外は loadModel でロードするのが効率がいいということになります。

Controller#loadModel のソースを見ると、ClassRegistry#init を使用してモデルクラスを生成しています。ClassRegistry#init 内でモデルクラスを生成しているソースの部分を抜き出してみます。(内部的にいろんなことをやってくれてるんですが、今回は説明に必要な部分だけ抜き出します。ClassRegistryに関しては id:hiromi2424 さんの「ClassRegistry徹底解剖」が参考になります)

  if (class_exists($class) || App::import($type, $pluginPath . $class)) {
    ${$class} =& new $class($settings);
  } elseif ($type === 'Model') {
    if ($plugin && class_exists($plugin . 'AppModel')) {
      $appModel = $plugin . 'AppModel';
    } else {
      $appModel = 'AppModel';
    }
    $settings['name'] = $class;
    ${$class} =& new $appModel($settings);
  }

ここで重要になってくるのが elseif の方で、うまくクラス生成ができなくて、さらにそれが Model だった場合、AppModel クラスとして生成されるということです。

usesプロパティに存在しないモデルを指定('User'と指定しないといけないのに'Users'にしてたとか)して、バリデーションがうまく動かずに困ったことがある人は結構いると思うんですが、それはここで AppModel が生成されるからになります。

ということで Controllerでモデルを使用する場合の注意点をまとめると...

  • uses プロパティには必要最低限のモデルを指定する
  • 追加でモデルをロードするには loadModel を使う
  • モデルを使用しない場合は null か array()
  • uses プロパティに存在しないモデルを指定すると AppModel になる

Modelのロードはそれなりに重たい処理なので、不必要なモデルは極力ロードしないように気をつけましょう!

ということで、明日の担当は connvoi_tyou さんです。よろしくお願いします!