[processing]伝統模様を描いてみよう(Processing Advent Calendar 2011 – 9日目)

Posted under processing by uechoco on 金曜日 9 12月 2011 at 00 : 01 : 56

Processingの記事を書くのは本当に久しぶりです。
Processing Advent Calendar 2011に参加しておりまして、9日目の担当ということで執筆いたします。

みなさんは、伝統模様と聞いてパッとイメージが浮かぶでしょうか?
たぶん着物やハンカチなどの絵柄に使われているのを見たことがあるかもしれません。

伝統模様は

  • 同じパターンが繰り返し使われている
  • 幾何学的な模様が多い

といった観点からとても不思議な模様で、またProcessingの練習で描いてみる題材としても適していると思っています。

百聞は一見にしかず、いくつか私の描いたものをコード付きでご紹介します。

青海波(せいがいは)

Processing:
  1. // 青海波(せいがいは)
  2.  
  3. int r = 80;
  4. int r2 = r * 2;
  5.  
  6.   size(400, 400);
  7.   background(255, 255, 255);
  8.   smooth();
  9.   noLoop();
  10. }
  11.  
  12.   noStroke();
  13.   background(255, 255, 255);
  14.  
  15.   boolean flag = true;
  16.   for (int y = 0; y <height + r2; y += r) {
  17.     int x_base = flag ? 0 : r / 2 ;
  18.     for (int x = x_base; x <width + r2; x += r) {
  19.       drawPattern(x, y);
  20.     }
  21.     flag = !flag;
  22.   }
  23. }
  24.  
  25. void drawPattern(float cx, float cy) {
  26.   ellipseMode(CENTER_RADIUS);
  27.   int script[][] = {
  28.     {80, 0, 0, 0},
  29.     {75, 255, 255, 255},
  30.     {65, 0, 0, 0},
  31.     {60, 255, 255, 255},
  32.     {50, 0, 0, 0},
  33.     {45, 255, 255, 255},
  34.     {35, 0, 0, 0},
  35.     {30, 255, 255, 255},
  36.     {20, 0, 0, 0},
  37.     {15, 255, 255, 255},
  38.     {5, 0, 0, 0}
  39.   };
  40.   for (int i = 0; i <script.length; i++) {
  41.     int len = script[i][0];
  42.     fill(script[i][1], script[i][2], script[i][3]);
  43.     ellipse(cx, cy, len, len);
  44.   }
  45. }

青海波は文字通り波をイメージした模様です。私のコードでは、2重のfor文でx, y座標をずらしながら、
パターン化した白黒の円を上から塗り重ねることで、青海波っぽく描いています。

星七宝繋ぎ(ほししっぽう)

Processing:
  1. // 星七宝繋ぎ(ほししっぽう)
  2.  
  3. int r = 80;
  4. int r2 = r * 2;
  5.  
  6. float ct[] = new float[360];
  7. float st[] = new float[360];
  8.  
  9.   size(400, 400);
  10.   background(0, 0, 0);
  11.   smooth();
  12.   noLoop();
  13.  
  14.   ellipseMode(CENTER_RADIUS);
  15.  
  16.   for (int d = 0; d <360; d++) {
  17.     ct[d] = cos(radians(d));
  18.     st[d] = sin(radians(d));
  19.   }
  20. }
  21.  
  22.   background(0, 0, 0);
  23.  
  24.   stroke(255, 255, 255);
  25.  
  26.   noFill();
  27.   boolean flag = true;
  28.   for (int y = -20; y <height + r2; y += r) {
  29.     int x_base = -20 + (flag ? 0 : r);
  30.     for (int x = x_base; x <width + r2; x += r2) {
  31.       drawPattern(x, y);
  32.     }
  33.     flag = !flag;
  34.   }
  35.  
  36.   fill(0, 0, 0);
  37.   flag = true;
  38.   for (int y = -20; y <height + r2; y += r) {
  39.     int x_base = -20 + (flag ? 0 : r);
  40.     for (int x = x_base; x <width + r2; x += r2) {
  41.       drawPattern2(x, y);
  42.     }
  43.     flag = !flag;
  44.   }
  45. }
  46.  
  47. void drawPattern(float cx, float cy) {
  48.  
  49.   float p[][] = {
  50. //    {cx + r, cy - r, 0, 90, 180, 270},
  51. //    {cx - r, cy - r, 90, 180, 270, 360},
  52.     {cx - r, cy + r, 180, 270, 0, 90},
  53.     {cx + r, cy + r, 270, 360, 90, 180}
  54.   };
  55.  
  56.   for (int i = 0; i <p.length; i++) {
  57.     float tx = p[i][0];
  58.     float ty = p[i][1];
  59.     int crad_begin = (int)p[i][2];
  60.     int crad_end = (int)p[i][3];
  61.     int trad_begin = (int)p[i][4];
  62.     int trad_end = (int)p[i][5];
  63.  
  64.     beginShape(LINES);
  65.     for (int d = crad_begin; d <crad_end; d++) {
  66.       vertex(cx + ct[d] * r, cy - st[d] * r);
  67.     }
  68.     for (int d = trad_begin; d <trad_end; d++) {
  69.       vertex(tx + ct[d] * r, ty - st[d] * r);
  70.     }
  71.     endShape(CLOSE);
  72.   }
  73. }
  74.  
  75. void drawPattern2(float cx, float cy) {
  76.   ellipse(cx + r, cy, 10, 10);
  77.   ellipse(cx, cy + r, 10, 10);
  78. }

七宝模様は、円を重ね合わせることで、円の弧が星のように見える模様です。
私のコードはちょっと複雑ですね。たしか円を並べただけだと七宝模様に近づかなかったので、
円弧をvertex()で描いていったのだと記憶しています。

花亀甲(はなきっこう)

Processing:
  1. // 花亀甲(はなきっこう)
  2.  
  3. float ROOT_3 = (float)Math.sqrt(3);
  4. float ROOT_3_DIV_2 = ROOT_3 / 2.0;
  5.  
  6. float ROOT_2 = (float)Math.sqrt(2);
  7. float ONE_DIV_ROOT_2 = 1 / ROOT_2;
  8.  
  9. int ix = -20;
  10. int iy = -20;
  11. int r = 50;
  12. int r2 = r * 2;
  13. int in_r = r - 8;
  14.  
  15. float ct[] = new float[360];
  16. float st[] = new float[360];
  17.  
  18.   size(400, 400);
  19.   background(255, 255, 255);
  20.   smooth();
  21.   noLoop();
  22.  
  23.   for (int d = 0; d <360; d++) {
  24.     ct[d] = cos(radians(d));
  25.     st[d] = sin(radians(d));
  26.   }
  27. }
  28.  
  29.   background(255, 255, 255);
  30.  
  31.   boolean flag = true;
  32.   for (float y = iy; y <height + r2; y += r * 3 / 2) {
  33.     float x_base = ix + (flag ? 0 : r * ROOT_3_DIV_2);
  34.     for (float x = x_base; x <width + r2; x += r * ROOT_3) {
  35.       drawPattern(x, y);
  36.     }
  37.     flag = !flag;
  38.   }
  39. }
  40.  
  41. void drawPattern(float cx, float cy) {
  42.  
  43.   float out_len = r;
  44.   float in_len = r - 5;
  45.  
  46.   int deg_list[] = {30, 330, 270, 210};
  47.   int deg_list2[] = {30, 330, 270, 210, 150, 90, 30};
  48.  
  49.   // 外側の亀甲
  50.   stroke(0, 0, 0);
  51.   noFill();
  52.   drawTortoiseshell(cx, cy, r, deg_list);
  53.  
  54.   // 内側の亀甲
  55.   drawTortoiseshell(cx, cy, in_r, deg_list2);
  56.  
  57.   // 中央文様
  58.   drawFlower(cx, cy, 7, 30, 20);
  59. }
  60.  
  61. void drawTortoiseshell(float cx, float cy, float r, int[] deg_list) {
  62.   float ox = ct[deg_list[0]] * r;
  63.   float oy = -st[deg_list[0]] * r;
  64.   for (int i = 1; i <deg_list.length; i++) {
  65.     float nx = ct[deg_list[i]] * r;
  66.     float ny = -st[deg_list[i]] * r;
  67.     line(cx + ox, cy + oy, cx + nx, cy + ny);
  68.     ox = nx;
  69.     oy = ny;
  70.   }
  71. }
  72. void drawFlower(float cx, float cy, int thin, int len, int len2) {
  73.   noStroke();
  74.   fill(0, 0, 0);
  75.  
  76.   // 上の葉(90〜270)
  77.   // 下の葉(-90〜90)
  78.   for (int i = 0; i <360; i++) {
  79.     float x = - st[safe_degrees(i * 2)] * len / thin;
  80.     float y = ct[safe_degrees(i)] * len;
  81.     vertex(cx + x, cy + y);
  82.   }
  83.   endShape(CLOSE);
  84.  
  85.   // 右の葉(-90〜90)
  86.   // 左の葉(90〜270)
  87.   for (int i = 0; i <360; i++) {
  88.     float x = ct[safe_degrees(i)] * len;
  89.     float y = - st[safe_degrees(i * 2)] * len / thin;
  90.     vertex(cx + x, cy + y);
  91.   }
  92.   endShape(CLOSE);
  93.  
  94.   // 左下の葉(90〜270)
  95.   // 右上の葉(-90〜90)
  96.   for (int i = 0; i <360; i++) {
  97.     float x = - st[safe_degrees(i * 2)] * len2 / thin;
  98.     float y = ct[safe_degrees(i)] * len2;
  99.     float dx = -1 * ONE_DIV_ROOT_2 * (x - y);
  100.     float dy = -1 * ONE_DIV_ROOT_2 * (x + y);
  101.     vertex(cx + dx, cy + dy);
  102.   }
  103.   endShape(CLOSE);
  104.  
  105.   // 右下の葉(90〜270)
  106.   // 左上の葉(-90〜90)
  107.   for (int i = 0; i <360; i++) {
  108.     float x = ct[safe_degrees(i)] * len2;
  109.     float y = - st[safe_degrees(i * 2)] * len2 / thin;
  110.     float dx = -1 * ONE_DIV_ROOT_2 * (x - y);
  111.     float dy = -1 * ONE_DIV_ROOT_2 * (x + y);
  112.     vertex(cx + dx, cy + dy);
  113.   }
  114.   endShape(CLOSE);
  115. }
  116.  
  117. int safe_degrees(int deg) {
  118.   while (deg>= 360) deg-=360;
  119.   while (deg <0) deg += 360;
  120.   return deg;
  121. }

亀甲模様に花柄がついた、花亀甲という模様です。コードもだいぶ複雑になって来ました。プログラムは太い亀甲を描くルーチン、細い内側の亀甲を描くルーチン、そして花柄模様を描くルーチンの3種類に分かれています。そしてそれらを1つのぱたーんとしてまとめあげて、亀甲の中心点を移動させることでパターン化しています。花柄を描くときやcos()やsin()に係数を掛けて、円を歪ませることで花びらの1枚1枚を描いています。

先ほどの星七宝のコードでも出てきたのですが、私のコードでは、cos()とsin()を0〜359度分、予め計算した状態で配列に確保しています。
これはコードの内部で使用する角度をを0〜359の整数に限定することで、描画中にcos()関数、sin()関数の結果がそれぞれ360通りに限定されるので、予め計算しておくことが出来るようになっています。小さな静止画を描くときはそこまで効力を発揮しないのですが、動く物体を描くときや、大量にcos()、sin()関数を使うときは非常に高速に計算ができます(関数を呼び出して計算させるより、予め計算結果を溜めておいたものを使用したほうが速のです)。

武田菱(たけだびし)

武田氏の家紋である「四つ割菱」の入った模様です。

Processing:
  1. // 武田菱(たけだびし)
  2.  
  3. float ROOT_3 = (float)Math.sqrt(3);
  4. float ROOT_3_DIV_2 = ROOT_3 / 2.0;
  5.  
  6. int ix = -60;
  7. int iy = -60;
  8. int block_w = 100;
  9. int block_h = 60;
  10. float ey = 10;
  11. float ex = ey * ROOT_3;
  12.  
  13. float ct[] = new float[360];
  14. float st[] = new float[360];
  15.  
  16.   size(400, 400);
  17.   background(0, 0, 0);
  18.   smooth();
  19.   noLoop();
  20.  
  21.   for (int d = 0; d <360; d++) {
  22.     ct[d] = cos(radians(d));
  23.     st[d] = sin(radians(d));
  24.   }
  25. }
  26.  
  27.   background(0, 0, 0);
  28.  
  29.   strokeJoin(MITER);
  30.  
  31.   boolean flag = true;
  32.   for (float y = iy; y <height + block_h; y += (block_h + ey) / 2) {
  33.     float x_base = ix + (flag ? (block_w + ex) / 2 : 0);
  34.     for (float x = x_base; x <width + block_w; x += block_w + ex) {
  35.       drawPattern(x, y, block_w, block_h);
  36.     }
  37.     flag = !flag;
  38.   }
  39. }
  40.  
  41. void drawPattern(float x, float y, float block_w, float block_h) {
  42.  
  43.   float subblock_w = block_w / 2;
  44.   float subblock_h = block_h / 2;
  45.   float cx = x + subblock_w;
  46.   float cy = y + subblock_h;
  47.   int m = 8;
  48.  
  49.   stroke(255, 255, 255);
  50.   noFill();
  51.   for (int i = m; i>= 4; i-=2) {
  52.     float w = lerp(0, subblock_w, i / (float)m);
  53.     float h = lerp(0, subblock_h, i / (float)m);
  54.     quad(
  55.       cx, cy - h,
  56.       cx - w, cy,
  57.       cx, cy + h,
  58.       cx + w, cy
  59.     );
  60.   }
  61.   float w = lerp(0, subblock_w, 4 / (float)m);
  62.   float h = lerp(0, subblock_h, 4 / (float)m);
  63.   line(cx - w / 2, cy - h / 2, cx + w / 2, cy + h / 2);
  64.   line(cx + w / 2, cy - h / 2, cx - w / 2, cy + h / 2);
  65. }
  66.  
  67. int safe_degrees(int deg) {
  68.   while (deg>= 360) deg-=360;
  69.   while (deg <0) deg += 360;
  70.   return deg;
  71. }

こちらのコードはそこまで複雑ではありません。四角形を描くquad()関数を多用して、上手く菱形を描いています。

おわりに

簡単ではありますが、伝統模様をお見せしました。
これ以外にも伝統模様はたくさんありますので、調べてみて、「この模様はどうやってProcessingで描いたら上手く書けるかな?」なんて考えてみてはいかがでしょうか。伝統模様に限らず、身近なデザインでも「Processingでどうやって書いたらいいかな?」って考えてみると、Processingの腕が上達するかもしれません。

それでは、次回は@reona396さんです。よろしくお願いします!


[Symfony2]入出力の文字エンコードを変換してみよう Symfony Advent Calender JP 2011 – 6日目-

Posted under php,Symfony2 by uechoco on 火曜日 6 12月 2011 at 10 : 00 : 00

@uechocoです。Symfony Advent Calendar JP 2011の6日目の記事です。@fivestrさんからのバトンタッチです。

日本Symfonyユーザー会に所属するスタッフとして、勢いで申し込んでみたものの、
普段職場でSymfonyを使ってないのでネタ探しに苦労しました。

そういえば去年のSymfony Advent 2010 : ATNDでは[Symfony2]PEAR::Net_UserAgent_MobileをDIコンテナから呼び出すという記事を書きました。
今年も似たような領域で、ガラケー向けのWebサイト開発で使えるかもしれないテクニックとして、入出力される値やコンテンツの文字コードを変換する方法をご紹介します。

symfony 1.x系ではMojavi由来のフィルタチェインの機構がありましたので、
MobileEncodingFilterなどのクラスを作って、入出力の前後でエンコードの変換をかませるというのが一般的だったかと思います。

Syfmony2系ではフィルタチェインという概念はなくなってしまいました。
代わりに処理の所々にイベントが定義されていて、リスナーを登録しておくと自動的にディスパッチしてくれるようなイベントドリブン方式に変わりました。

今回はSymfony2のHttpKernel機構に標準で設定されているkernel.requestイベントとkernel.responseイベントのリスナークラスとしてMobileEncodingListenerを作り、入出力のエンコード処理を行なっています。今回はSymfonyに標準で同梱されているAcme\DemoBundleの中に作成する前提です。

MobileEncodingListenerクラスの作成

まずはイベントリスナークラスを作成します。Symfony本体のFrameworkBundleやHttpKernelコンポーネントのディレクトリ構造の慣習に従ってAcme\DemoBundleの下にEventListenerディレクトリを作成し、その下にイベントリスナークラスを作成します。以下のようなMobileEncodingListnerクラスを作成してください。まだ中身は実装しません。

php:
  1. <?php
  2.  
  3. namespace Acme\DemoBundle\EventListener;
  4.  
  5. /**
  6.  * Convert input encoding or output encoding.
  7.  * @author uechoco <uechoco at gmail.com>
  8.  *
  9.  */
  10. class MobileEncodingListener
  11. {
  12. }

kernel.responseイベント

まずは簡単なkernel.responseイベントに対するメソッドを記述します。クラスの使用宣言を追加して、MobileEncodingListenerクラスにonKernelResponse()メソッドを実装します。

php:
  1. use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
  2. use Symfony\Component\HttpKernel\HttpKernelInterface;

php:
  1. /**
  2.      * Convert output encoding of response.
  3.      * @param FilterResponseEvent $event
  4.      */
  5.     public function onKernelResponse(FilterResponseEvent $event)
  6.     {
  7.         if (HttpKernelInterface::MASTER_REQUEST !== $event->getRequestType()) {
  8.             return;
  9.         }
  10.  
  11.         $response = $event->getResponse();
  12.  
  13.         $response->setContent(mb_convert_encoding($response->getContent(), 'SJIS-win', 'UTF-8'));
  14.     }

中身の処理としては単純で、Resopnseオブジェクトを取得し、その中のコンテンツの文字コードを変換してまたセットしなおしているだけです。今回は説明の簡略化のために文字コードの部分を直書きしています。最初の行のマスターリクエスト以外なら何もしないという条件文がありますが、HttpKernelではリクエストの種別が2種類あり、マスターリクエストとサブリクエストと呼ばれています。そのマスターリクエストの時だけ処理したいので条件式を記述しています。FilterResponseEventクラスを受け取るというのはkernel.responseイベントとの仕様として決められています。

kernel.requestイベント

次にkernel.requestイベントに対するメソッドを記述します。先ほどと同様にクラスの使用宣言を追加して、MobileEncodingListenerクラスにonKernelRequest()メソッドを実装します。

php:
  1. use Symfony\Component\HttpKernel\Event\GetResponseEvent;

php:
  1. /**
  2.      * Convert input encoding of request.
  3.      * @param GetResponseEvent $event
  4.      */
  5.     public function onKernelRequest(GetResponseEvent $event)
  6.     {
  7.         if (HttpKernelInterface::MASTER_REQUEST !== $event->getRequestType()) {
  8.             return;
  9.         }
  10.  
  11.         $request = $event->getRequest();
  12.  
  13.         // GET
  14.         $get = $request->query->all();
  15.         mb_convert_variables('UTF-8', 'SJIS-win', $get);
  16.         $request->query->replace($get);
  17.         // POST
  18.         $post = $request->request->all();
  19.         mb_convert_variables('UTF-8', 'SJIS-win', $post);
  20.         $request->request->replace($post);
  21.     }

こちらもマスターリクエストのみ処理する記述が最初にあります。次にRequestオブジェクトを取得し、今回は$_GETと$_POSTに相当する変数だけを文字コード変換しました。$_GETと$POSTはRequestオブジェクトの$queryと$requestというパブリック変数に代入されています。形式としてはParameterBagというクラスでラッピングされて代入されています。ParameterBagクラスのインターフェースとしてall()メソッドで全配列を取得し、replace()メソッドで全配列を総取替しています。

イベントリスナーとして登録する

最後に、先ほど作ったクラスとメソッドをイベントリスナーとして登録します。登録手順はDIコンテナにサービスとして登録するのと同じですが、特別なタグを定義することでイベントリスナーとして認識されるようになっています。src/Acme/DemoBundle/Resources/config/services.xmlを開き、以下のように追記してください。

XML:
  1. <!-- 省略 -->
  2.  
  3.     <parameters>
  4.         <parameter key="mobile_encoding_listener.class">Acme\DemoBundle\EventListener\MobileEncodingListener</parameter>
  5.     </parameters>
  6.  
  7.     <services>
  8.         <!-- 省略 -->
  9.         <service id="acme.demo.mobile_encoding_listener" class="%mobile_encoding_listener.class%">
  10.             <tag name="kernel.event_listener" event="kernel.request" method="onKernelRequest" />
  11.             <tag name="kernel.event_listener" event="kernel.response" method="onKernelResponse" />
  12.         </service>
  13.     </services>
  14.  
  15.     <!-- 省略 -->

確認する

何事もなければデモ画面が正常に動作すると思います。プロファイラのEvent項を見てみると、リスナーが登録されていることが確認できます。

今回直書きだった文字コードの指定は、config.ymlなどの設定ファイルから取ってくるような仕様にしたり、UserAgentを判別して決定するような仕様にしたほうが汎用性が高いでしょう。

余談

今回の記事の参考にするために他のイベントリスナークラスを見ていましたが、イベントリスナークラスの実装は様々なパターンが存在しているようです。例えば1つのリスナークラスに2つ以上のイベントメソッドをもたせているものや、1クラス1イベントメソッドのもの、他の役割のあるクラスにイベントメソッドを持たせてリスナークラスを兼任させているものなどです。

SymfonyのHttpKernelにどのようなイベントがあるか知りたい方は、Symfonyの内部構造のドキュメントの一節にイベントについて書かれている部分がありますので、そちらを参照してください。

最後に

7日目はMongoDB JPにも所属している@madapajaさんです。よろしくお願いします。


[php]homebrewでintlライブラリが有効なphpをコンパイルする

Posted under php by uechoco on 日曜日 4 12月 2011 at 14 : 42 : 24

Symfony2などを使用する場合、php 5.3のintlという国際化用拡張モジュールがインストールされていないと警告が出たり一部の機能が使用することができません。

私のMacBook Airに標準で入っているphpは5.3.6ですが、intlライブラリは含まれていません。

そこで、今回はMac OSX 10.7 Lionのhomebrewでintlライブラリが有効なphpをコンパイルし、加えてSymfony2のcheck.phpと呼ばれる環境チェックスクリプトで警告が出ないようにしてみます。私のphpは標準のものに対してライブラリを加えているため、皆さんよりも追加でインストールする項目が少ないかもしれません。

intlオプションが有効なphp formula

phpは標準でインストールされているため、homebrewのformulaは有りません。そこで、非公式に作られているformulaを使用します。
ココらへんの手順はいくつかの記事を参考にしました。

Bash:
  1. brew install https://github.com/adamv/homebrew-alt/raw/master/duplicates/php.rb --with-mysql --with-intl

このとき、使用可能なオプションはoptionsコマンドで見ることができます。

TEXT:
  1. brew options https://github.com/adamv/homebrew-alt/raw/master/duplicates/php.rb
  2. php
  3. --with-mysql
  4.     Include MySQL support
  5. --with-mariadb
  6.     Include MariaDB support
  7. --with-pgsql
  8.     Include PostgreSQL support
  9. --with-mssql
  10.     Include MSSQL-DB support
  11. --with-fpm
  12.     Enable building of the fpm SAPI executable (implies --without-apache)
  13. --without-apache
  14.     Build without shared Apache 2.0 Handler module
  15. --with-intl
  16.     Include internationalization support
  17. --without-readline
  18.     Build without readline support
  19. --with-gmp
  20.     Include GMP support

依存関係のあるlibxml2, mcrypt, icu4cなどもコンパイルされたあと、php本体もコンパイルされます。少し時間がかかるので、気長に待ちましょう.。

apacheの設定

phpのコンパイルが終了すると、以下のようなメッセージが出てきます。

TEXT:
  1. For 10.5 and Apache:
  2.     Apache needs to run in 32-bit mode. You can either force Apache to start
  3.     in 32-bit mode or you can thin the Apache executable.
  4.  
  5. To enable PHP in Apache add the following to httpd.conf and restart Apache:
  6.     LoadModule php5_module    /usr/local/Cellar/php/5.3.8/libexec/apache2/libphp5.so
  7.  
  8. The php.ini file can be found in:
  9.     /usr/local/etc/php.ini
  10.  
  11. 'Fix' the default PEAR permissions and config:
  12.     chmod -R ug+w /usr/local/Cellar/php/5.3.8/lib/php
  13.     pear config-set php_ini /usr/local/etc/php.ini

例えば、Webサーバーがapache であれば「LoadModule php5_module /usr/local/Cellar/php/5.3.8/libexec/apache2/libphp5.so」を/etc/apache2/httpd.confに追加しまししょう。(元々入っているのphp5_moduleの行があるので、そちらは先頭に「#」をつけてコメントアウトしておきましょう。)

また新しいphpのiniファイルは「/usr/local/etc/php.ini」にありますので標準の場所と異なるのを気をつけましょう。

PEARライブラリののパーミッションも直しておくと便利です。「chmod -R ug+w /usr/local/Cellar/php/5.3.8/lib/php」というコマンドはすぐに通るかも知れませんが、「pear config-set php_ini /usr/local/etc/php.ini」のときに「/User/hogehoge/.pearrc」が作れないといったエラーがあった場合は、touchコマンドなどで事前に作成してあげて、パーミッションを777にでもしておいてください。

この時点で「php --version」としても、まだ元々のphpコマンドの方を参照しているでしょう。「which php」とすると「/usr/bin/php」を参照しているためです。コマンドラインが読み込まれた段階でbrew側のコマンド群を優先的に読みこむようにしましょう。ここではシェルがbashの想定で設定ファイルを書きます。

Bash:
  1. vi ~/.bash_profile

としてこの1行を追加しましょう。

TEXT:
  1. export PATH="$(brew --prefix)/bin:$PATH"

最後に、bashの設定を反映させます。

Bash:
  1. source ~/.bash_profile

この時点でphp --versionすると、新しいほうのphpが参照されているでしょう。

TEXT:
  1. PHP 5.3.8 (cli) (built: Dec  4 2011 13:40:01)
  2. Copyright (c) 1997-2011 The PHP Group
  3. Zend Engine v2.3.0, Copyright (c) 1998-2011 Zend Technologies

timezoneの設定

新しいphp.iniが作成されたので、最低限の設定としてtimezoneの設定をしておかないと、いずれ警告が出てしまいます。

Bash:
  1. vi /usr/local/etc/php.ini

diff形式でいうと、以下のように変更してください。

TEXT:
  1. -;date.timezone =
  2. +date.timezone = "Asia/Tokyo"

APCのインストール

この時点でintl込のphpが動くのですが、最後にSymfony2用にAPCライブラリもコンパイルして用意しましょう。

Bash:
  1. brew install apc

と打つだけです。

インストール後、以下のようなメッセージが表示されます。

TEXT:
  1. To finish installing APC:
  2.  * Add the following lines to php.ini:
  3.     [apc]
  4.     extension="/usr/local/Cellar/apc/3.1.9/apc.so"
  5.     apc.enabled=1
  6.     apc.shm_segments=1
  7.     apc.shm_size=64M
  8.     apc.ttl=7200
  9.     apc.user_ttl=7200
  10.     apc.num_files_hint=1024
  11.     apc.mmap_file_mask=/tmp/apc.XXXXXX
  12.     apc.enable_cli=1
  13.  * Restart your webserver
  14.  * Copy "/usr/local/Cellar/apc/3.1.9/apc.php" to any site to see APC's usage.

書いてあるとおりに、「/usr/local/etc/php.ini」にapcの設定を追加し、webサーバーを再起動します。最後のスクリプトのコピーは、APCの便利スクリプトなので、今はいりません。

Symfony2のapp/check.phpを見る

Symfony2のapp/check.phpを使って、環境が整っているかチェックしてみましょう。(その前にSymfony2の本体をDLしておいてください。)

Symfony2のルートディレクトリに移動し、以下のコマンドでapp/check.phpを実行します。

Bash:
  1. php app/check.php

TEXT:
  1. ********************************
  2. *                              *
  3. *  Symfony requirements check  *
  4. *                              *
  5. ********************************
  6.  
  7. php.ini used by PHP: /usr/local/etc/php.ini
  8.  
  9. ** WARNING **
  10. *  The PHP CLI can use a different php.ini file
  11. *  than the one used with your web server.
  12. *  If this is the case, please ALSO launch this
  13. *  utility from your web server.
  14. ** WARNING **
  15.  
  16. ** Mandatory requirements **
  17.  
  18.   OK        Checking that PHP version is at least 5.3.2 (5.3.8 installed)
  19.   OK        Checking that the "date.timezone" setting is set
  20.   OK        Checking that app/cache/ directory is writable
  21.   OK        Checking that the app/logs/ directory is writable
  22.   OK        Checking that the json_encode() is available
  23.   OK        Checking that the SQLite3 or PDO_SQLite extension is available
  24.   OK        Checking that the session_start() is available
  25.   OK        Checking that the ctype_alpha() is available
  26.   OK        Checking that the token_get_all() is available
  27.   OK        Checking that the APC version is at least 3.0.17
  28.  
  29. ** Optional checks **
  30.  
  31.   OK        Checking that the PHP-XML module is installed
  32.   OK        Checking that the token_get_all() function is available
  33.   OK        Checking that the mb_strlen() function is available
  34.   OK        Checking that the iconv() function is available
  35.   OK        Checking that the utf8_decode() is available
  36.   OK        Checking that the posix_isatty() is available
  37.   OK        Checking that the intl extension is available
  38.   OK        Checking that the intl ICU version is at least 4+
  39.   OK        Checking that a PHP accelerator is installed
  40.   OK        Checking that php.ini has short_open_tag set to off
  41.   OK        Checking that php.ini has magic_quotes_gpc set to off
  42.   OK        Checking that php.ini has register_globals set to off
  43.   OK        Checking that php.ini has session.auto_start set to off
  44.  
  45. ** Optional checks (Doctrine) **
  46.  
  47.   OK        Checking that PDO is installed
  48.   OK        Checking that PDO has some drivers installed: mysql, sqlite, sqlite2

基本的な警告はなくなりました。これでSymfony2を楽しむ環境が整いましたね!


« 前ページへ

Copyright © 2012 うえちょこ@ぼろぐ. WP Theme created by Web Top.