Pistolfly のすべての投稿

Software Engineer in Tokyo, Japan

プロジェクトのアップグレード(to 1.0 beta1)

http://www.symfony-project.com/trac/wiki/HowToUpgradeToLatestBeta
まず、以下のファイルの書き換えをする。

  • /SYMFONY => /symfony
  • /config/config.php
  • /apps/[appname]/config/config.php

...以上で、symfonyコマンドが使えるようになるので、プロジェクトディレクトリから、
symfony upgrade 1.0
を実行する。
あとは、modelのrebuildとclear-cache。
D:\sfprojects\askeet2>symfony upgrade 1.0
>> upgrade 1.0 upgrading propel.ini configuration file
# there are 2 new propel.ini options:
# - propel.builder.addIncludes
# - propel.builder.addComments
# sfConfig::get('sf_i18n_instance') is deprecated
# use sfContext::getInstance()->getI18N()
>> upgrade 1.0 upgrading require in models
# model require must be lib/model/...
# instead of model/...
>> upgrade 1.0 migrate activate to enabled
# activated_modules: is deprecated in settings.yml
# use enabled_modules:
# activate: is deprecated in cache.yml
# use enabled:
# active: is deprecated in logging.yml
# use enabled:
# sf_logging_active is deprecated in *.php
# use sf_logging_enabled
>> file- D:\sfprojects\askeet2/SYMFONY
>> file+ D:\sfprojects\askeet2/symfony
>> chmod 777 D:\sfprojects\askeet2\symfony
>> upgrade 1.0 upgrading schemas
# schema.xml must now have a database package
# default is package="lib.model"
>> upgrade 1.0 add test bootstrap files
>> dir+ D:\sfprojects\askeet2/test/bootstrap
>> file+ D:\sfprojects\askeet2/test/bootstrap/functional.php
>> file+ D:\sfprojects\askeet2/test/bootstrap/unit.php
>> upgrade 1.0 upgrading main config.php
>> upgrade 1.0 upgrading application "frontend"
>> upgrade 1.0 upgrading config.php
>> upgrade 1.0 upgrading filters.yml
# filters.yml now contains core symfony filters
>> upgrade 1.0 upgrading deprecated helpers
>> upgrade 1.0 upgrading date form helpers
>> upgrade 1.0 upgrading deprecated helpers in generator.yml
>> upgrade 1.0 upgrading cache configuration
# "type" has been removed in cache.yml
# read the doc about "with_layout"
>> upgrade 1.0 upgrading deprecated methods in actions
>> upgrade 1.0 upgrading view configuration
>> upgrade 1.0 upgrading sf/ path configuration
>> upgrade 1.0 done
>> dir+ D:\sfprojects\askeet2/plugins
# WARNING: you must re-install all your plugins
# Now, you must:
# - rebuild your model classes: symfony propel-build-model
# - clear the cache: symfony cc

filterからforward404するには?

filterからforward404したいと思って、

$this->getContext()->getController()->getAction($this->getContext()->getModuleName(), $this->getContext()->getActionName())->forward404Unless($office);

とやったところ、
sfError404Exception: in D:\php5\PEAR\symfony\action\sfAction.class.php on line 129
というエラー。
これは、例外をスローしているだけのようだ。
これは、filterは、forwardするたびに実行されてしまうからのようだ。
filterの実行条件が

 if ($this->isFirstCall())
{
 ...
}

の場合、fowardするたびに実行してしまう。
以下のように修正すると、意図したとおり、forwardされた。

if ($this->isFirstCall() && !($this->getContext()->getModuleName() == sfConfig::get('sf_error_404_module') && $this->getContext()->getActionName() == sfConfig::get('sf_error_404_action')))
{
 ...
}

schema.yml syntax

http://www.symfony-project.com/book/trunk/model
databse.yml
prod:
 propel:
   param:
     host:              mydataserver
     username:          myusername
     password:          xxxxxxxxxx
all:
 propel:
   class:                sfPropelDatabase
   param:
     phptype:            mysql
     host:              localhost
     database:          blog
     username:          root
     password:
     compat_assoc_lower: true
     # datasource:      propel
     # encoding:        utf8
     # persistent:      true
schema.yml basic
propel:
 blog_article:
   _attributes: { phpName: Article }
   id:
   title:      varchar(255)
   content:    longvarchar
   created_at:
 blog_comment:
   _attributes: { phpName: Comment }
   id:
   article_id:
   author:      varchar(255)
   content:    longvarchar
   created_at:
propel:
 blog_article:
   id:      { type: integer, required: true, primaryKey: true, autoincrement: true }
   name:    { type: varchar , size: 50, default: foobar, index: true }
   group_id: { type: integer, foreignTable: db_group, foreignReference: id, onDelete: cascade }
schema.yml syntax detail
The column parameters are:

  • type: Propel column type. See Propel list of types for more details. The compact syntax (varchar(50)) is also supported as a type value.
  • size: for VARCHAR type columns, the size of the string. Note that a column defined as varchar(50) in basic syntax is defined as { type: varchar , size: 50 } in extended syntax.
  • required: false by default, set it to true if you want the column to be required
  • default: default value
  • primaryKey: boolean, to be set to true for primary keys
  • autoincrement: boolean, to be set to true for columns of type integer that need to be auto-increment
  • sequence: sequence name for databases using sequences for auto-increment columns (e.g. PostgreSQL or Oracle)
  • index: boolean, to be set to true if you want a simple index or to unique if you want a unique index to be created on the column
  • foreignTable: to create a foreign key to another table.
  • foreignReference: the name of the related column if a foreign key is defined via foreignTable
  • onDelete: if set to cascade for a foreign key, records in this table are deleted when a related record in the foreign table is deleted.
  • isCulture: to be set to true for culture columns in localized content tables (see the internationalization chapter)

Type
boolean
integer
float
date >= 1970-01-01
bu_date
timestamp >= 1970-01-01
bu_timestamp
varchar(size) <= 256 characters
longvarchar <= 65kb
Schema conventions
Empty columns called id are considered to be primary keys.
Empty column ending with _id are considered to be foreign keys, and the related table is automatically determined according to the first part of the column name.
Empty columns called created_at are automatically set to the timestamp type.
For all these columns, you don't need to specify any type, since symfony will deduce their format from their name.
Foreign key
   _foreign_keys:
     my_foreign_key:
       foreign_table: db_user
       onDelete:      cascade
       references:
         - { local: user_id, foreign: id }
         - { local: post_id, foreign: id }
Index
propel:
 blog_article:
   id:
   title:            varchar(50)
   created_at:
   _indexes:
     my_index:      [title, user_id]
   _uniques:
     my_other_index: [created_at]
schema.xml
<?xml version="1.0" encoding="UTF-8"?>
 <database name="propel" defaultIdMethod="native" noxsd="true">
   <table name="blog_article" phpName="Article">
     <column name="id" type="integer" required="true" primaryKey="true" autoIncrement="true" />
     <column name="title" type="varchar" size="255" />
     <column name="content" type="longvarchar" />
     <column name="created_at" type="timestamp" />
   </table>
   <table name="blog_comment" phpName="Comment">
     <column name="id" type="integer" required="true" primaryKey="true" autoIncrement="true" />
     <column name="article_id" type="integer" />
     <foreign-key foreignTable="blog_article">
       <reference local="article_id" foreign="id"/>
     </foreign-key>
     <column name="author" type="varchar" size="255" />
     <column name="content" type="longvarchar" />
     <column name="created_at" type="timestamp" />
   </table>
 </database>

変数のパターンマッチ

http://www.atmarkit.co.jp/flinux/rensai/theory08/theory08a.html

* ${変数#パターン}
変数の内容について、最初の部分とパターンがマッチしたら、最も短く一致する部分を取り除いた残りの部分を返す。
* ${変数##パターン}
変数の内容について、最初の部分とパターンがマッチしたら、最も長く一致する部分を取り除いた残りの部分を返す。
* ${変数%パターン}
変数の内容について、最後の部分とパターンがマッチしたら、最も短く一致する部分を取り除いた残りの部分を返す。
* ${変数%%パターン}
変数の内容について、最後の部分とパターンがマッチしたら、最も長く一致する部分を取り除いた残りの部分を返す。
 変数testpathに/home/sekino/Linux/how.to.linuxという値を設定しておくと、
$ echo ${testpath##/*/}
how.to.linux
$ echo ${testpath#/*/}
sekino/Linux/how.to.linux
$ echo ${testpath%%.*}
/home/sekino/Linux/how
$ echo ${testpath%.*}
/home/sekino/Linux/how.to
といった結果になります。また、ファイル拡張子を置き換えるという観点からは、
#!/bin/sh
file=scan01.jpg
echo ${file}
echo ${file%jpg}
echo ${file%jpg}png
というスクリプトを実行すると分かりやすいと思います。

rsyncのexcludeリストの書き方

ディレクトリ名、ファイル名だけ書くと、ディレクトリツリー内のすべての一致する名前のディレクトリとファイルが、除外されてしまう。
たとえば、
cache
と書くと、
ディレクトリツリー内のすべてのcacheディレクトリが除外されてしまう。
ルート直下のcacheだけを除外したい場合は、
/cache
と書かなくてはいけない。
/stats
.svn
/web/uploads
/cache
/log
/web/.htaccess
上記のように書いた場合、すべての「.svn」が除外され、
他のディレクトリやファイルは、それだけが除外される。

symfonyをプロジェクトにインストールする(Windows編)

1. symfonyのパッケージ(.tgz)をダウンロードして展開する
2. 展開したディレクトリ構造は以下のようになる
package.xml
symfony/
  LICENSE
  data/
  lib/
3. 以下のファイルをプロジェクト内にコピーする
symfony/data/* -> myproject/data/symfony/
symfony/lib/* -> myproject/lib/symfony/
4. symfony.batをプロジェクトルートにコピー
myproject/data/symfony/bin/symfony.bat -> myproject/
myproject/data/symfony/bin/symfony.sh -> myproject/
5. コピーしたmyproject/symfony.batとsymfony.shを編集
"@DATA-DIR@"を"data"に変更して保存する。
6. webデータ(css、jsファイルなど)をコピーする
myproject/data/symfony/web/sf/* -> myproject/web/sf/
以上。
http://www.symfony-project.com/book/trunk/installation
http://www.symfony-project.com/askeet/22

3値論理とNULL

http://codezine.jp/a/article/aid/532.aspx

 しかし、NOTの場合は単純だからいいとして、ANDとORの組み合わせを全部覚えるのはなかなか大変です。そこで、3つの真理値の間に次のような優先順位があると考えてください。
* ANDの場合: false > unknown > true
* ORの場合 : true > unknown > false
 強い方が弱い方を呑み込みます。例えば、「true AND unknown」なら、unknownの方が強いので、結果もunknownになります。ところが、「true OR unknown」の場合、今度はtrueの方が強くなるので、結果はtrueになります。この順位を覚えておけば、3値論理演算も見通しがよくなります。特に、ANDの演算にunknownが含まれた場合、結果が絶対にtrueにならないという特徴をよく覚えておいてください。後でこれが重要なキーになります。

http://codezine.jp/a/article.aspx?aid=532&p=2

NOT INのサブクエリで使用されるテーブルの選択列にNULLが存在する場合、SQL全体の結果は常に空になります。これは恐ろしい現象です。
正しい結果を得るには、EXISTS述語を使って書きます。
EXISTS述語が絶対にunknownを返さないからです。EXISTSは、trueとfalseしか返しません。そのために、INとEXISTSは同値変換が可能なのに、NOT INとNOT EXISTSは同値ではないという紛らわしい状況が生じています。

http://codezine.jp/a/article.aspx?aid=532&p=2

...これは、入力が空テーブル(空集合)だった場合はNULLを返すという極値関数の仕様によります。...入力が空テーブルだった場合にNULLを返すのは、極値関数だけではありません。COUNT関数以外の集約関数もそうです。

unlink

[PHP-users 23600] Re: バージョンアップ後にunlinkでエラー

> オープンしたままのファイルに対して削除(unlink)するなんて
> ルール違反ですしOS、バージョン、タイミングによって
> 挙動が変化するのは当然です。
まさにおっしゃる通りで、基本的には OS によって挙動が変化するのは当り
前ですが、UNIX 系の OS では一時的に作成したテンポラリファイルを確実に
消す方法としては
open 直後に unlink して、そのまま使いつづける
というのは定番的な tips だったりします。
というのは、どれかのプロセスがそのファイルをオープンしていた場合、そ
のオープンしている最後のプロセスがファイルを close するまで、そのファ
イルは存在しつづけることが保証されるからです。確か POSIX でもそう決まっ
ていたはず。
どういうときに嬉しいかというと、先ほども書いたようにプログラム内で一
時ファイルを作るときです。プログラム内で一時ファイルを使用終了したら
unlink するという処理でも良いのですが、それではエラーで終了するときに
もいちいち unlink しなければなりませんし、予想外の異常終了の場合は一時
ファイルが残ったままになってしまいます。open 直後に unlink しておけば、
例えどんなケースであれ、プロセスが終了したら確実にファイルは消去されま
す。