[CakePHP]LIKE文のワイルドカードをエスケープする

Written by uechoco 9月 16
[CakePHP]LIKE文のワイルドカードをエスケープする はコメントを受け付けていません。
この記事を読む時間:16くらい

CakePHPでは等号(=)以外のSQL演算子を特殊な方法で指定します。たとえば、比較演算子であれば以下のような感じ。

[phpcode]
$params[‘conditions’][‘User.created <'] = date('Y-m-d'); [/phpcode] 同様にLIKE文もこのように指定できます。 [phpcode] $params['conditions']['User.name LIKE'] = $this->data[‘User’][‘name’];
[/phpcode]

ここで困ったのがワイルドカードを使用する場合。検索文字列を%%でくくるなんていうことはよくあることですが、フォームに「%」を入れられてしまった場合、エスケープ処理をしないと全レコードが一致してしまい、検索結果が大変なことになります。

[phpcode]
// エスケープ処理をしていないワイルドカード検索
$params[‘conditions’][‘User.name LIKE’] = ‘%’.$this->data[‘User’][‘name’].’%’;
[/phpcode]

LIKE文に指定する文字列は独自のエスケープ関数をAppModelに作成して呼び出すことにしましょう。なお、下記ソースコードはUTF-8での使用を想定しているので、そのほかの文字コードで記述する場合はstr_replace()の代わりにmb_ereg_replace()を使用することを検討してください。

[phpcode]
class AppModel extends Model
{
/**
* SQLのLIKE分のワイルドカードをエスケープする
*
* @params string $str LIKE文に指定する検索文字列
* @params boolean $before 検索文字列の前に % を付与するか
* @params boolean $after 検索文字列の後に % を付与するか
* @return string ワイルドカードがエスケープされたLIKE文
*/
function escapeLikeSentence($str, $before = false, $after = false)
{
$result = str_replace(‘\\’, ‘\\\\’, $str); // \ -> \\
$result = str_replace(‘%’, ‘\\%’, $result); // % -> \%
$result = str_replace(‘_’, ‘\\_’, $result); // _ -> \_
return (($before) ? ‘%’ : ”).$result.(($after) ? ‘%’ : ”);
}
}
[/phpcode]

モデル内での使用方法
[phpcode]
// エスケープ処理をしたワイルドカード検索
$like = $this->escapeLikeSentence($this->data[‘User’][‘name’], true, true);
$params[‘conditions’][‘User.name LIKE’] = $like;
[/phpcode]

こういうエスケープ処理ってフレームワーク側でやってくれるものかと思ってたんですが、ワイルドカードで検索される可能性もあるから、勝手にエスケープはしないんですかね。

[ruby]Redmine 1.0.1をCentOS 5にインストール

Written by uechoco 9月 16
[ruby]Redmine 1.0.1をCentOS 5にインストール はコメントを受け付けていません。
この記事を読む時間:1756くらい

Wikiが欲しかったんですが、TracかRedmineみたいのがいいかなーと思って、Redmineのインストールに挑戦してみました。rubyは未開拓なのでいろいろ戸惑いました。

サーバ環境はServerman@VPSの256MBプランです。CentOS 5.4のi386です。root権限は使わずに、NOPASSWDのアカウントを仕様ています(基本的にsudoでインストール)。Apacheで、SQLite3での運用を考えています。redmineの本体は/var/work/redmineに設置しようかと思います。Apache httpdはyumか何かで既に入っている前提です。

Redmineは1.0.x系の最新の1.0.1を対象としています。Redmineのインストールガイド(Redmine – RedmineInstall – Redmine)を見ると、以下のような必要条件になっています。後述しますが、Rack 1.0.1というのはピンポイントでこのバージョンじゃないとデータベースのマイグレーションに失敗するようです。

  • Supported Ruby Version: ruby 1.8.6, 1.8.7
  • Required Rails version: Rails 2.3.5
  • Required Rack version: Rack 1.0.1

DL/解凍用の作業ディレクトリの作成

RPMやtar ballをダウンロードしたり、解凍するための場所として~/srcを使います。以下のインストール作業はこのディレクトリを使っていますので、適宜お好みのディレクトリに置き換えて読んでください。
[shcode]
# RPMやtar ballの置き場を作成
mkdir ~/src
[/shcode]

各種yumレポジトリのインストール

いくつかのレポジトリのためにyumのレポジトリをインストールします。私の好みで以下の3つをインストールします。使わないものもあるかもしれませんが。

  • Utter Ramblings
  • EPEL
  • RPMForge

[shcode]
# Utter RamblingsのGPGキーのインポート
sudo rpm –import http://www.jasonlitka.com/media/RPM-GPG-KEY-jlitka
# レポジトリ定義ファイルの作成
sudo vim /etc/yum.repos.d/utterramblings.repo
### [utter]
### name=Jason’s Utter Ramblings Repo
### baseurl=http://www.jasonlitka.com/media/EL$releasever/$basearch/
### enabled=0
### gpgcheck=1
### gpgkey=http://www.jasonlitka.com/media/RPM-GPG-KEY-jlitka

# EPELレポジトリ追加
sudo rpm -Uvh http://download.fedora.redhat.com/pub/epel/5/i386/epel-release-5-4.noarch.rpm
# レポジトリ定義ファイルでenableを0にしておく
sudo vim /etc/yum.repos.d/epel.repo
### enabled=0

# RPMForgeレポジトリ追加
cd ~/src
wget http://packages.sw.be/rpmforge-release/rpmforge-release-0.5.1-1.el5.rf.i386.rpm
sudo rpm -ivh rpmforge-release-0.5.1-1.el5.rf.i386.rpm
# レポジトリ定義ファイルでenableを0にしておく
sudo vim /etc/yum.repos.d/rpmforge.repo
### enable=0
[/shcode]

gcc、gcc-c++のインストール

Serverman@VPSにはgccが入っていませんでした。インストールします。
[shcode]
sudo yum -y install gcc gcc-c++
[/shcode]

checkinstallのインストール

checkinstallはtar ballからRPMパッケージを作ってくれるツールです。ruby界隈では割とよく使われているようです。その流儀に従って、後述のrubyやsqliteはcheckinstallでRPMパッケージにしてからインストールします。RPMにしておけば、アンインストールも楽ですよね。
[shcode]
# rpm-buildってのが必要かも
sudo yum -y install rpm-build
# RPMForgeからcheckinstallをインストール
sudo yum -y –enablerepo=rpmforge install checkinstall
[/shcode]

rubyのインストール

CentOS 5のyumでインストール出来るrubyは1.8.5までです。最新のRedmineは1.8.6や1.8.7あたりでしか動作しないらしいので、tar ballでとってきて、checkinstallでRPM化して、インストールします。
[shcode]
# tar ballのダウンロード、解凍
cd ~/src
wget ftp://ftp.ruby-lang.org/pub/ruby/1.8/ruby-1.8.7-p302.tar.gz
tar zxf ruby-1.8.7-p302.tar.gz
# コンパイル
cd ruby-1.8.7-p302
./configure –prefix=/usr
make
# RPM化
sudo checkinstall –fstrans=no –exclude=/selinux
# RPMでインストール
sudo rpm -ivh /usr/src/redhat/RPMS/i386/ruby-1.8.7-p302-1.i386.rpm

# ruby バージョンの確認
ruby –version
[/shcode]

RubyGemsのインストール

RubyGemsはrubyの拡張を簡単にインストール出来る仕組みです。phpでいうPEAR/PECL、pythonでいうeasy_installみたいなものだと思います。さきほど、rubyの1.8.7を導入したので、RubyGemsは最新の1.3.7が入るはずです。
[shcode]
cd ~/src
# 最新のRubyGemsをダウンロード
wget http://rubyforge.org/frs/download.php/70696/rubygems-1.3.7.tgz
tar zxf rubygems-1.3.7.tgz
cd rubygems-1.3.7
sudo ruby setup.rb

# gemのバージョンの確認
gem –version
[/shcode]

Ruby on Railsのインストール

いるかどうかわかりませんが、Ruby on Railsをインストールしておきます。いくつか警告のようなものが出てきますが、とりあえず無視しておきます。
[shcode]
sudo gem install rails
rails –version
[/shcode]

rack 1.0.1のインストール

どうやらRedmineでは、rack 1.0.1がないとデータベースのマイグレーションに失敗してしまうようです。ぴったりこのバージョンじゃないといけないようです。
[shcode]
sudo gem install rack -v=1.0.1
[/shcode]

SQLite3のインストール

CentOS 5にはsqliteが既に入っているかもしれませんが、ややバージョンが古いです。今回はSQLite 3.6.16以上が必要なので、最新版をダウンロードしてcheckinstallでRPM化してインストールします。
[shcode]
cd ~/src
# ダウンロード
wget http://www.sqlite.org/sqlite-amalgamation-3.7.2.tar.gz
tar zxf sqlite-amalgamation-3.7.2.tar.gz
cd sqlite-3.7.2
# コンパイルとRPM化、インストール
./configure –prefix=/usr
sudo checkinstall –fstrans=no –exclude=/selinux
sudo rpm -ivh /usr/src/redhat/RPMS/i386/sqlite-3.7.2-1.i386.rpm

# バージョンを確認
sqlite3 -version
[/shcode]

sqlite3-rubyのインストール

sqlite3-rubyをインストールします。
[shcode]
sudo gem install sqlite3-ruby
[/shcode]

redmineのインストール

ようやくRedmineのインストールに入ります。まずは本体をダウンロードし、運用ディレクトリに設置します。今回は/var/work/redmineに設置します。
[shcode]
cd ~/src
# 最新の1.0.x系をダウンロード、解凍
wget http://rubyforge.org/frs/download.php/72201/redmine-1.0.1.tar.gz
tar zxf redmine-1.0.1.tar.gz
# 運用ディレクトリに名前を変えて移動
sudo mv redmine-1.0.1 /var/work/redmine
# change directory
cd /var/work/redmine

# DBの設定
sudo vim config/database.yml
### production:
### adapter: sqlite3
### dbfile: db/redmine.db
### timeout: 5000

# DBのマイグレートを行う(エラーが起きた)
sudo rake db:migrate RAILS_ENV=production
### (in /var/work/redmine)
### rake aborted!
### A key is required to write a cookie containing the session data. Use config.action_controller.session = { :key => “_myapp_session”, :secret => “some secret phrase” } in config/environment.rb

# エラーに従って設定を追記
sudo vim config/environment.rb
### config.action_controller.session = { :key => “_myapp_session”, :secret => “SKv83bVAs39cjh” }

# DBのマイグレートを行う(再挑戦、またエラーが起きた)
sudo rake db:migrate RAILS_ENV=production
### (in /var/work/redmine)
### rake aborted!
### Secret should be something secure, like “77fb77e9ba061d6236016ca6cf9d3f87”. The value you provided, “SKv83bVAs39cjh”, is shorter than the minimum length of 30 charsudoacters

# エラーに従ってセッションキーを30文字以上の文字に変更
sudo vim config/environment.rb
### config.action_controller.session = { :key => “_myapp_session”, :secret => “kljdvh0hljsbav753wrbkCA87sdSb87qbvhjkVCABrqc98bAiu” }

# DBのマイグレートを行う(再挑戦、変なログがたくさん流れて終わった)
sudo rake db:migrate RAILS_ENV=production

# 初期データのロード
sudo rake redmine:load_default_data RAILS_ENV=production
### 「Select language」と出てきたら「ja」と入力
[/shcode]

Passenderのインストール

PassengerというApacheのモジュールを導入します。これによってrubyがapacheで効率的に動作するようになります。
[shcode]
# install Passenger Web サーバ
sudo gem install passenger

# インストールされた関連ファイルの確認
ls -la /usr/bin/passenger*
### -rwxr-xr-x 1 root root 391 Sep 7 23:14 /usr/bin/passenger-config
### -rwxr-xr-x 1 root root 407 Sep 7 23:14 /usr/bin/passenger-install-apache2-module
### -rwxr-xr-x 1 root root 405 Sep 7 23:14 /usr/bin/passenger-install-nginx-module
### -rwxr-xr-x 1 root root 401 Sep 7 23:14 /usr/bin/passenger-make-enterprisey
### -rwxr-xr-x 1 root root 397 Sep 7 23:14 /usr/bin/passenger-memory-stats
### -rwxr-xr-x 1 root root 397 Sep 7 23:14 /usr/bin/passenger-spawn-server
### -rwxr-xr-x 1 root root 391 Sep 7 23:14 /usr/bin/passenger-status
### -rwxr-xr-x 1 root root 396 Sep 7 23:14 /usr/bin/passenger-stress-test

# Apache用モジュールのビルドとインストール(サジェスチョンが表示される、バージョンが違うかもしれないので表示されたものを使用してください)
sudo passenger-install-apache2-module
### Please edit your Apache configuration file, and add these lines:
###
### LoadModule passenger_module /usr/lib/ruby/gems/1.8/gems/passenger-2.2.15/ext/apache2/mod_passenger.so
### PassengerRoot /usr/lib/ruby/gems/1.8/gems/passenger-2.2.15
### PassengerRuby /usr/bin/ruby
###
### Suppose you have a Rails application in /somewhere. Add a virtual host to your
### Apache configuration file and set its DocumentRoot to /somewhere/public:
###
###
### ServerName www.yourhost.com
### DocumentRoot /somewhere/public # <-- be sure to point to 'public'! ###
### AllowOverride all # <-- relax Apache security settings ### Options -MultiViews # <-- MultiViews must be turned off ###

###

# Apahceの各種設定
sudo vim /etc/httpd/conf.d/passenger.conf
### LoadModule passenger_module /usr/lib/ruby/gems/1.8/gems/passenger-2.2.15/ext/apache2/mod_passenger.so
### PassengerRoot /usr/lib/ruby/gems/1.8/gems/passenger-2.2.15
### PassengerRuby /usr/bin/ruby
sudo vim /etc/httpd/conf/httpd.conf
### NameVirtualHost *:80
sudo vim /etc/httpd/conf.d/vhost.conf
###
### ServerName redmine.example.com
### DocumentRoot /var/work/redmine/public
###
### AllowOverride all
### Options -MultiViews
###

### ErrorLog logs/redmine.example.com_error_log
### CustomLog logs/redmine.example.com_access_log combined
###

# Apacheの再起動
sudo apachectl -t
sudo apachectl graceful

[/shcode]

Internal Server Errorとの格闘

インストールに慣れていないせいか、Internal Server Errorと戦うことになりました。
[shcode]
# この時点で試しにredmine.example.comにアクセスすると、Internal Server Errorとなる。

# パーミッションの設定を忘れていた
sudo chown -R apache:apache ./*
sudo mkdir tmp public/plugin_assets
sudo chmod -R 777 files log tmp public/plugin_assets/
sudo chmod 666 db/redmine.db
sudo apachectl graceful

# この時点で試しにredmine.example.comにアクセスすると、Internal Server Errorとなる。

# Railsのバージョンを適切なバージョンを入れてみる
sudo gem install rails -v=2.3.5
sudo apachectl graceful

# この時点で試しにredmine.example.comにアクセスすると、Internal Server Errorとなる。

# Apacheのerror_logをみて1つずつ改善していくことにする。
# [1]: /var/work/redmine/vendor/rails/railties/lib/rails/gem_dependency.rb:119:Warning: Gem::Dependency#version_requirements is deprecated and will be removed on or after August 2010. Use #requirement
# 参考リンク:
# > http://pinzolog.blogspot.com/2010/07/versionrequirements-is-deprecated.html
# > http://d.hatena.ne.jp/tkrd/20100328/1269738099
sudo vim config/environment.rb
sudo apachectl graceful

# [2]: The {{key}} interpolation syntax in I18n messages is deprecated. Please use %{key} instead.
# 参考リンク:
# > http://shockby.com/2010/08/14/redmine%E3%81%A7i18%E9%96%A2%E9%80%A3%E3%81%A7%E3%82%A8%E3%83%A9%E3%83%BC%E3%81%8C%E5%87%BA%E3%81%9F/
# > http://www.redmine.org/issues/6314
sudo gem install i18n -v=0.3.7
sudo apachectl graceful

# この時点で試しにredmine.example.comにアクセスすると、最初のページはアクセス可能だが、マイページはInternal Server Errorとなる。
# 不要なバージョンを消してみる
sudo gem uninstall rails -v=3.0.0
sudo gem uninstall actionmailer -v=3.0.0
sudo gem uninstall railties -v=3.0.0
sudo gem uninstall actionpack -v=3.0.0
sudo gem uninstall activerecord -v=3.0.0
sudo gem uninstall activeresource -v=3.0.0
sudo gem uninstall activemodel -v=3.0.0
sudo gem uninstall i18n -v=0.4.1
sudo apachectl graceful

# 無事に表示される
[/shcode]

どうやら今のところ、正常に動いています。

教訓:バージョン指定があるものは、ピンポイントでそのバージョンを入れるべき。

[xampp][php]sendmailを使用する

Written by uechoco 9月 14
[xampp][php]sendmailを使用する はコメントを受け付けていません。
この記事を読む時間:53くらい

xamppのローカルのphpからメールを送るには、xamppの内部のsendmail.exeの設定をするだけで可能です。以下のサイトの通りにやればできました。

参考:Xampp sendmail の設定 | モデルさんのお金

なお、私はyahooのSMTPサーバを利用してsendmailを使うことにしましたが、Yahooメールの「POPアクセスとメール転送」を使用する設定でないと、認証に失敗します。sendmail.logに「smtpstatus=535 smtpmsg=’535 authorization failed (#5.7.0)’ errormsg=’authentication failed (method PLAIN)’ exitcode=EX_NOPERM」が残ると思います。

[php](断念)Unable to initialize module\nModule compiled with module API

Written by uechoco 9月 14
[php](断念)Unable to initialize module\nModule compiled with module API はコメントを受け付けていません。
この記事を読む時間:751くらい

Apacheのerror_logに以下のようなのがでます。

PHP Warning: PHP Startup: readline: Unable to initialize module\nModule compiled with module API=20050922, debug=0, thread-safety=0\nPHP compiled with module API=20060613, debug=0, thread-safety=0\nThese options need to match\n in Unknown on line 0

Utter Rambringsレポジトリを使ってyumでphp 5.2.13が入っている環境なのですが、yum list php*すると、以下のようになります。php-readlineだけ他と比べてバージョンが低いです。

[shcode]
# yum パッケージの削除
sudo yum remove php-readline
# 適当なディレクトリにphp 5.2.13のDL、解凍
cd ~/src
wget http://jp2.php.net/get/php-5.2.13.tar.gz/from/this/mirror
tar zxf php-5.2.13.tar.gz
# readline拡張をphpizeでインストール(撃沈)
cd php-5.2.13/ext/readline/
phpize
./configure
# configure: error: Please reinstall libedit – I cannot find readline.h
[/shcode]

configure: error: Please reinstall libedit – I cannot find readline.h

[shcode]
# libeditとlibedit-develをEPELレポジトリからインストール
sudo yum -y –enablerepo=epel install libedit libedit-devel

# 再度readline拡張をインストール(撃沈)
./configure
make
# make: *** [readline.lo] Error 1
[/shcode]

‘rl_mark’ undeclared (first use in this function)

コンパイルエラーの内容はこんな感じ。

  1. [admin@localhost]$ make
  2. /bin/sh /home/admin/src/php-5.2.13/ext/readline/libtool --mode=compile cc  -I. -I/home/admin/src/php-5.2.13/ext/readline -DPHP_ATOM_INC -I/home/admin/src/php-5.2.13/ext/readline/include -I/home/admin/src/php-5.2.13/ext/readline/main -I/home/admin/src/php-5.2.13/ext/readline -I/usr/include/php -I/usr/include/php/main -I/usr/include/php/TSRM -I/usr/include/php/Zend -I/usr/include/php/ext -I/usr/include/php/ext/date/lib  -DHAVE_CONFIG_H  -g -O2   -c /home/admin/src/php-5.2.13/ext/readline/readline.c -o readline.lo
  3.  cc -I. -I/home/admin/src/php-5.2.13/ext/readline -DPHP_ATOM_INC -I/home/admin/src/php-5.2.13/ext/readline/include -I/home/admin/src/php-5.2.13/ext/readline/main -I/home/admin/src/php-5.2.13/ext/readline -I/usr/include/php -I/usr/include/php/main -I/usr/include/php/TSRM -I/usr/include/php/Zend -I/usr/include/php/ext -I/usr/include/php/ext/date/lib -DHAVE_CONFIG_H -g -O2 -c /home/admin/src/php-5.2.13/ext/readline/readline.c  -fPIC -DPIC -o .libs/readline.o
  4. /home/admin/src/php-5.2.13/ext/readline/readline.c: In function 'zif_readline_info':
  5. /home/admin/src/php-5.2.13/ext/readline/readline.c:184: error: 'rl_mark' undeclared (first use in this function)
  6. /home/admin/src/php-5.2.13/ext/readline/readline.c:184: error: (Each undeclared identifier is reported only once
  7. /home/admin/src/php-5.2.13/ext/readline/readline.c:184: error: for each function it appears in.)
  8. /home/admin/src/php-5.2.13/ext/readline/readline.c:185: error: 'rl_done' undeclared (first use in this function)
  9. /home/admin/src/php-5.2.13/ext/readline/readline.c:186: error: 'rl_pending_input' undeclared (first use in this function)
  10. make: *** [readline.lo] Error 1

readline系の関数がないのかと推測して、readline-develパッケージをインストールして再挑戦してみます。
[shcode]
# readline-develをインストール
sudo yum -y install readline-devel

# 再再度readline拡張をインストール(撃沈)
./configure
make
# make: *** [readline.lo] Error 1
[/shcode]

関係有りませんでした。

久しぶりに私の能力では解決できそうもないので、そしてreadlineはUnix系でしか使えないので別にいいかなって思って諦めました。なんだったんだろう。。。

[DB]MyISAMからInnoDBへ変換

Written by uechoco 9月 10
[DB]MyISAMからInnoDBへ変換 はコメントを受け付けていません。
この記事を読む時間:17くらい

phpMyAdminにも同じ機能がありますが、実際はこんなSQLを発行することでMyISAMからInnoDBへ変換できます。

  1. ALTER TABLE  `users` ENGINE = InnoDB;