カテゴリー : 2007年 6月

symfony の基礎 – セッションとスコープ


Action クラスにて

スコープ get 方法 set 方法 用途
インスタンス スコープ(ページ スコープ) echo $this->foo; $this->foo = “boo”; View でローカル変数のように参照可能
リクエストスコープ $this->getRequest()->getAttribute(“key”) $this->getRequest()->setAttribute(“key”,$value) リダイレクト時などアクション間でのデータ参照に利用
ユーザスコープ($_SESSION と同等) $this->getUser()->getAttribute(“key”) $this->getUser()->setAttribute(“key”, $value) ショッピングカートなどページ遷移のあるトランザクションで利用

J2EE でのスコープと照らし合わせて symfony での変数(データホルダ)の種類をリストアップしました。
(アプリケーションスコープについては必要性が薄いので割愛)
 
参考:
- パラメータホルダー(symfony book 日本語ドキュメント)

GDB でコアダンプの原因を探る


プログラム実行中に Segmentation Fault や Bus Error などで Core dumped となった場合、
core ファイル(または *.core)が作業ディレクトリに出力されます。
 
これを解析する場合, GDB(GNU Project Debugger)コマンドが有用です。

$ gdb <コアダンプした実行可能バイナリ> <コアダンプファイル>

例えば以下の perl のスクリプト(仮に foo.pl とします)の実行中にコアダンプした場合..

#!/bin/perl
 
# 何かの処理
 

この場合はスクリプト(foo.pl)ではなく、実際にコアダンプしたバイナリプログラム(/bin/perl)について gdb を実行します。

$ gdb /usr/bin/perl core
GNU gdb 4.18 (FreeBSD)
Copyright 1998 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type “show copying” to see the conditions.
There is absolutely no warranty for GDB. Type “show warranty” for details.
This GDB was configured as “i386-unknown-freebsd”…Deprecated bfd_read called at /usr/src/gnu/usr.bin/binutils/gdb/../../../../contrib/gdb/gdb/dbxread.c line 2627 in elfstab_build_psymtabs
Deprecated bfd_read called at /usr/src/gnu/usr.bin/binutils/gdb/../../../../contrib/gdb/gdb/dbxread.c line 933 in fill_symbuf
 
Core was generated by `perl’.
Program terminated with signal 11, Segmentation Fault.
 
以下ライブラリ読み込み、エラー箇所表示が続く

 
具体的なトレースの仕方については参考サイト参照のこと。
 
参考:
-gdbを用いたデバッグ
  core ダンプ解析方法を含む GDB によるデバッグの基本が分かりやすく書かれています。
 
-Debugging with GDB(日本語)
  GDB 公式ドキュメント日本語訳

symfony – データベースを扱うには?


symfony ではデータベース処理に Propel を使っています。
次の手順を踏むことで、テーブルをオブジェクトとして扱うことが可能になります。
 
1. propel.ini の設定

<project_dir>/config/propel.ini

 

$ symfony propel-*-*

で利用するデータベース接続の設定.
propel.database.* の設定を変える以外はデフォルトでよい。

; unix socket 接続(TCP接続ならデフォルトにならえばよい)
propel.database.createUrl = mysql://root:dbpass@unix+/
propel.database.url = mysql://root:dbpass@unix+/dbname

 
2. databese.yml の設定

<project_dir>/config/database.yml

web,batch から利用する symfony の設定

all:
  propel:
    class: sfPropelDatabase
    param:
# dsn: mysql://root:dbpass@localhost/dbname
# unix socket 接続
        phptype: mysql
        hostspec:
        database: dbname
        username: root
        password: dbpass
        port:
        encoding: utf8
        persistent:

3-1. DB, テーブルを設定ファイルから新しく作る場合,
こちら(symfony で開発日記)を参考に、

config/schema.yml

を以下のように設定する

propel:
  table1:
  table2:
    _attributes: { phpName: FooTable }
    table1_id:
    name: varchar(255)
    amount:
       type: integer
       unsigned:true
       notnull:true
    created_at:
    updated_at:

説明..
  propel: … 接続名。
  table1 が最低限のテーブル構造例(id カラムのみ持つ)。
  table2 については以下のカラムを定義している
     id … int not null auto_increment primary key。デフォルトで定義される。
     table1_id .. int 型。 <table_name>_id とすることで table_name に Foreign key を張る
     amount … amount int unsigned not null というカラム定義。
     created_at … DATETIME 型。symfony がレコード作成日時を自動挿入してくれる
     updated_at … DATETIME 型。symfony がレコード更新日時を自動挿入してくれる。
  また、table2 はモデルクラスにマッピングする時(後述)に、
   __attributes: { phpName: FooTable } で指定した名前(FooTable)でマッピングされます。
 
3-2. propel.ini で設定した名前の空の DB を作成する。

symfony propel-build-db

 
3-3. schema.yml から CREATE TABLE の SQL 文を生成する

symfony propel-build-sql

 
3-4. (3-3) で生成した SQL 文を実行してテーブルを作成する。

symfony propel-insert-sql

 
Note: 3-1 とは逆に既存 DB のテーブルから schema.yml を作成するには

symfony propel-build-schema

を実行します。
 
4. symfony プロジェクトで利用できるように schema.yml からモデルクラスを生成する

symfony propel-build-model

ここで生成したモデルクラスは

<project_dir>/lib/model/

以下に作成されます。
 
5. (4)で作成したモデルクラスを使い、symofony プロジェクト内で参照する

apps/app_name/modules/model_name/actions/actions.class.php

等で以下のようにして参照します(require,include は不要)。

public function executeIndex()
{
   // 最も簡単なレコード挿入の例
    // 新規レコード用インスタンスを生成
    $table1 = new Table1();
    // データベースに実際にレコードを書き込む
    $table1->save();
 
   // カラムに値を設定して挿入する例
    $fooTable = new FooTable();
    
    $fooTable->setTable1Id(1); // カラム table1_id に 1 を指定
    $fooTable->setName(“milk”); // カラム name に milk を指定
    $fooTable->setAmount(123); // カラム amount に 123 を指定
    // 書き込む
    $fooTable->save();
 
   // プライマリキーからカラムを取得し、削除する例
    // プライマリキーカラム(id)が 1 のレコードのインスタンスを取得する
    $fooTable = FooTablePeer::retrieveByPK(1);
    if($fooTable){
        // id = 1 のレコードがあれば削除
        $fooTable->delete();
    }
     
    // 更新の場合, 既存レコードを取得して変更後 save() すればよい。
     $fooTable = FooTablePeer::retrieveByPK(1);
     if($fooTable){
         $fooTable->setAmount(10);
         $fooTable->save();
     }
    
    // プライマリキー以外からレコードを得る場合は *Peer::doSelect(), doSelectOne() を使う
     // 単純に SELECT した場合の一番始めのレコードを取得
     $fooTable = FooTablePeer::doSelectOne(new Criteria());
     
     // name が milk で, 作成日時の古い順に全てのレコードを配列で取得
     $c = new Criteria();
     $c->add(FooTablePeer::NAME, “milk”); // 条件
     $c->addAscendingOrderByColumn(FooTablePeer::CREATED_AT); // ORDER
     $tables = FooTablePeer::doSelect($c);
     
}

Criteria クラスの利用方法については
The Definitive Guide to symfony
8 章(日本語)の Criteria についての項に詳細に書かれています。
なお、Criteria クラスの実体は symfony インストールフォルダの

vendor/propel/util/Criteria.php

で定義されています。
  
参考:
-symfony フレームワークテスト置場
  おおまかな手順、設定ファイルの設定の仕方、それぞれの意味など。
-symfony book 日本語ドキュメント コマンドラインインターフェイス

 symfony propel-*-*

についてはこちらを参照。
-schema.yml がどこまで楽させてくれるか(symfony で開発日記)
  schema.yml の書き方についてまとめられています。
-MySQL4.1以降+symfonyのときのdatabase.yml
  MySQL4.1 以降では encoding: utf8 を指定しないと化ける、とのこと。

文法チェック


GNU ChangeLog フォーマットでは TAB + * から始まる行が記事中にあってはいけないのか、chalow で文中で他のトピックとして扱われてしまいます。
 
なので、

cat ChangeLog | perl -ne ‘if(/\t[*]/ && !/\]:/){print “Line ” . $. . “:”;print;}’

として、

<tab>*

からはじまり、なおかつ

<tab>* …. [....]:

という書式を満たさない行を抽出して個別修正しました。

The Definitive Guide to symfony


公式サイトのドキュメントからも辿れる、symfony 公式ガイドブックの日本語訳。
 
http://symfony.xrea.jp/

symfony で XCache の管理ページ認証が出る問題


XCache が有効な環境で symfony を使うと、時々(初回実行時やキャッシュクリア後等に)
XCache Administration というメッセージで HTTP 認証が出ます。
パスワードが違っていると勿論

XCache Auth Failed. User and Password is case sense

となります。
 
このままでは都合がとても悪いので原因と対策を調べてみたところ
symfony framework forum に、この問題についてコメントがありました。
http://www.symfony-project.com/forum/index.php/m/26145/

i tried XCache, APC and eAccelerator. What i discovered is, when the first hit occure (after symfony cc) there is a call for sfProcessCache::clear() in the checkConfig() method (line 201) of the sfConfigCache class. This happens even when using of ProcessCache is not enabled in the configuration.
 
All three of them require a user and password setting to use methods for clearing the cache. eAccelerator use ini settings, xCache require authentication. Thats bad, but not symfonys fault. The result is either a php ‘warning’ (eAccelerator) orthe authentication box popup (xCache) when you hit your app the first time.
 
I helped myself by rewriting the sfProcessCache::clear() and adding few lines. For eAccelerator i’m setting the proper ini settings right before the call of eA’s clearing method, and for xCache by setting $_SERVER['PHP_AUTH_USER'] and $_SERVER['PHP_AUTH_PW'] before calling xcache_clear_cache(). I read those settings out of the app config YAML, where i added them manually.

とのことで、
sfProcessCache::clear() で xcache_clear_cache() を呼ぶ際に xcache の管理権限が必要なことが原因のようです。
ここに書かれているように自分で

$_SERVER['PHP_AUTH_USER'] = ‘XCacheの管理ユーザ名’;
$_SERVER['PHP_AUTH_PW'] = ‘ XCache の管理パスワード’;

<pearディレクトリ>/symfony/cache/sfProcessCache.class.php の sfProcessCache::clear()

や、あるいは

<symfonyプロジェクトルート>/web/index.php

などに書き加える事で対処できます。
 
もう一つの解決方法として、XCache 1.2.1 RC1 からの新しい php.ini の設定で

xcache.admin.enable_auth = Off

とすれば XCache の管理認証なしで xcache のキャッシュクリアができるようになります。認証できなくして管理機能を使えなくするのではなく、認証なしで xcache の管理操作ができるようになる事に注意してください。
なお、セキュリティを考慮してなのか .htaccess で

php_flag xcache.admin.enable_auth off

としても無視されます。
 
- 前者はセキュリティ面で少しマシだが、管理面で手間
- 後者は XCache に関して内部のセキュリティを犠牲にするが、楽
 
なので、状況によって使い分けるのがよさそうです。

PHP5 MVC フレームワークの新スタンダード? symfony


http://www.symfony-project.com/
 
本日の「今更」その2。
 
CakePHPMojavi より symfony がいいかも。
 
と聞いていたので、とりあえずsymfony のインストールだけ。

$ pear channel-discover pear.symfony-project.com
$ pear install symfony/symfony

インストールの確認

$ symfony -V

と打てば

symfony version 1.0.3

のようにインストールしたバージョンが表示されます。
楽ちん。
 
なお、PHP ソースの configure 時に –enable-ctype をつけていないと
いざ使おうとした時に

PHP Fatal error: Call to undefined function ctype_alpha()

のようにエラーがでてしまいます。
(Windows の場合は ctype は標準で組み込まれているので問題ありません)
 
参考:
- symfony.jp symfony の日本語情報 WiKi
- CodeZine: symfonyで始めるPHPフレームワーク

Ruby on Rails はじめの一歩


今更ですが、最近ようやく Rails を触ってみました。
 
- 10分で作る Rails アプリ for Windows
- Ruby on Rails 公式 – [http://www.rubyonrails.org/]
 
10 分でできる Rails アプリは、本当に 10 分で Ruby on Rails の手軽さが分かるのでお勧めです。
10分で作る…が Windows + MySQL なので,とりあえず FreeBSD で DB を使わない Hello World を表示する場合のメモを残しておきます。
 
あまりまとまったものではないですが..
 

 
1.Ruby + RubyGems をインストール
 FreeBSD の場合、Ruby, RubyGems のいずれも ports からインストール可能です(RubyGems は lang/ruby-extensions に含まれる)。

# portinstall lang/ruby lang/ruby-extensions

 
2. RubyGems の gem コマンドで Ruby on Rails をインストール

$ gem install rails

上のコマンドで一発インストール。依存関係について聞かれるのが嫌なら

$ gem install -y rails

とすればプロンプトなしでインストールされるはずです。
 
3.$rails アプリケーションサーバの構築

$ rails foo

このコマンドひとつで、カレントディレクトリに以下のものをすべてふくむフォルダ foo/ を作成します。
- 管理用スクリプト(script/)
  たとえば script/server はスタンドアロンサーバであり、
  script/generate は目的に応じたクラスやフォルダの自動生成を行うスクリプトです。
- 公開ディレクトリ(public/)
  実際の URL マッピングは public/.htaccess および、public/dispatches.cgi で行われています。
  rails サーバのデフォルトのトップページは public/index.html です。
  
-コントローラ格納フォルダ(app/controllers)
  MVC の controller 格納先
  サンプルとして最初からコントローラの雛型(app/controllers/Application.rb)が含まれています。
  コントローラ作成時はコマンド(scriot/generate controller <コントローラ名>) で作成すると便利です。
 
-ビュー格納フォルダ(app/views)
  MVC の view 格納先。
  ここに .rhtml (eRuby) 形式のテンプレートファイルで view を記述します。
-モデル格納フォルダapp/models)
  MVC の model 格納先。
  script/generate model <モデルクラス名> 等で作成したモデルが格納されます。
 
- 設定ファイル(config/)、
コントローラと URL のマッピングを設定する config/routes.rb,
アプリケーション上のすべての Ruby スクリプトに影響する環境設定を行う config/environment.rb,
MySQL 等のデータベース接続用の設定(アカウント、接続先 DB 名等)を設定する config/database.yml 等があります。
 
- アプリケーションで利用する追加 ruby ライブラリ格納フォルダ(lib/)
  ここにいれておくと ruby スクリプトでのrequire でパス指定なしで参照できるようになります。
  例: lib/my_library.rb があれば、rails アプリケーションからの参照時は require ‘my_library’ とするだけでよい。
 
4. コントローラ作成

script/generate controller Foo

  デフォルトでは HTTP リクエスト URL の最初のディレクトリ表記がコントローラ、次が呼び出すメソッド(action)となっています。
  たとえば

http://localhost:3000/foo/edit

へのアクセスは、ファイル app/controllers/foo_controller.rb の

FooController#edit()

が実行されます。
また、

http://localhost:3000/foo

のように、アクションを省略した場合は、Foo#index メソッドが呼び出されます。
一般的な Web サーバにおける index.html が、コントローラでは index メソッドとなると考えれば分かりやすいと思います。
 
 
5. Hello world を出力する(view, model を使わない場合)
ActionController::Base#render() を使うのが基本です。
具体的にはコントローラのアクション定義メソッド(例: FooController#index)を以下のようにします。
app/controllers/foo_controller.rb

# 前略
def index
    render :text => “hello world!!”
end
# 後略

 
6.コントローラでテキストの出力を行う(view を使う場合)
まず以下のファイルを作成します。
app/views/foo/index.rhtml

<html>
 <head>
   <title>Hello Example</title>
 </head>
 <body>
 <%= @message %>
 </body>
</html>

次に、さきほどのfoo_controller.rb の def index を次のように書き換えれば自動的に index.rhtml を参照します。

def index
   @message = “Hello, world!”
   render
end

具体的には、参照される view のファイル名は

app/<コントローラ名>/<アクション名>.rhtml

です。

procmail を使う


procmail とはメール受信時の振り分け、フィルタリングなどを行うためのメール処理プログラムです。
 
Postfix で利用するためには、メール受信ユーザのホームディレクトリに
以下の内容をもつ .forward ファイルを作成します(両端のダブルクォーテーションも必要)。

“|IFS=’ ‘&&exec procmailのフルパス -f-||exit 75 #ログインユーザ名”

例:
/home/john

“|IFS=’ ‘ && exec /usr/local/bin/procmail -f-||exit 75 #john”

 
次に同様に .procmailrc ファイルを作成します。

MAILDIR=$HOME/Maildir
DEFAULT=$MAILDIR/
LOGFILE=$MAILDIR/procmail.log
LOCKFILE=$MAILDIR/.procmail.lock
# — 例1:未承諾広告を捨てる
:0 H
* ^Subject:.*iso-2022-jp
* ^Subject:.*\/.*
* ? echo “$MATCH” | nkf -me | egrep ‘※未承諾広告’
/dev/null
# — 例2:エイリアスによる script@example.org 宛のメールの内容(ヘッダ含む)を /usr/local/bin/dosomething.sh に渡して実行する
:0
* ^To:.*script@example.org

/usr/local/bin/dosomething.sh

前者はメールフィルタリングの例です。
後者はメールをトリガとして任意のプログラムを実行する例です。このようにすることで自動応答メール等様々な用途で利用できます。
 
~/.forward がない場合、main.cf の mailbox_command 変数で指定されたコマンド, mailbox_cmmand も指定されていない場合は通常のメール配送を行います。
procmail を実行した時に ~/.procmailrc がない場合も(procmail が)単純にメール配送を行います。
 
なお、仮想ドメインのメールボックスでは .forward ファイルおよび main.cf での mailbox_command は参照されないため、 procmail 等コマンド実行は適用されません。
このため、仮想ドメインのメールアドレスで procmail を扱うためには virtual_alias_maps でそのメールアドレスのみローカルのリアルユーザにエイリアスする必要があります。
 

例:
foo@example.org 宛のメールをリアルユーザ mailuser で受け取る場合…
main.cf

# …略…
# @localhost のみリアルユーザとする(仮想ドメインを含めないこと)
mydestination = localhost
# …略…
# 仮想メールアカウントのエイリアス
virtual_alias_maps = hash:/etc/postfix/viatual
# 仮想メールアカウントのメールボックス
virtual_mailbox_maps = hash:/etc/postfix/virtual_mailbox_maps

/etc/postfix/virtual

foo@example.com mailuser@localhost

/etc/postfix/virtual_mailbox_maps

# (エイリアスしたものは含めません)
# example.com
info@example.com example.com/info
postmaster@example.com example.com/postmaster
root@example.com example.com/postmaster
# example.net
info@example.net example.net/info
postmaster@example.net example.net/postmaster
root@example.net example.net/postmaster

以下のコマンドを実行

# cd /etc/postfix
# postmap hash:virtual_mailbox_maps
# postmap hash:virtual
# postfix reload

あとは前述のとおり mailuser のホームディレクトリ(例: /home/mailuser/ )に .forward, .procmailrc を作成すれば foo@example.com に対して procmail が利用できます。
 
参考:
Advanced Email Forwarding
Manpage of PROCMAILRC(JM Project による和訳)
Postfix 設定パラメータ
.procmailrc の書き方
Virtual環境での.forward が有効になりません(postfix-jp: 425)
Postfix 設定パラメータ

IE6.0SP1以上で利用できるシステム制限


- Internet Explorer 6.0 SP1 で使用できる制限値(Microsoft)
http://support.microsoft.com/kb/823057/ja
 
Spybot の IE Tweaks 機能について気になって調べていて見付けました。
レジストリで設定すると、IE の機能の一部(例: メニューの項目等)を制限することが可能です。
例えば Spybot では

HKEY_CURRENT_USER\Software\Policies\Microsoft\Internet Explorer\Restrictions

キーで、NoBrowserOptions = 1 (REG_DWORD)とすることで
ブラウザからインターネットオプションを開こうとした時に

このコンピュータの制限により、処理は取り消されました。システム管理者に問い合わせてください。

と出し実行できなくする、という機能を実現しています。
 
その他

NoSelectDownloadDir : [ファイルのダウンロード] ダイアログ ボックスの [保存] ボタンを無効にします。
NoViewSource : [表示] メニューの [ソース] を無効にします。ただし、ユーザーがソースを完全に表示できなくなるようにするには、NoBrowserContextMenu 値を追加する必要があります。
AlwaysPromptWhenDownload : [ファイルのダウンロード] ダイアログ ボックスの [この種類のファイルであれば常に警告する] チェック ボックスを淡色表示にし、常にオンに設定されるようにします。
NoTheaterMode : F11 キー (全画面表示モード) を無効にします。
NoBrowserContextMenu : Web ページを右クリックしたときに表示されるショートカット メニューを無効にします。
NoOpeninNewWnd : Ctrl + N キーおよび [開く] を無効にします。
NoBrowserSaveAs : [ファイル] メニューの [名前を付けて保存] を非表示にします。

などなど。
作品展示用のコンピュータなどで機能制限したい場合に有用かもしれません。
 
なお、セキュリティのため Policies 以下については、(HKEY_CURRENT_USER においても)管理者権限がないと追加、削除、変更ができないようになっています。