現状、Apache+mod_phpをnginxで置き換えるとすると、nginx+spawn-fcgi+php-cgiを使ってる人が多いと思うんだけど、Ubuntuの公式リポジトリだとnginxのバージョンが低く(0.7系)、spawn-fcgiはinit.dスクリプトを書くかdaemontools使わなきゃいけないし、Apache+mod_phpみたいにインストール一発で動かせないので割とメンドクサイ。

同じこと思ってる人はnginxチームが提供しているaptリポジトリを使うと、nginx1.0.2+php5.3.5+php-fpmをaptでインストールできるので楽になりますよ。

既にnginxがインストールされている場合は念のためremoveしておく、spawn-cgiなどはkillしておきましょう。
以下、手順。

# nginxリポジトリを登録
$ sudo echo "deb http://ppa.launchpad.net/nginx/stable/ubuntu lucid main" > /etc/apt/sources.list.d/nginx-stable-lucid.list
$ sudo echo "deb http://ppa.launchpad.net/nginx/php5/ubuntu lucid main" > /etc/apt/sources.list.d/nginx-stable-lucid.list
$ sudo echo "deb-src http://ppa.launchpad.net/nginx/php5/ubuntu lucid main" > /etc/apt/sources.list.d/nginx-stable-lucid.list
$ sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys C300EE8C
# aptitudeのリストを更新
$ sudo aptitude update
# nginxをインストール
$ sudo aptitude install nginx
# PHP関連をインストール
$ sudo aptitude install php5 php5-cgi php5-cli php5-mysql php5-memcached php5-gd php5-curl php-pear php-apc php-fpm

インストールできたら、プロセスを確認してみる。

$ ps aux | grep nginx
root     14051  0.0  0.1  71092  1568 ?        Ss   May28   0:00 nginx: master process /usr/sbin/nginx
www-data 14052  0.1  0.2  72496  3568 ?        S    May28   3:47 nginx: worker process

$ ps aux | grep php
root     14238  0.0  0.3 182432  4944 ?        Ss   May28   0:25 php-fpm: master process (/etc/php5/fpm/main.conf)
www-data 14255  0.1  3.1 192428 48292 ?        S    May28   4:54 php-fpm: pool www
www-data 14256  0.1  4.0 207328 62988 ?        S    May28   4:43 php-fpm: pool www
www-data 14258  0.1  3.8 202720 59212 ?        S    May28   4:36 php-fpm: pool www
www-data 14291  0.1  3.6 199648 55496 ?        S    May28   4:39 php-fpm: pool www
www-data 14293  0.1  3.3 196576 52260 ?        S    May28   4:51 php-fpm: pool www
www-data 14294  0.1  3.4 196576 52952 ?        S    May28   4:47 php-fpm: pool www
www-data 14297  0.1  4.5 214756 70368 ?        S    May28   4:34 php-fpm: pool www
www-data 14298  0.1  3.1 192336 48900 ?        S    May28   4:46 php-fpm: pool www
www-data 14299  0.1  3.1 192332 48856 ?        S    May28   5:05 php-fpm: pool www
www-data 14300  0.1  2.9 191044 46132 ?        S    May28   4:58 php-fpm: pool www

ちゃんとユーザーwww-dataでphp-fpmのプロセスが起動されてますね。一番上のrootで実行されているのでphp-fpmの子プロセスを管理してるマスタープロセスです。起動していないければsudo service nginx startとsudo service php-fpm startで起動させて再度確認します。
起動するプロセス数やfastcgiのlisten URLなどは/etc/php5/php-fpm/pool.d/www.confにて設定します。

次に、nginxのバーチャルホストの設定。
下の設定だとwordpressとCakePHPは動くはず。

# /etc/nginx/sites-avilable/example.com

# www.example.comへのアクセスをexample.comへリダイレクト
server {
  listen 80;
  server_name www.example.com;
  rewrite ^(.*) http://example.com$1 permanent;
}
server {
  listen   80;
  server_name  example.com;

  access_log  /var/log/nginx/example.com.access.log;
  error_log  /var/log/nginx/example.com.error.log;

  root   /var/www/example.com;
  index  index.php index.html;

  try_files $uri $uri/ /index.php?q=$1;

  # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
  location ~ \.php$ {
    include fastcgi_params;
    fastcgi_pass   127.0.0.1:9000;
    fastcgi_index  index.php;
    fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
  }

  # deny access to .htaccess files, if Apache's document root
  # concurs with nginx's one
  location ~ /\.ht {
    deny  all;
  }
}

この内容を/etc/nginx/sites-available/example.comに保存し、/etc/nginx/sites-enabled/example.comからシンボリックリンクを張ります。

$ sudo vi /etc/nginx/sites-available/example.com
$ cd
$ sudo ln -s /etc/nginx/sites-availabe/example.com /etc/nginx/sites-enabled/example.com

ここまでやったらnginxとphp-fpmを再起動して、http://example.comをブラウザで開き、正常に動けばOKです。ダメだったら何とかしましょう。

 

CakePHPにもRailsでいうscaffold generatorのような、DBスキーマからCRUD画面を生成するbakeという機能があります。このbakeで生成するコードのテンプレートを予めカスタマイズしておくと、簡単なシステムなら非常に効率よく作れます。

しかしこの方法を説明している日本語版Cookbookが古いままである為、そのまま実践しても出力結果がデフォルトのままになってしまい大変残念なので、英語版Cookbookの該当ページを見ましょうっていうお話。

f you wish to modify the default HTML output produced by the “bake” command, follow these simple steps:
For baking custom views:
Go into: cake/console/templates/default/views
Notice the 4 files there
Copy them to your: app/vendors/shells/templates/[themename]/views
Make changes to the HTML output to control the way “bake” builds your views
The [themename] path segment should be the name of the bake theme that you are creating. Bake theme names need to be unique, so don’t use ‘default’.

Modify default HTML produced by “baked” templates

– 以下適当な意訳で解説 –

bakeコマンドで出力されるデフォルトHTMLを変更する場合、以下の手順を実行して下さい。
viewをカスタマイズする場合:

  1. cake/console/templates/default/viewsに移動する
  2. 4つのファイルがあるはず(index.ctp, form.ctp, view.ctp, home.ctp)
  3. これら4つのファイルをあなたのアプリケーションのapp/vendors/shells/templates/[themename]/viewsにコピーする
  4. コピーしたファイルを好きに編集したらbakeがそれを使ってコードを作ってくれる

ちなみに、[themename]の部分のディレクトリ名はあなた独自のものを指定する。特に’default’という名前は使わないこと。

– 解説以上 –

というわけで、上記の手順を実行すると、cake bakeしたときにthemeを選ぶ作業が追加されます。他のテーマが無ければ[themename]と’default’の2つから選ぶことになるので遠慮無く前者を選ぶとよいです。

デフォルトのテンプレートがあるcake/console/templates/default以下にはbakeで出力できる全てのテンプレートが置いてあるので、controllerやmodelなんかも修正できて大変便利です。ちなみにプロジェクトのテンプレートを編集する方法は上記の参考ページに書いてあるので是非見ることをお勧めします。

蛇足ですがググっても古い方の情報しか出てこないのでこの記事が上がるといいと思うし、
これを見た@hiromi2424が書き直してくれる気がする。

 

標題のとおりですが、google geocoding API v3だとjsonpに対応しておらず、ブラウザからリクエストすることができません。この場合、素直にgoogle map APIからGecoderオブジェクトを使うとよいです。






このへんはGoogle map API Referenceに書いてあるんですが探しづらいのでURL張っときます。
sample: geocoding-simple.html

以下、コード

<script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false&region=JP"></script>
<script type="text/javascript">
$(function(){
  var geocoder = new google.maps.Geocoder();
  $("#execute").click(function(){
    geocoder.geocode({
      address: $("#address").val()
    },
    function(data, status){
      if (status == google.maps.GeocoderStatus.OK) {
        $("#latitude").val(data[0].geometry.location.lat());
        $("#longitude").val(data[0].geometry.location.lng());
      } else {
        alert("次の理由でGoogle map APIがダメっぽいです: " + status);
      }
    });
  });
});
</script>
 

ちょっと友達がハマってたのでソースを確認したら間違っていたので訂正。

ソーシャルボタン”Share On Tumblr”をWordpressに入れる方法 | gori.me

PHPタグ閉じて無かったりurlencodeの中で呼んでるjavascriptのクオートがエスケープされてなかったりするので、これだとsyntax errorになります。wordpressの管理画面で貼り付けちゃったりすると、間違った状態で落ちたまま復帰不能になってSSHとかでゴニョゴニョすることになってめんどくさいので修正しました。

<a href="http://www.tumblr.com/share/link?url=<?php echo urlencode(get_permalink(get_the_ID())) ?>&name=<?php echo urlencode(get_the_title()) ?>&description=<?php echo urlencode(mb_substr(strip_tags(get_the_content()), 0, 140))?>" title="Share on Tumblr" style="display:inline-block; text-indent:-9999px; overflow:hidden; width:20px; height:20px; background:url('http://platform.tumblr.com/v1/share_4.png') top left no-repeat transparent; vertical-align:top;">Share on Tumblr</a>

tumblrのURLから、問題のあったdescriptionというパラメータをごっそり削っただけで動くんですが、せっかくなので全部修正しました。descriptionのところはtwitterぽく140文字でぶった切ってます。httpのget requestの仕様では512byteまでOKなので適宜調整して使って下さい。

 

railsは3からしか触っていないので以前がどうだったか知りませんが、rails3では独自のvalidationを作るのも簡単でよいです。
試しに、入力の書式を検証するFormatsValidatorというクラスを書いてみました。

# RAILS_ROOT/app/validators/formats_validator.rb
class FormatsValidator < ActiveModel::EachValidator

  def validate_each(record,attribute,value)
    begin
      r = __send__ options[:type].to_s, value
    rescue
      raise "Invalid option (type) is specified."
    end

    unless r
      record.errors[attribute] << (options[:message] || I18n.t('activerecord.errors.messages.invalid'))
    end
  end

  private
  # e-mail address
  def email(value)
    # 値を評価する式
  end
end

これをRAILS_ROOT/app/validators以下に配置して、modelから以下のように呼び出す。

class User < ActiveRecord::Base
  validates :mail_addr, :presence => true,
    :length => { :maximum => 255 }, :formats => { :type => :email }
end

modelのvalidatesメソッドの引数optionsはEachValidator::initializeに渡されるので、validate_eachでoptionsを参照することができます。
もとは1validatorにつき1クラスという想定っぽいですが、正規表現1行で使えるようなvalidatorはまとめてしまいたいときは使えそうですね。

 

標題の通りなんですが、Ubuntu 10.04 LTSをアップデートしたらウェルカムメッセージが2重になって大変気持ち悪い。

具体的には以下のようになっている。

Linux ip-10-170-90-19 2.6.32-314-ec2 #27-Ubuntu SMP Wed Mar 2 22:54:48 UTC 2011 i686 GNU/Linux
Ubuntu 10.04.2 LTS

Welcome to Ubuntu!
 * Documentation:  https://help.ubuntu.com/

  System information as of Tue May 10 09:28:09 UTC 2011

  System load:  0.91              Processes:           100
  Usage of /:   33.8% of 7.87GB   Users logged in:     0
  Memory usage: 8%                IP address for eth0: 10.170.175.104
  Swap usage:   0%

  Graph this data and manage this system at https://landscape.canonical.com/
---------------------------------------------------------------------
At the moment, only the core of the system is installed. To tune the
system to your needs, you can choose to install one or more
predefined collections of software by running the following
command:                                                             

   sudo tasksel --section server
---------------------------------------------------------------------

Ubuntu 10.04.2 LTS

Welcome to Ubuntu!
 * Documentation:  https://help.ubuntu.com/

  System information as of Tue May 10 09:24:16 UTC 2011

  System load:  0.0               Processes:           87
  Usage of /:   32.4% of 7.87GB   Users logged in:     0
  Memory usage: 58%               IP address for eth0: 10.170.175.104
  Swap usage:   0%

  Graph this data and manage this system at https://landscape.canonical.com/
---------------------------------------------------------------------
At the moment, only the core of the system is installed. To tune the
system to your needs, you can choose to install one or more
predefined collections of software by running the following
command:                                                             

   sudo tasksel --section server
---------------------------------------------------------------------

8 packages can be updated.
6 updates are security updates.

*** System restart required ***
Last login: Tue May 10 09:24:20 2011 from example.com

要するに、新しいウェルカムメッセージが表示された後にアップデート前に出ていたウェルカムメッセージが続けて表示されてしまっておるわけですね。気持ち悪い。

ウェルカムメッセージを表示しているmotdの仕様変更か何からしいです。

/etc/motd.tailをcatしてみるとわかるんですが、古いウェルカムメッセージがそのまま保存されっ放しになっておるのが原因なので、以下のようにすれば直ります。

$ sudo mv -f /etc/motd.tail /etc/motd.tail.org
 

標題の通り、PHPにおいて三項演算子をネストした時の挙動がおかしい話。
例えば、以下のようなコードの場合。

echo (1 == 1) ? "one" : (2 == 2) ? "two" : "false"; // "two"

他の主要な言語と同じように、”one”が表示されることを期待してたんですが”two”が表示されますね。何かの間違いかと思って3回ぐらい試した。

と思ったら、マニュアルにしっかり書いてありました。

三項演算子を “積み重ねて” 使用することは避けましょう。 ひとつの文の中で複数の三項演算子を使用した際の PHP の振る舞いは、 少々わかりにくいものです。

PHP: 比較演算子 – Manual

マニュアルの通り、基本的に三項演算子はネストすべきではないですが、どうしても使いたい場合は以下のように括弧を付けると期待通りの結果になります。

echo (1 == 1) ? "one" : ((2 == 2) ? "two" : "false"); // "one"

蛇足ですが、マニュアルの上記ページにあるようにPHP5.3からは三項演算子の真ん中が省略できるようになったようです。

$hoge = "hoge";
echo ($hoge) ?: "fuga"; // "hoge"

$hoge = null;
echo ($hoge) ?: "fuga";  // "fuga"

これはいい仕様変更ですね。

そもそも三項演算子をネストするのってどうなのよ、って話ではありますが、
ちょっとしたワンライナーを書くときなんかは便利に使えるので参考までに。

 

昨日と逆にrubyでsmtp経由でメールを送信する。

require 'net/smtp'
Net::SMTP.start('smtp.example.com', 587, 'example.com', 'hoge@example.com', 'fugafuga', 'plain') {|smtp|
      smtp.send_mail "test", "hoge@example.com", "to@mail.addr"
}

相変わらず簡単ですね。

通常のsmtp認証の場合は上記でOKです。POP before SMTPの場合は、Net::POPにPOP認証だけ行って接続を切るauth_onlyというメソッドがあるので送信前にそれを実行すればよい。

Net::POP3.auth_only( 'pop.example.com', 110, 'hoge@example.com', 'fugafuga' )
Net::SMTP.start('smtp.example.com', 587, 'example.com') {|smtp|
      smtp.send_mail "test", "hoge@example.com", "to@mail.addr"
}

参考: net/smtp – Rubyリファレンス

 

これだけ。

require 'net/pop'
Net::POP3.start('example.com', 110, 'hoge@example.com', 'fugafuga') do |pop|
  unless pop.mails.empty?
    pop.mails.each do |m|
      # 受信
      p m.pop
      # 削除
      m.delete
   end
  end
end

非常にシンプルでよろしいですね。

実はrubyの公式リファレンスにはこういう簡単なsnippetも載ってたりして調子が良いです。

net/pop – Rubyリファレンスマニュアル

 

rvmには、rvm環境のバイナリをラップして非rvm環境から叩く為の仕組みがある。

解説:

Using RVM with God(本家)

rvm で unicorn(日本語解説)

なので、例えばrvm環境のrails runnerをcronから叩きたい時は、まずrvm環境で以下のようにスクリプトを作っておき、

# rvm wrapper ruby-1.9.2-p180@rails3 rails3 rails

できあがったスクリプトを非rvm環境から普通に叩けばよい。

# $HOME/.rvm/bin/rails3_rails runner "MailReceiver.receive_with_pop" -e production

便宜上$HOME/.rvm以下としてるけど、適宜読み替えてください。

ちなみに私は、rvm環境の何かを叩くためのスクリプトを該当アプリのRAILS_ROOT/script以下に作っておき、そのスクリプトをcronに登録するようにしている。

© 2011 sanojimaru.com Suffusion theme by Sayontan Sinha