ホーム ブログ ページ 50

Passengerのステータス確認ツールの紹介(その2)

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

前回に引き続き、Passengerに標準でインストールされるステータス確認ツールの紹介をしたいと思います。

passenger-memory-stats

 passengerのプロセスのメモリの使用状況が見れます。出力内容がpassenger 3.0より変わったようで、3.0より前、3.0以降で以下のようになります。

3.0より前

-------------- Apache processes --------------
PID    PPID   Threads  VMSize   Private  Name
----------------------------------------------
16483  1      1        9.7 MB   0.2 MB   /usr/local/apache2/bin/httpd
22344  16483  1        10.0 MB  0.6 MB   /usr/local/apache2/bin/httpd
22693  16483  1        10.1 MB  0.6 MB   /usr/local/apache2/bin/httpd
22695  16483  1        10.4 MB  0.8 MB   /usr/local/apache2/bin/httpd
22710  16483  1        10.0 MB  0.5 MB   /usr/local/apache2/bin/httpd
22711  16483  1        10.4 MB  0.8 MB   /usr/local/apache2/bin/httpd
22712  16483  1        10.0 MB  0.5 MB   /usr/local/apache2/bin/httpd
22726  16483  1        10.1 MB  0.6 MB   /usr/local/apache2/bin/httpd
22729  16483  1        10.1 MB  0.6 MB   /usr/local/apache2/bin/httpd
22746  16483  1        10.0 MB  0.4 MB   /usr/local/apache2/bin/httpd
22751  16483  1        10.0 MB  0.4 MB   /usr/local/apache2/bin/httpd
22768  16483  1        10.0 MB  0.5 MB   /usr/local/apache2/bin/httpd
22770  16483  1        9.8 MB   0.3 MB   /usr/local/apache2/bin/httpd
22771  16483  1        9.8 MB   0.2 MB   /usr/local/apache2/bin/httpd
22772  16483  1        9.8 MB   0.2 MB   /usr/local/apache2/bin/httpd
### Processes: 15
### Total private dirty RSS: 7.11 MB

--------- Passenger processes ---------
PID    Threads  VMSize   Private  Name
---------------------------------------
16505  13       7.6 MB   0.6 MB   /usr/lib/ruby/gems/1.8/gems/passenger-2.1.3/ext/apache2/ApplicationPoolServerExecutable 0 /usr/lib/ruby/gems/1.8/gems/passenger-2.1.3/bin/passenger-spawn-server  /usr/bin/ruby  /var/rails/tmp/passenger.16483/info/status.fifo
16506  1        7.4 MB   4.5 MB   Passenger spawn server
17566  1        48.1 MB  35.5 MB  Rails: /var/rails/huga
19798  1        53.7 MB  39.7 MB  Rails: /var/rails/hoge
19800  1        51.1 MB  37.3 MB  Rails: /var/rails/hoge
22320  1        37.9 MB  30.1 MB  Passenger ApplicationSpawner: /var/rails/huga
22325  1        51.0 MB  37.2 MB  Rails: /var/rails/hoge
22327  1        52.4 MB  38.5 MB  Rails: /var/rails/hoge
22329  1        37.6 MB  29.6 MB  Rails: /var/rails/hoge
### Processes: 9
### Total private dirty RSS: 252.97 MB

項目の説明

VMSize

仮想メモリ領域のサイズPrivate

ディスクとの同期が取れていない物理メモリの領域のサイズ(dirtyと表記されるもの) .

3.0以降

--------- Apache processes ----------
PID    PPID  VMSize   Resident  Name
-------------------------------------
644    1     15.6 MB  7.5 MB    /usr/apache2/2.2/bin/httpd
25364  644   15.0 MB  4.1 MB    /usr/apache2/2.2/bin/httpd
652    644   15.0 MB  4.1 MB    /usr/apache2/2.2/bin/httpd
653    644   15.0 MB  4.3 MB    /usr/apache2/2.2/bin/httpd
655    644   15.0 MB  4.3 MB    /usr/apache2/2.2/bin/httpd
656    644   15.0 MB  4.3 MB    /usr/apache2/2.2/bin/httpd
25282  644   15.0 MB  4.3 MB    /usr/apache2/2.2/bin/httpd
25706  644   15.0 MB  4.3 MB    /usr/apache2/2.2/bin/httpd
26280  644   14.9 MB  2.9 MB    /usr/apache2/2.2/bin/httpd
25284  644   15.0 MB  4.3 MB    /usr/apache2/2.2/bin/httpd
25283  644   15.0 MB  4.3 MB    /usr/apache2/2.2/bin/httpd
6255   644   15.0 MB  4.3 MB    /usr/apache2/2.2/bin/httpd


-------- Nginx processes ---------



---- Passenger processes ----
PID  VMSize   Resident  Name
-----------------------------
648  4.6 MB   3.0 MB    PassengerWatchdog
649  5.5 MB   4.0 MB    PassengerHelperAgent
651  10.6 MB  5.2 MB    PassengerLoggingAgent

 ApacheとNginxとWebサーバーのプログラムごとで表示されるようになりました。自分の検証環境はApacheで動作させているので、Nginxで動いているプロセスは表示されていません。

項目の説明

VMSize

仮想メモリ領域のサイズResident

物理メモリの領域のサイズ.

 また、3.0より前のバージョンだとapxs, httpdにパスが通ってないとエラーになり実行できません。

 その場合、

 $ APXS2=[apxsのパス] passenger-memory-stats

か、または、

 $ HTTPD=[httpdのパス] passenger-memory-stats

とすれば、実行できます。また、root権限で実行しないとPrivateの合計が取得できず表示が以下のようになります。

 ### Total private dirty RSS: 0.00 MB (?) 

 サイトの動きが怪しい時など、前回紹介したpassenger-statusと合わせて使ってもらえると、怪しいプロセスを見つけるのに便利かと思います。それでは。

アリペイの導入について-即時支払方法の実装

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

アリペイ支払いにも3種類があります。

(ネット上すでにrails開発用のプラグインがあるようです)

今日はそのうちに、一番簡単な即時支払いについてご紹介します。即時支払いというはエンドユーザが支払った金額はすぐ売り方のアリペイアカウントに入る支払いで、
要求/応答パタンです。

一.アリペイ支払い用のデータの用意
パラメータ説明
必須パラメータ:
1.service:api名称、”create_direct_pay_by_user”、固定の文字列
2.partner:パートナーID、アリペイ社が発行する売り方のID
3.return_url:エンドユーザがアリペイシステムで支払完了後、パートナーシステム(売り方)に戻る時のURL
4.out_trade_no:注文番号などのパートナーシステムにユニックの注文識別番号
5.subject:商品名称
6.total_fee:合計金額(priceと同時に渡せない)
7.payment_type:1で固定
8.seller_email:パートナーシステム(売り方)がアリペイに登録する時のメールアドレス(seller_idでもOK)
9.sign:パラメータをサインする後の値
10.sign_type:サインアルゴリズム

ここではパラメータのサインについて説明する必要があります。
1、パラメータ名の昇順(signとsign_type以外)でソートする。
パラメータ名が同じ場合、パラメータ値の昇順でソート。

2、アリペイ社が発行するパートナーの秘密キーを直接接続

3、指定のsign_typeで、サインする

例、
out_trade_no=20111111111111
partner=2088123456789000
payment_type=1
return_url=http://example.com/alipay/alipay_return.jsp
seller_email=taro@example.com
service=create_direct_pay_by_user
subject=AAA
total_fee=0.01
秘密キー:abc123

サイン前のパラメータは下記になります。
out_trade_no=20111111111111&partner=2088123456789000&payment_type=1&return_url=http://example.com/alipay/alipay_return.jsp&seller_email=taro@example.com&service=create_direct_pay_by_user&subject=AAA&total_fee=0.01abc123

※サイン用のパラメータ値はURLエンコードしないでください。


二、連携用URLを生成、エンコード、連携する

上記の1~10までパラメータを接続して、特殊記号が入っている場合、エンコードする必要があります。

一番基本的なものをご紹介しました。
上記の1~10以外、いろいろパラメータが渡せます。必要に応じてアリペイ社のドキュメントをご参照ください。

リンク画像をonmouseを使わずにcssで変化させるTips

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

リンクになっているバナーなどの画像を簡単にonmouseで変化させたい時のちょっとしたTipsです。


マウスオーバーで切り替えたいとき、
普通は画像を別途用意してjavascriptのonmouse処理を使って切り替えます。
でもやんごとない事情で画像を用意できない時もあります。
それでも変化させたい!
そんな時はcssで透明度を指定することで
あたかもonmouse属性を使っているかのようなフリをすることができます。

cssは簡単。
a:hover img {
    filter: alpha(opacity=75);
    opacity:0.75;
}

これだけ。
数字はゼロに近づくほど透明になります。
画像を半透過させることで変化をつけているので、
背景に柄があったり背景色と混ざってへんな色になったり、
そもそも画像の一部だけ変化させたいということには対応できませんが
画像が用意できないなど取り急ぎ必要なときにはちょっと使える小技です。

ctagsを使ってみました

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

ctagsとはソース内の変数やメソッドを解析し、インデックスを作成するツールです。

インデックスを作成しておくと、Vimなどで指定のキーを叩くことで、現在のカーソル位置

にある変数やメソッドの定義にジャンプすることができます。

 ctagsのインストール(MacOS Xの場合)

MacOS X 10.3 以降では標準でctagsがインストールされていますが、BSD由来のもので

一部オプションが使えなかったりするので、Exuberant Ctagsをmac portsでインストールします。

$ sudo port install ctags

インストールできたら以下のコマンドで対応している言語を見てみましょう。

$ ctags --list-languages
C
C++
C#
Cobol
DosBatch
Eiffel
Erlang
Flex
Fortran
HTML
Java
JavaScript
Lisp
Lua
Make
MatLab
OCaml
Pascal
Perl
PHP
Python
REXX
Ruby
Scheme
Sh
SLang
SML
SQL
Tcl
Tex
Vera
Verilog
VHDL
Vim
YACC

 タグの作成

今回はRubyのコードを解析してタグを作成してみます。

Railsのアプリケーションルートに移動します。

$ cd [RAILS_ROOT]

タグを作成します。

※コマンド実行の前に、ctagsのパスが/opt/local/bin/ctagsになっていることを確認してください

$ ctags -R

アプリケーションルートディレクトリ直下にtagsというファイルができたはずです。

試しに、tagsファイルを作成したアプリケーションで適当なファイルをVimなどで開き、

ctrl + ] を打ってみてください。

カーソル位置にあるメソッド定義にジャンプできます。

これでエディタでのコーディングが少し楽になります。

以上です。

GCALDaemonを使って、ical対応アプリケーションとGoogleカレンダーを同期する

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

弊社にて販売しているSNSパッケージはスケジューラとして社内で利用されていますが、icalデータとして出力するインターフェースも持ち合わせているので、折角だからGoogleカレンダーと同期をとって利用したいと思います。

GCALDaemonというソフトウェアを利用すれば、比較的簡単に同期が実現できます。

今回は Mac OS X 10.6 上で設定を施してみたいと思います。

 必要なもの

  • Java 1.5 以上のランタイム環境
  • Gmailのアカウント
  • iCal 互換のアプリケーション

 Mac OS X へのインストール

http://sourceforge.net/projects/gcaldaemon/files/linux/ からLinux用バイナリzipをダウンロードし、

mkdir -p ~/gnu/ などとしてインストール用ディレクトリを作成します。

そこで以下のオペレーションを実行します。

cd ~/gnu
unzip ~/Downloads/gcaldaemon-linux-1.0-beta16.zip
chgrp -R admin ~/gnu/GCALDaemon
chmod -R g+w ~/gnu/GCALDaemon
chmod 755 ~/gnu/GCALDaemon/bin/*.sh

設定をテストするため、以下のコマンドを実行します。

cd ~/gnu/GCALDaemon/bin
 ./password-encoder.sh
Your Google password: Googleアカウントのパスワードを入力します

Original password: 上で入力したパスワードが表示されます
Encoded  password: xxxxxxxxxx ここで出てきた文字列を後ほど利用します

Sample configuration options for GCALDaemon:

file.google.password=xxxxxxxxxx
ldap.google.password=xxxxxxxxxx

notifier.google.password=xxxxxxxxxx
sendmail.google.password=xxxxxxxxxx
mailterm.google.password=xxxxxxxxxx

この後で設定ファイルも編集します。~/gnu/GCALDaemon/conf/gcal-daemon.cfg を開いてください。

% diff -U0 gcal-daemon.cfg.default gcal-daemon.cfg
--- gcal-daemon.cfg.default     2011-05-23 20:36:16.000000000 +0900
+++ gcal-daemon.cfg     2011-05-23 20:42:32.000000000 +0900
@@ -62 +62 @@
-file.ical.path=/usr/local/sbin/GCALDaemon/google.ics
+file.ical.path=/Users/myname/gnu/GCALDaemon/ical.ics
@@ -65 +65 @@
-file.google.username=example@gmail.com
+file.google.username=myname@gmail.com
@@ -68 +68 @@
-file.google.password=328$$gbv1WZhRGbhN2Z
+file.google.password=047$hogehogehog
@@ -71 +71,2 @@
-file.private.ical.url=/calendar/ical/example%40gmail.com/private-495cf94a5c0f1bfg/basic.ics
+file.private.ical.url=/calendar/ical/myname%40gmail.com/private-f1ldld54d7f9888316e6dlflf9ldld8hoge/basic.ics
+

設定差分は上記の通りです。

また、file.private.ical.urlに関してはGoogleカレンダーの設定から「限定公開URL」のICALリンクをクリックしてでてきた文字列のhttps://www.google.com/以降の文字列をペーストしてください

ここまでで基本的な設定はできました。一度きちんと同期ができるか、以下のコマンドを実行してみてください。

% ~/gnu/GCALDaemon/bin/sync-now.sh

コマンドを実行した後、ical.icsファイルの内容がGoogleカレンダーに反映されていたら成功です。

icalファイルを出力するアプリケーションに対してwgetやcurlなどでファイルをgetするようcrontabにしかけておきます。

% crontab -l
0 * * * * (cd ~/gnu/GCALDaemon ; curl -O http://sns.kbmj.jp/users/myname/calendar/ical.ics ; /Users/myname/gnu/GCALDaemon/bin/sync-now.sh ) > /dev/null 2>&1

これで1時間おきに同期がおこなわれた事になります。

他にもいろんなパターンでカレンダー同期がGCALDaemonで出来ますので、是非試してみていただければと思います。

nodeJS 〜nodeJSとは?〜

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

rick No22です。
今回はnodeJSついてです。
nodeJSとは?nodeJSが生まれた経緯等話していきます。

nodeJSとは?

「JavaScriptを用いたNon-blocking I/O環境」です。

Non-blocking I/Oとは?

データの送受信を行う際に、完了せずに他の処理を開始する通信方式です。
例えるならば、
洗濯機を動かしつつ掃除して完了したら洗濯物を干すといったながら作業のようなものです。

nodeJSが生まれた経緯

「C10k問題対策用」としてnodeJSは誕生しました。
※ Cは「Client」10kは「1万台」を表しており「クライアント1万台問題」ともいわれています。

C10k問題とは?

クライアントの数が多すぎてサーバがパンクする問題です。
2009年当時、「apache」vs「nginx(エンジンエックス)」という構図がありました。
※apacheはスレッド方式、nginxはイベントループ

apacheのスレッド

スレッドはクライアントが増加するごとにスレッドが増加し、
スレッドが増加するごとにメモリの使用率が増加。

nginxのイベントループ

全ての実行要求を一つのキューに保存し、一つ一つ実行していく。

スレッドは使用するユーザが増えれば増えるほどメモリをくうため、イベントループのnginxが有利という形になりました。
しかし、イベントループにも弱点があります。

実行できる要求が一つのみになるということは、
その一つの処理が遅いと他の処理もその分遅れてしまうことになります。
この問題を解決しようと考えたのがそもそものnodeJSの始まりです。
ではどうやって解決したのか?
その答えは最初に述べた「Non-bloking I/O」が使用されます。
Non-bloking I/Oを使用することにより、
実行要求をそれぞれ平行して処理することを可能にしました。
イベントループを採用している言語は他にもあり、
Python:Twisted
Ruby:EventMachine
Perl:CokoのAnyEvent
などがあるが、
Non-blocking I/Oは強制されていない。
このNon-blocking I/Oを強制したものがnodeJSです。

ためしに触ってみたい方は、
はじめての共同作業 Canvas編がおすすめです。
これを使用するにあたって1点注意点が有ります。
nodeJSなど使用するものすべて最新で動かすことができますが、
落としたファイルをそのまま起動させようとすると
TypeError: Object #

rspec で、referer や user_agent 関連の機能もテストしよう

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

お恥ずかしながら、TDDを行わずにRailsで開発を行い続けてきたred です。最近、自分でも spec を書く用になりました。かなり捗ります。まだの方、お早めに。

自分にとって、spec を覚えるにあたっての最大の難関は、参考になる情報をなかなか見つけられなかった、ということでした。

結局、自分は、プロジェクトメンバの書いたものをコピペ改変することにより覚えました。

もし、独学の方、まわりにspec を書いている方のいない Rails/Ruby プログラマの方、まずはこのブログの記述もしくは下の私のコードを写経してみて、そこから、RSpec on Rails の使い方を調べるのが、導入によろしいかと思います。

=====

これ以下の内容は、下記環境にて動作確認をしています。

  • ruby 1.8.7
  • rails 2.1.0
  • rspec 1.3.0
  • rspec-rails 1.3.2

=====

直近のプロジェクトでは、ユーザエージェントやリファラを見て、それによって LPO を行うナビゲーションを実装していました。

つまりは、下記のような機能を実装しました。勿論、本物はもっと高機能です。

#{RAILS_ROOT}/app/controllers/test_controller.rb

class TestController < ApplicationController

  # リファラより、どの検索エンジンから流入したかを特定
  def referer
    referer = request.env['HTTP_REFERER']
    if referer.blank?
      @engine = "no referer"
    elsif referer.split("?")[0].include? "google"
      @engine = "google"
    elsif referer.split("?")[0].include? "yahoo"
      @engine = "yahoo"
    else
      @engine = "not determined"
    end
    render :text => @engine
  end
 

  # ユーザエージェントより、どのブラウザよりアクセスしているかを特定
  def ua
    ua = request.env['HTTP_USER_AGENT']
    if ua.include? "MSIE"
      @browser = "ie"
    elsif ua.include? "Firefox"
      @browser = "firefox"
    elsif ua.include? "Chrome"
      @browser = "chrome"
    elsif ua.include? "Opera"
      @browser = "opera"
    elsif ua.include? "safari"
      @browser = "safari"
    else
      @browser = "others"
    end
    render :text => @browser
  end

end

上記のようなアプリがうまく動いているか確認する際、通常のブラウザで見ることが不可能な場合は、Live HTTP Headers や User Agent Switcher のようなツールを使い、ユーザエージェントやリファラを詐称してチェックするのがセオリーかと思います。

spec で上記テストを自動化したい場合、下記のように記述すれば実行することができます。

#{RAILS_ROOT}/spec/controllers/test_controller_spec.rb

require 'spec_helper'

describe TestController do
  
  describe "referer" do
    it "google 検索からの流入かどうか判別するテスト" do
      request.env["HTTP_REFERER"] = "http://www.google.co.jp/search?q=test"
      get "referer"
      response.should be_success
      assigns[:engine].should == "google"
    end
    
    it "yahoo 検索からの流入かどうか判別するテスト" do
      request.env["HTTP_REFERER"] = "http://search.yahoo.co.jp/search?p=test"
      get "referer"
      response.should be_success
      assigns[:engine].should == "yahoo"
    end
  end
  
  describe "ua" do
    it "firefox を使っているかどうか判別するテスト" do
      request.env["HTTP_USER_AGENT"] = "Mozilla/5.0 (Windows; U; Windows NT 6.0; ja; rv:1.9.0.17) Gecko/2009122116 Firefox/3.0.17 GTB6 (.NET CLR 3.5.30729)"
      get "ua"
      response.should be_success
      assigns[:browser].should == "firefox"
    end
    
    it "IE を使っているかどうか判別するテスト" do
      request.env["HTTP_USER_AGENT"] = "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)"
      get "ua"
      response.should be_success
      assigns[:browser].should == "ie"
    end
  end
end

上記のように、get で controller/method にアクセスする前に、request.env の各項目の値を上書きすれば、該当のテストを作成することができます。

dev_machine:rails_root red$ spec spec/controllers/test_controller_spec.rb 
....

Finished in 0.065284 seconds

4 examples, 0 failures
dev_machine:rails_root red$ 

describe や it は配列の each の中での実行も出来るので、テストしたいユーザエージェントやリファラとその結果をDB化しておくことにより、いちいちツールを用いて切り替えることなく、一気にhttp_header 関連のテストが行えるようになりました。

参考:http://stackoverflow.com/questions/542856/how-do-i-set-http-referer-when-testing-in-rails

【FlashLite】機種依存の不具合や仕様について7つの事例。

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

FlashLiteにはFlashLite固有の機種依存による不具合や仕様が数多く存在します。

今回は実際に自分が実際に直面した中から7つの事例をピックアップしてご紹介します。

(1) SH機種でFlashの再生が停止する

【現象】

・SoftBankのSH機種の場合は、画面が真っ白で表示(画像取得失敗と同様の表示)され、閲覧不可となる。
・DocomoのSH機種の場合は、「画像に誤りがあり、正しく動作しません」というメッセージが表示され、閲覧不可となる。

【原因】

無限ループが発生しているため。大半の携帯端末はFlash内で無限ループが発生した際に無視するが、一部SH機種はそのまま実行後、実行回数制限によりFlashの再生を停止する。

【解決方法】

無限ループが発生する場合のほとんどはコーディングミスである可能性が高いため、細かくtraceしながらデバッグを行うしかありません。
※次項にて意図しない無限ループが発生する特殊な事例についてご紹介しています。

(2) 一部端末で無限ループが発生する

【現象】

一部端末で無限ループが発生する

【原因】

「for(i=0; i < NaN; i++){}」となった場合に無限ループが発生するため。

【解決方法】

for文のlimit指定が「NaN」になっていないかどうかtraceをしながらデバッグするしかありません。 例えば、「int(“”)」等で「NaN」になっている可能性もあります。

(3) System.capabilities.hasSharedObjectsの判定結果が誤っている

【現象】

Panasonic製/TOSHIBA製のSoftbank端末で「System.capabilities.hasSharedObjects」を実行すると、Shared Object が利用できないにもかかわらず「true」が返される。
この結果を受けて、SharedObject.addListener を実行している場合はそのまま処理が停止する恐れがあるため注意が必要です。

【解決方法】

System.capabilities.hasSharedObjects と同等の判定を他の方法で行うことはほぼ不可能。

【代替案】

System.capabilities.hasSharedObjects の結果が「true」の場合に、SharedObject.addListenerを実行している場合、
一定時間Listenerが走らない場合は強制的にremoveListenerを実行後、次処理へ移行させる等の対応が必要です。
※設定時間が短すぎると、正常にデータをロード中の端末において読み込み完了前に次処理に強制移行されてしまうので注意が必要です。

(4) _rotationを指定すると、_xscale, _yscaleの値が勝手に変わってしまう

【現象】

_rotationにFloat型の数値を指定すると 対象MCの_xscale, _yscaleが伸縮されてしまう(_rotation後に_xscale, _yscaleを再定義する必要有り)

【発生例】

アナログ時計の針を動かす処理等

【原因】

45°毎の _rotation 指定しか保証されていないため(?)

【解決方法】

_rotation後に_xscale, _yscaleを再設定することで処理は増えてしまいますが、見た目の崩れを防ぐことができます。

(5) auの一部端末にてPOSTができない

【現象】

auの一部端末でPOST通信ができない

【発生例】

・swfから大量の入力テキストをPOSTでサーバーに送りたい場合等
・HTML内のPOSTが指定された検索フォームから検索した結果としてswfのページを表示させたい場合等

【解決方法】

なし

【代替案】

swfの前後の通信はGET形式で統一します

(6) デバイスフォントが勝手に縁取りされる

【現象】

古いSHARP製Softbank端末において、デバイスフォントの色を白に設定すると端末側で勝手に白で縁取りされてしまう
※参考:”【web creators】今“ 知っておくべき”ケータイサイト制作事情/第五回”:http://www.mdn.co.jp/di/articles/2145/?page=2

【解決方法】

なし
白デバイスフォントは使用しない、不具合が生じる機種は非対応機種とする等の対策が必要です。

(7) Docomoの文字コード

【現象】

Docomo端末からswf経由でマルチバイト文字が含まれるパラメータを送信した場合、端末によって文字コードがShift_JISのものとUTF-8のものがある

【発生例】

(例)「あ」をGETパラメータに付与した場合

(1) F905i

 swf内にてescape処理無しswf内にてパラメータ全体をescape処理swf内にてパラメータの名前, 値を個別にescape処理
パラメータの文字コードShift_JISパラメータとして認識されないUTF-8

(2) SH01-B

 swf内にてescape処理無しswf内にてパラメータ全体をescape処理swf内にてパラメータの名前, 値を個別にescape処理
パラメータの文字コードUTF-8パラメータとして認識されないUTF-8

通常、携帯HTMLサイトを構築する際にDocomo端末の場合はShift_JISのパラメータを受け取る前提で実装されることが多くありますが、 FlashLiteの場合、Docomo端末で表示されたswfからパラメータが送られた場合に、上記のようにパラメータの文字コードにばらつきがでてきます。

【解決方法】

暫定的に判別ロジックを組んではいますが、あまりスマートな方法ではないので公開は控えておきます…。

アリペイの導入について

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

最近、アリペイを試験ECサイトへ導入しています。導入しながら、まとめて少しずつメモします。ご参考まで

PS:
エンドユーザ⇒例、ECサイトで注文者
パートナーシステム⇒例、ECサイト及び運用者

第一回

——————2011-03-11(金)晴れ—————————————-
1.概要
アリペイ外部向けAPIには2種類あり、
一つは外部からリクエストを受け取るAPIであり、受取APIと言い、
もうひとつはアリペイから外部に通知するAPIであり、通知APIと言う。

受取API、通知APIの例はこの後詳しく説明するのでここで省略

2.交互パタン
(1)要求/応答パタン
もっとも使われているパタンで、パートナーシステムからリクエストを送信して、アリペイシステムにて処理を行って、処理結果を同期にパートナーシステムに戻すこと。

画面上から見れば呼出と遷移に分かれて、
呼出:パートナーシステムがアリペイの関連APIを呼び出すこと
遷移:パートナーシステムからアリペイの支払い画面に遷移して、エンドユーザはアリペイ支払システムにて支払いを行うこと。

アリペイ支払処理完了後、またパートナーシステムに戻らせたい場合、パートナーシステムからアリペイAPIを呼び出す時、パラメータの一つとして、return_url(戻り先)を渡す必要があります。


・処理フローとしては、

・呼出先URL:
https://www.alipay.com/cooperate/gateway.do


(2)通知モード
エンドユーザがパートナーシステムからアリペイシステムに遷移して、アリペイシステムにて今回の操作を完了させる。(パートナーシステムに戻らない)
アリペイシステムはパートナーが関心しているイベント、ステータスなどをパートナーシステムに通知する。
アリペイシステムの処理結果を非同期に通知されたい場合、パートナーシステムからアリペイAPIを呼び出す時、パラメータの一つとして、notify_url(通知先)の指定が必要です。

例、エンドユーザがパートナーシステムにて注文して、アリペイシステムにて支払う。支払いステータスが変わる時、アリペイシステムから
最新の支払いステータスや関連情報をパートナーシステムに通知する。

・処理フローとしては

・1.アリペイシステムからパートナーシステム(通知URL:nofity_url)に通知する。
・2.通知到着後、パートナーシステムは通知ID(nofity_id)で通知の有効性をアリペイシステムに確認する。
・3.アリペイシステムは通知の有効性を判断して、判断の結果をパートナーシステムに戻す。(True/False)
・4.パートナーシステムは通知により処理を行い、処理結果をアリペイシステムに戻す。
・5.パートナーシステムから戻された処理結果によりアリペイシステムは処理を行う。

アリペイシステムはHTTP/HTTPSプロトコルのpostメソッドで、データをパートーナシステムに送信する。
通知URLはアリペイとの契約に静的に指定できる。通知URL(notify_url)が指定されたら、すべての通知を指定されたURLに通知する。
アリペイ通知失敗またはパートーナシステムから処理成功の応答がない場合、アリペイシステムは定期的(1分間、3分間、5分間、10分間…)にデータを再送するが、すべての通知がパートーナシステムに届けることを保証しない。
重複送信の可能性がある、かつ、必ず業務上に前後順位で通知するわけではないので、パートーナシステムには重複送信無視及びだたしくソートする処理が必要だ。通知を受け取って処理する前に本システムの処理ステータスなどで処理されたかどうか判断する。本システムの処理ステータスをチェックする時、データロックかタイムスタンプを見るのをお勧め。

2-2.通知検証
システムの安全性から考えると、パートーナシステムはアリペイの通知を受けると、通知の有効性を検証する必要がある。アリペイAPIが正しく利用されているのを保証するために、パートーナシステムが1分間以内(現状1分間、今後調整可能性もある)の通知のみ検証できる。
検証用URL:
HTTPSの場合
https://www.alipay.com/cooperate/gateway.do

検証リクエスト例
https://www.alipay.com/cooperate/gateway.do?service=notify_verify&partner=1234567890¬ify_id=abcdefghijklmnopqrst

HTTPの場合
http://notify.alipay.com/trade/notify_query.do
検証リクエスト例
http://notify.alipay.com/trade/notify_query.do?partner=1234567890¬ify_id=abcdefghijklmnopqrst

通知検証APIの出力パラメータ
出力内容    説明
Invalid        パラメータ無効
True        検証成功
False        検証失敗

——————————————————————————

まだまだありますが、今回はここまでです。☆.。*・゜゜‥*。.☆.。*・゜゜‥*。. ☆.。*・゜゜‥*

MacPorts で /opt/local/bin/perl が無くなってしまった時の対処方法

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

こんにちは、たろちゃんです。MacPortsで/opt/local/bin/perlが無くなってしまってImageMagickがインストールできないという現象が起きたので対処してみました。

MacPortsは便利ですが、たまに依存関係などで問題が起きるケースがあります。

本日MacPortsをアップデートしたところ、ImageMagickがインストールできないというエラーが発生しました。

行ったコマンドは以下の通りです。

$ sudo port selfupdate
$ sudo port upgrade outdated

たったこれだけでエラーになりました。ログを確認すると”/opt/local/bin/perl”が存在しないため、ImageMagickのインストールに失敗しているようです。

Perlの変更点を確認したところ、“Changeset 76485”にて以下の修正があったのが原因のようでした。

change perl5.* ports to do +mangle_names by default
change perl5 to link perl5.x pieces to their non-mangled names
change perl5 to default to perl5.12

この修正点でperl5.12がデフォルトになるのですが、perl5.12側のアップデートの歳にperl5を消してしまうように動いてしまうため、/opt/local/bin/perlが消えてしまったようです。

なので、以下のようにしてperl5を再インストールしました。

$ sudo port install perl5

あとは先ほど失敗したupgradeをやり直してあげます。

$ sudo port upgrade outdated

これで無事ImageMagickがインストールされました。

なお、perl5はデフォルトでperl5.12を使うようになりますが、これはperl5のvariantsで設定された値がデフォルトで5.12ということになります。

Wisp:~ btm$ port variants perl5
perl5 has the variants:
   perl5_10: use perl 5.10 instead of perl 5.8 or perl 5.12
     * conflicts with perl5_12 perl5_8
[+]perl5_12: use perl 5.12 instead of perl 5.8 or perl 5.10
     * conflicts with perl5_10 perl5_8
   perl5_8: use perl 5.8 instead of perl 5.10 or perl 5.12
     * conflicts with perl5_10 perl5_12

perl5.8やperl5.10を使いたい場合は、variantsに指定してperl5をインストールすれば良いでしょう。

jQuery animation 〜動きのあるWebサイト作り〜

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

rick No21です。
今回はjQueryでできる動きのあるサイトの作り方の一部をご紹介。

表示されている場所がおかしいかもしれませんが、表示されていますか?
ちなみにchromeでしか動作確認していません。
firefoxだとみれませんでしたw


では解説に入ります。

jQueryの読み込み

まずは、jQueryを読み込まないと始まりません。
< script type=”text/javascript” src=”http://search.kbmj.com/javascripts/jquery-1.4.2.min.js” >< /script >これによりjQueryを読み込みます。
自分で試すときは
http://jquery.com/
ここから落としてきてください。
本来は内に記述します。

表示場所

表示場所の指定
< div id=”box” title=”sample” > < /div>
< div id=”linkText” class=”lt” > < /div>

jQuery

< script language=”JavaScript” >< !–
URL = [1,2,3,4] //長いので省略
jQuery(function(){
  for (var i=1; i <= URL.length; i++) {
    jQuery(“#box”).append(‘< a href=”‘ + URL[(i – 1)] + ‘” >< div id=”box’+ i + ‘” class=”box” title=”sample’ + i + ‘” >< /div >’);
    move(“box” + i, i);
  };

  jQuery(“.box”).css({
    ”width”:”40px”,
    ”height”:”40px”,
    ”position”:”absolute”,
     “top”:”400px”,
    ”background-color”:”#FFCC66″,
    ”cursor”:”pointer”
  });

  jQuery(“.lt”).css({
    ”width”:”270px”,
    ”position”:”absolute”,
    ”font”:”bold 10pt monospace”,
    ”top”:”350px”,
    ”letter-spacing”:”2px”,
    ”margin”:”0px”,
    ”padding”:”5px”,
    ”border-top”:”dotted 2px #FFCC66″,
    ”border-bottom”:”dotted 2px #FFCC66″,
    ”display”:”none”
  });

  function move(id, count){
    jQuery(‘#’ + id).animate({“left”: (count * 100) + 200 + ‘px’});
  };

  jQuery(“.box”).hover(
   function(){
     jQuery(this).css({“background-color”:”#669933″});
     var tx = jQuery(this).attr(“title”)
     jQuery(“#linkText”).text(“->” + tx);
     jQuery(“#linkText”).show();
   },

   function(){
     jQuery(this).css({“background-color”:”#FFCC66″});
     jQuery(“#linkText”).text(“”);
     jQuery(“#linkText”).hide();
   }
  );
});
//– >< /script >

#boxに対しての動作

for (var i=1; i <= URL.length; i++) {
    jQuery(“#box”).append(‘< a href=”‘ + URL[(i – 1)] + ‘” >< div id=”box’+ i + ‘” class=”box” title=”sample’ + i + ‘” >< /div >’);
    move(“box” + i, i);
  };
内にURLの数だけ

タグを追加します。
  function move(id, count){
    jQuery(‘#’ + id).animate({“left”: (count * 100) + 200 + ‘px’});
  };
タグ追加後moveに引数でid名と現在地(何ループ目?)を引数に渡してmoveの処理を行います。
moveの処理は、その名の通りboxを動かします。
animateによって動きのある動作をcssで指定できます。
どのboxをで第1引数のidをどれだけ移動させるかに第2引数のcountを使用しています。

boxと#linkTextに対しての動作

  jQuery(“.box”).hover(
   function(){
     jQuery(this).css({“background-color”:”#669933″});
     var tx = jQuery(this).attr(“title”)
     jQuery(“#linkText”).text(“->” + tx);
     jQuery(“#linkText”).show();
   },
   
   function(){
     jQuery(this).css({“background-color”:”#FFCC66″});
     jQuery(“#linkText”).text(“”);
     jQuery(“#linkText”).hide();
   }
  );
hoverは、各boxにマウスが重なったとき、外れたときの動作です。
まずhoverの第1引数に記述されているのが、マウスが重なったときの処理です。
cssで背景を変更、タグのtitleを取り出して#linkTextに記述して表示しています。
第2引数は、マウスが外れたときの動作です。
cssで背景を元に戻して#linkTextの内容を空にして非表示にしています。

CSS
CSSの記述内容は割愛させていただきますが、本来は外部参照の方が綺麗ですね。

jQueryを使用するとこのような動きのあるサイトが簡単に作成可能です。<>

ブラウザ関連でひっかかった諸々のこと(主にjavascript)

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

「結局、お客様にとってサービスの品質って、画面がどれだけ洗練されているか、なんだよね」

企画や営業担当の方からよく聞く言葉です。全くもってその通り。

でもエンジニアとしては、データの保存と加工、セキュリティを最初に気にしてしまいがち。だから「こそ」、画面のしっかいりしているサービスは「いいサービス」と言えるのでしょう。

というわけで、自分が携わってきた画面(ブラウザ)系のびっくりしたことを紹介します。

まず前提として、自分は普段このようなスタイルでコーディングを行っています。

  • 基本的にサーバサイドのアプリを作ることがメイン(Rails 以前はPHP)
  • よく使うブラウザは FireFox。LiveHttpHeaders と FireBugs に惹かれてそのまま
  • 開発機は MacOS。テスト用に Linux。windowsテスト機は共有

cookie制限の罠

自分が初めて本格的なjavascriptを書いたのは今から4年前。新卒で入社して1ヶ月が経ったGW前でした。作ったアプリは、画面上のガジェットを「開閉」できるようにする、という今ではよく有るもの。mixi では、ガジェットの右上をクリックして調整します。

open_close

今ではmixiも上記のガジェットはリアルタイムで行いましたが、当時はクリックするたびにリクエストが飛んでいるのを見て、

  「じゃぁ自分は遷移せずに変更/保存できるようにしまーす」

ととんでもないことを宣言した新入社員時代。しかも javascript は素人同然。「○日までに実現の目処が経たなかったら、遷移で実装してくださいね」と繰り返すリーダーを尻目に設計/実装してみたものFireFoxでは動くが IE6で動かない。

んで、その原因は何故かというと、自分はその実装で各ガジェットの状態をcookie で保存していたのですが、1ガジェットにつき1つのcookieを発行していました。それが、制限にひっかかっていました。

http://www.studyinghttp.net/cookies#Restriction

で、これを共有したときに「これだからIEは。。。」と言いそうになったのですが、

実はこれ、IEの方が本来のcookieの仕様(rfc)に忠実で、FFの方が拡大解釈をしている模様。そのため、設計(仮実装)のときにうまくいっていたのが、そろそろ出来そうかな、となった時点で大幅変更を加えるはめになりました(各ガジェットの状態を構造化し、jsonにして1つのcookieに保存)。

FFの「ゆるさ」というのも、後々問題になるというお話。

IE6のselect tag問題

IE7が出来て(普及して)一番うれしかったのが、この問題が解消されたこと。

これは、各タブを重ねたときに、IE6(以前)の場合はselectタグが1番上にきてしまう、というもの。このページの一番下を参照して下さい

で、iframe を使うという対応策は既に知られているのですが、 とはいっても複数ブラウザで競合チェックしたりというのはやっぱりめんどくさいです。

IE での position : fixed が効かない問題

こちらも、比較的有名なIEの不具合?仕様?でしょうか。こちらができると固定したサイドバー等が簡単に実装できるのですが(javascript で実現したものはわざとらしくて)、これはどうしようもないです。

fixed.jsというライブラリがありますが、それでもテストの心配はあるわけで、 その分の調査やデバッグの期間というのは長く取る必要がある、と経験上感じています。

上記のセレクトタグと併せて、javascriptとCSSでリッチな画面を作ろうとした場合に大問題となる場所ですので、その点、調整にはかなりの時間を確保しておく必要がある所です。

 json.stringify と prototype の喧嘩

2つ続けてIE6という古いブラウザの話をしましたが、今後は最近のブラウザの話。

前回の記事、 何か変なjson が吐かれるために苦労していましたが、そちら、やっと原因がつかめました。

現在担当しているプロジェクトではjavascript のライブラリはjQuery を主に使っているのですが、以前からの資産もありprototypeで実装されているものもあります。そのprototype のライブラリが json.stringify を汚染していた模様。

http://d.hatena.ne.jp/Gimite/20091129/1259495440

よって、今回は、json化は他のライブラリを使わず、その部分だけprototypeを使うように実装しました。

    var json = Object.toJSON(obj);

 ブラウザというよりもprototype.jsの問題ですが、高機能というのもアレなものだということで。

ajax 通信における post(本番) と get(開発時) の使い分け with firebugs

 rfc には含まれていないのですが、IE系では get で指定できるURLの長さは2083文字という制限があります。たしかにそれくらいの長さになるドメインやディレクトリはとても考えづらく、それくらい長いパラメータをつけるならpostにしろよ、というのは極々当たり前の常識的な判断ですので、特に疑問や憤りを覚えず他のブラウザの場合でも素直に従うべきでしょう。

ですが、ajax で非同期にページに一部だけ更新する場合、その通信は「開発期間の間は」getで行った方が特なことがあります。

Firefox で ajax 通信を行った場合、「接続」タブを開いた状態ではそのページでリクエストされた全てのコンテンツのリクエスト状況が表示されます。勿論、ajax でリクエストされたページも表示されます。

ajax で呼び出す URL(上記だと「ajax_body」)は、大抵の場合、Ruby(on Rails)等のサーバサイドの言語で動的に生成されています。勿論、開発中でバグや未実装があることも多いでしょう。そのリクエストが失敗した(500系のステータスコードが返ってきた)場合、上記のようにpostだと追跡が難しいです。

そのため、開発期間中だけでも get で ajax通信をするようにします。

このようにすると、上記の「ajax_body」にリクエストパラメータが付属してつくため、そのパーツとなるページだけ、別途ブラウザで表示し、デバッグを進めることができます。

最近のajax は、jQuery.ajax 等を用いて実装されるケースが多いと思われます。getとpostの切り替えに大幅な仕様変更を伴いませんので、ちょっとした参考にして下さいませ。勿論、リリース時より前、例えば負荷検証やUIテストの前には、post に戻しておく必要があります。

<script type=”???”>の怪奇

最後に、ちょっと脱力してしまったお話しを。

<script type=” text/javascript” language=”javascript”>〜</script> で囲まれたjavascript は、firefox, safari, chrome では実行されますが、IE系, Opera では実行されません。

つまり、

type の中が不正、つまり「(半角スペース)text/javascript」等、想定されていないものが入った場合、ブラウザ毎に挙動が異なります!!

お気をつけ下さい。

Ruby on RailsでfacebookのOAuth認証を実装する

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

今回は、Ruby on RailsでfacebookのOAuth認証を実装する手順をご紹介したいと思います。

OAuth認証といえば何だか小難しい印象がありますが、RailsにおけるOAuth認証の実装は驚くほど簡単です。

今回は例として、facebookのOAuth認証を実装する手順を5つのステップに分けてご紹介します。

※以下の手順はfacebookアカウントを登録済みのものとします。

facebookの設定(facebookにアプリケーションを登録する)

STEP1:本人認証を行う

携帯電話のメールアドレス、または、クレジットカードにて本人認証を行います。

※以下、携帯電話のメールアドレスで認証を行う手順を記載します

(1) http://www.facebook.com/docs/guides/web#!/developers/createapp.php

(2) 「携帯認証」のリンクを押下(登録画面がポップアップで表示されます)

(3) 携帯電話のメールアドレスを入力する

(4) 携帯電話に届いた確認用コードを入力する

(5) 本人認証完了

※2011/03/02現在、完了メッセージと共に再び②の入力フォームが表示されますが、①のウィンドウに戻り、画面を更新すると次のステップへ進むことができます。

STEP2:アプリケーションを登録する

(1) アプリケーション名を入力し、利用規約に同意した上で「アプリケーションを作成」を押下します。

(2) 画像認証を行います。

(3) アプリケーションの情報を入力します。

(※WEB Site > Site URL に「http://localhost:3000/」を記載するだけでOKです)

(4) アプリケーション登録完了

※マイアプリ画面内に表示されている「アプリID」「アプリの秘訣(※facebook側の誤訳な気がしますが、以下これで通します)」がfacebookアプリケーション開発時に必要となります。

Railsアプリの作成

STEP3:必要なRails環境

<実行環境>

今回のサンプルは以下の環境で作成しました。必要なgemが入っていない場合はインストールしてください

ruby:1.8.7
rails:2.3.10(sudo gem install rails -v 2.3.10)
oauth:0.4.4(sudo gem install oauth -v 0.4.4)
facebook_oauth:0.2.2(sudo gem install facebook_oauth -v 0.2.2)

STEP4:Railsアプリの作成

(1) 新規Railsプロジェクトを作成します

rails facebook

(2) RAILS_ROOTに移動し、OAuth認証用のControllerを作成します

script/generate controller Users index callback

(3) 各ファイルを下記のとおりに編集します

app/controllers/users_controller.rb

class UsersController < ApplicationController

  CALLBACK_URL    = "http://localhost:3000/users/callback"
  CONSUMER_KEY    = "アプリID"
  CONSUMER_SECRET = "アプリの秘訣"

  def index
  end

  def oauth
    client = FacebookOAuth::Client.new(
      :application_id     => CONSUMER_KEY,
      :application_secret => CONSUMER_SECRET,
      :callback           => CALLBACK_URL
    )
    redirect_to client.authorize_url
  end

  def callback
    @client = FacebookOAuth::Client.new(
      :application_id     => CONSUMER_KEY,
      :application_secret => CONSUMER_SECRET,
      :callback           => CALLBACK_URL
    )
    @client.authorize(:code => params[:code])
  end
  
end

app/views/users/index.html.erb

<%= link_to 'OAuth認証', '/users/oauth' %>

app/views/users/callback.html.erb

<%= @client.me.info %>

STEP5:Railsアプリを動かす

(1) サーバーの起動

script/server

(2) ブラウザで「http://localhost:3000/users」にアクセス

(3) 「OAuth認証」リンクを押下

(4) 未認証の場合、facebookサイトにて認証画面が表示されるので、「許可」を押下します

(5) CALLBACK先(/users/callback)にリダイレクトされます

(6) 「/usrs/callback」ページにてユーザー情報が表示されれば認証成功です。

さいごに。

以上となりますが、いかがでしょうか。意外とハードルは高くないという印象を受けていただけたでしょうか。

ちなみに、TwitterのOAuth認証実装については当サイト内の記事『rubyでOAuthを使ってみる』が参考になります。

pg 0.9.0 の Windows版バイナリをMac OS XでCross compileする

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

こんにちは、たろちゃんです。先日同僚のWindows環境にpgが必要になったのですがWindows側でコンパイラがなかったのでMac OS Xで作成してみました。

今回はMacPortsの環境を使います。

まず、Windowsのソフトウェアをクロスコンパイルできるようにするためにmingw32の環境をMacPortsで取得します。

$ sudo port install i386-mingw32-gcc

次に必要なgemをインストールします。

$ sudo gem install rdoc
$ sudo gem install rake-compiler

次にクロスコンパイルされたrubyを構築します(調べた当時ではruby-1.8.6 p398がビルドされました)。

$ rake-compiler cross-ruby

次にpg-0.9.0のgemを取得して展開します。

$ gem fetch -v 0.9.0 pg
$ gem unpack pg-0.9.0.gem

最後にrake crossを使ってpgをビルドします。

$ cd pg-0.9.0
$ rake cross native gem POSTGRESQL_VERSION=8.4.6

あとはrake crossを実行したところのpkg以下にできる pg-0.9.0-x86-mingw32.gem をWindows環境で手動インストールします。

今回の注意点としては、クロスコンパイル環境として ruby 1.8.7 を利用したところクロスコンパイルができない状態があり、調べてみると細かいパッチレベルでできるできないがあったりするようです。現段階では1.8系でクロスコンパイルをするには1.8.6の方が安定しているのではないかという印象がありました。

【PHP】画像アップロードとリサイズの仕方(フォームの生成~リサイズ処理の方法)

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

【PHP】画像アップロードとリサイズの仕方(フォームの生成~リサイズ処理の方法)

 フォーム生成からアップロードされた画像を保存する。

プロジェクト内で画像のアップロードからリサイズ処理を見ることがあったので、

勉強がてら処理内容を追ってみました。

  • 1.フォームの生成
  • 2.アップロードされたファイル情報取得
  • 3.画像の保存方法

1. フォームの生成

 <form action="アクション先" method="post" enctype="multipart/form-data">
   <input type="file" name="upload_file" />
   <input type="submit" value="アップロード" />
</form>

※ formタグのmethodをpostに、enctype=”multipart/form-data”を指定する必要があります。

2. アップロードされたファイル情報取得

アップロードされたファイルの情報は $_FILES に格納されます。

$_FILES は $_POST や $_GET と同様、PHPが自動的に値をセットしてくれる連想配列です。

また、アップロードしたファイルは一時的にサーバー側に保存され、PHPプログラムの実行が終了すると削除されるそうです。

$upload_file = $_FILES["upload_file"];
array(5) {
  ["name"]=>
  string(10) "Desert.jpg"
  ["type"]=>
  string(10) "image/jpeg"
  ["tmp_name"]=>
  string(14) "/tmp/phph8PFva"
  ["error"]=>
  int(0)
  ["size"]=>
  int(845941)
}
  • name →アップロードファイル名
  • type →MIMEタイプ
  • tmp_name →アップロードされたファイルが一時的に保存されたファイルパス
  • error →エラーコード(正常にアップロードされた場合、0になります)
  • size →アップロードされたファイルサイズ

となっています。

3. 画像の保存方法

アップロードされた画像は一時的に、tmp_name値で指定された箇所に保存されています。

move_uploaded_file()を用いて、別ディレクトリに移動させます。

move_uploaded_file( $upload_file["tmp_name"], ‘/img/upload/');

とここまでの手順で、アップロードされた画像を保存することが可能です。

4. 画像をリサイズするサンプルコード

下記の1.~6.までの手順をサンプルに落としてみました。

1.画像情報を取得する

2.画像をコピー

3.空画像を作成

4.コピー画像を指定サイズで作成

5.コピー画像を保存

6.画像データ破棄

$orig_file 元画像

$resize_weight リサイズ幅

$resize_height リサイズ高さ

function sample_resize($orig_file, $resize_weight, $resize_height)
{
	// GDライブラリがインストールされているか
	if (!extension_loaded('gd')) {
	    // エラー処理
	    return false;	
	}

	// 画像情報取得
	$result = getimagesize($orig_file);
	list($orig_width, $orig_height, $image_type) = $result;
	
	// 画像をコピー
	switch ($image_type) {
	    // 1 IMAGETYPE_GIF
	    // 2 IMAGETYPE_JPEG
	    // 3 IMAGETYPE_PNG
            case 1: $im = imagecreatefromgif($orig_file); break;
            case 2: $im = imagecreatefromjpeg($orig_file);  break;
            case 3: $im = imagecreatefrompng($orig_file); break;
            default: //エラー処理 
          return false;
        }	

	// コピー先となる空の画像作成
	$new_image = imagecreatetruecolor($resize_width, $resize_height);
        if (!$new_file) {
            // エラー処理 
	    // 不要な画像リソースを保持するメモリを解放する
            imagedestroy($im);
            return false;
        }

 	// GIF、PNGの場合、透過処理の対応を行う
	if [1]$image_type == 1) OR ($image_type==3 {
            imagealphablending($new_image, false);
            imagesavealpha($new_image, true);
            $transparent = imagecolorallocatealpha($new_image, 255, 255, 255, 127);
            imagefilledrectangle($new_image, 0, 0, $resize_width, $resize_height, $transparent);
        }

	// コピー画像を指定サイズで作成
 	if (!imagecopyresampled($new_image, $im, 0, 0, 0, 0, $resize_width, $resize_height, $orig_width, $orig_height)) {
            // エラー処理
	  // 不要な画像リソースを保持するメモリを解放する
            imagedestroy($im);
            imagedestroy($new_image);
            return false;
        }

        // コピー画像を保存
	// $new_image : 画像データ
	// $new_fname : 保存先と画像名
        // クオリティ

        switch ($image_type) {
	    // 1 IMAGETYPE_GIF
	    // 2 IMAGETYPE_JPEG
	    // 3 IMAGETYPE_PNG
            case 1: $result = imagegif($new_image, $new_fname, $quality); break;
            case 2: $result = imagejpeg($new_image, $new_fname, $quality); break;
            case 3: $result = imagepng($new_image, $new_fname, $quality); break;
            default: //エラー処理 
          return false;
        }

        if (!$result) {
            // エラー処理 
	    // 不要な画像リソースを保持するメモリを解放する
            imagedestroy($im);
            imagedestroy($new_image);
            return false;
        }

	// 不要になった画像データ削除
	imagedestroy($im);
        imagedestroy($new_image);

}

下記記事を書くにあたって参考にしたサイトになります、

透過処理についての解説

http://www.phppro.jp/qa/1269

References

References
1 $image_type == 1) OR ($image_type==3

checkinstallをつかってrpm化して楽になる

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

なにかをソースから自力でインストールするときに、パッケージ管理しておいたほうが

管理が楽ですので、checkinstallで楽にrpm化して楽しましょう

どういうことをするかというと、

makeまでしてinstallの代わりにcheckinstallしてrpm化して入れる感じです

まずはcheckinstallのインストール、依存してるソフトを入れます。

# yum install gettext rpm-build

次にcheckinstall本体を入れます。

# cd /usr/local/src
# wget http://asic-linux.com.mx/~izto/checkinstall/files/source/checkinstall-1.6.2.tar.gz
# tar zxf checkinstall-1.6.2.tar.gz
# cd checkinstall-1.6.2
# make
# make install

次にcheckinstall自体をrpm化します

# checkinstall 
# rpm -i /usr/src/redhat/RPMS/x86_64/checkinstall-1.6.2-1.x86_64.rpm
# rpm -qi checkinstall => OK^^v

インストールされてます。

これにて準備完了です。試しにRubyをインストールしてみます。

# cd /usr/local/src
# wget ftp://ftp.ruby-lang.org/pub/ruby/1.8/ruby-1.8.7-p302.tar.gz
# tar -xzf ruby-1.8.7-p302.tar.gz
# cd ruby-1.8.7-p302
# ./configure
# make
# checkinstall -R --fstrans=no  --provides="ruby"
# rpm -ivh /usr/src/redhat/RPMS/x86_64/ruby-1.8.7-p302-1.x86_64.rpm
# rpm -qi ruby => OK^^v

入りました。

ruby-opensslも同じステップでインストールしてみます。

# cd /usr/local/src/ruby-1.8.7-p302/ext/openssl
# ruby extconf.rb
# make
# checkinstall --exclude=/selinux -R
# rpm -ivh  /usr/src/redhat/RPMS/x86_64/openssl-20101102-1.x86_64.rpm
# rpm -qi openssl => OK^^v

入りました。

パッケージ管理されてるとホっとします

Solaris 10メモ

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

普段Mac OS XやLinuxを使っているとついついわすれてしまうSolarisのコマンド。自分たちでつけてたメモを書いてみる事にしました。

 パッケージの中身を知るには

# pkgchk -vn CSWvim
/opt/csw/bin/ex
/opt/csw/bin/rview
/opt/csw/bin/rvim
/opt/csw/bin/view
/opt/csw/bin/vim
/opt/csw/bin/vimdiff
/opt/csw/bin/vimtutor
/opt/csw/bin/xxd
/opt/csw/share/doc/vim
/opt/csw/share/doc/vim/license

 ファイルがどのパッケージか知るには

# pkgchk -lp /opt/csw/bin/glocate
Pathname: /opt/csw/bin/glocate
Type: regular file
Expected mode: 0755
Expected owner: root
Expected group: bin
Expected file size (bytes): 216836
Expected sum(1) of contents: 14151
Expected last modification: Jun 08 11:44:20 2009
Referenced by the following packages:
        CSWfindutils   
Current status: installed

 patchがどこまであたっているのか知りたい

# patchadd -p | grep パッチ番号

 sudoがないよ?

pfexecを使いましょう。

 共有ライブラリのパスを設定する

参考 http://solaris.roguelife.org/usr/ccs/bin/ld.xhtml

crleコマンドを使う。

# crle -c /var/ld/ld.config -l /lib:/usr/lib:/usr/local/lib:/opt/csw/lib

設定情報を確認するには

# crle

Configuration file [version 4]: /var/ld/ld.config  
  Default Library Path (ELF):   /usr/lib:/usr/local/lib:/opt/csw/lib:/opt/sfw/lib
  Trusted Directories (ELF):    /lib/secure:/usr/lib/secure  (system default)

Command line:
  crle -c /var/ld/ld.config -l /usr/lib:/usr/local/lib:/opt/csw/lib:/opt/sfw/lib

設定を更新(追記)するには

# crle -c /var/ld/ld.config -u -l /opt/sfw/lib
# crle

Configuration file [version 4]: /var/ld/ld.config  
  Default Library Path (ELF):   /usr/lib:/usr/local/lib:/opt/csw/lib
  Trusted Directories (ELF):    /lib/secure:/usr/lib/secure  (system default)

Command line:
  crle -c /var/ld/ld.config -l /usr/lib:/usr/local/lib:/opt/csw/lib:/opt/sfw/lib

:joinと:includeの区別について

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

:joinと:includeの区別について、いままであまり分からかなったので、実行してみて、メモします。


:joinと:includeの区別について、いままであまり分からかなったので、実行してみて、メモします。

(1):includeは最初に関連モデルを全て取得し、その後、キャッシュからロードされる

products,product_detailsテーブルがhas_oneの関係です。
現在、A,Bデータベースの上記2テーブルのデータを比較して、差分分をAからBへコピーする機能です。

set_db(a)
a_prodcut = Product.find(10)

set_db(b)
b_prodcut = Product.find(10)


※set_db(x)はDB指向を指定するメソッドの仮名です。

a_prodcut.product_detailのcommentカラムの内容を取得したい場合、
a_prodcut.product_detail.commentですと
「select * from product_details where product_id = 10」sqlが発行されています。
この場合、DBがbに指向されているので、取得したのはa_prodcutのproduct_detailではなく、
b_prodcutが紐付いているproduct_detailです。
joinでやって、同じく、sqlが発行されています。

includeでやってみます。
set_db(a)
a_prodcut = Product.find(:first,:conditions => [“products.id = 10”], :include => [:item_content])

set_db(b)
b_prodcut = Product.find(:first,:conditions => [“products.id = 10”], :include => [:item_content])


a_prodcut.product_detail.commentしたら正しい内容が取得できます。
:includeは、最初に関連モデルを全て取得しているため、a_prodcut.product_detailがキャッシュからロードされます。

(2):includeと:selectは併用できない
:includeは、最初に関連モデルを全て取得しているため、:selectの指定が無効となります。
:joinの場合、:selectが使えます。

追記:

巨大なテーブルの場合、:includeはすべてキャッシュにロードするので、パフォーマンスが落ちるかもしれないとの話もあったようです。
>:includeは、最初に関連モデルを全て取得しているため
結局、↑この特性を理解したうえで、状況に合わせて使えってことですね

2011-10月

久しぶりに追加します。:joinsは、関連モデルを検索条件に追加する場合に使うべし。includeを使うと、:includeは、最初に関連モデルを全て取得しているため、キャッシュからロードされるということで期待の結果がヒットできない可能性が十分あります。

json の憂鬱

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

現在ではxmlよりもyml よりも使われているであろう構造化文書の形式json。自分がド新人だったときに、「json? なんて不吉な名前の変数なんだ」と思ったのも遠い昔のことです。

json を始めとする構造化文書の便利さは、適切なライブラリを使えば 言語内の変数(hash, array 等)⇔一般的なテキスト、の変換が 容易に行えることにあります。

データを RDB に保存するとき、変数の構造が変化したとしても、 カラムを増やしたり join を行ったりせず、その項目での検索を ある程度あきらめるのであれば、容易かつ高速に、多様な形式の データを保存できます

class Samples < ActiveRecord::Migration
  def self.up
    create_table :samples do |t|
    t.string “name”
    t.text “description”
    t.text “parms_json” #ここに、詳しいデータを json 化して保存する
  end
  def self.down
    drop_table :samples
  end

で、ここの「params_json」の値ですが、上の値に関しては、 サーバサイド(Ruby on Rails)で生成した場合と クライアントサイド(Ajax)で生成した場合と、 同じ形式で保存されることが期待されるのですが、 こちら、ちょっと困った「クセ」がそれぞれありました。 そのクセの内容と、対策を共有します。

0) まずはスタート

下記のような変数を(ruby の記法)

hash = {
    :a => “b”, :c => [ [“あ”, “い”, “う”], [“え”, “お”, “か”] ]
}

を、

{ “a”:”b”, “c”:[ [“あ”,”い”,”う”], [“え”,”お”,”か”] ] }



という json にしたい。

1) Ruby on Rails の場合

何も考えずに hash.to_json した場合、

>> hash.to_json => “{\”a\”:\”b\”,\”c\”:[[\”\\u3042\”,\”\\u3044\”,\”\\u3046\”],[\”\\u3048\”,\”\\u304a\”,\”\\u304b\”]]}”

のように、 unicode_escape されて出力されます。 こちら、escape されて欲しくない場合、下記のような関数を作成し 出力を得ます。

    def json_unescape(str)
      str.gsub(/\\([\\\/]|u[0-9a-fA-F]{4})/) do
        ustr = $1
        if ustr.starts_with?(‘u’)
          [ustr[1..-1].to_i(16)].pack(“U”)
        elsif ustr == ‘\\’
          ‘\\\\’
        else
          ustr
        end
      end
    end

出力は

>> json_unescape(hash.to_json) => “{\”a\”:\”b\”,\”c\”:[[\”あ\”,\”い\”,\”う\”],[\”え\”,\”お\”,\”か\”]]}”

2) jquery-json の場合

jquery および jquery-json を読み込んだ環境下にて、

alert(jQuery.toJSON({a:”b”, c:[[“あ”, “い”, “う”], [“え”, “お”, “か”]]}));

を実行したら、

{“a”:”b”,”c”:”[[\”あ\”, \”い\”, \”う\”], [\”え\”, \”お\”, \”か\”]]”}

のように、配列が内部でエスケープされた状態で出力されます。 上記のエスケープを解除したい場合、下記のような処理になります。

function no_escape_to_json(obj) {
  return jQuery.toJSON(obj).replace(/\\\”/g, “\””).replace(/\”\[/g, “\[“).replace(/\]\”/g, “\]”);
}

1), 2) の処理とも、アドホックな対応のため、あまり推奨されないやり方になります。が、もしお困りの方がいればご参考いただきたいな、と。 また、もっと根本的なスマートなやり方がある場合、お教えいただけますと幸いです。

PHPのソースインストール

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

CentOSにPHP5.2系を入れる為に、utterramblingsリポジトリを使用してyumで楽にインストールしてましたが、ある時から不安定でインストール出来ないという状況が何度か続いた為、最近はソースインストールするようにしています。そのメモです。
私の要件はyumの場合と同じものを使えるようにする事。
ちなみに以前はこんな感じで色々入れてました。
# yum –enablerepo=utterramblings -y install php php-gd php-ldap php-mbstring php-pear php-mcrypt php-xml php-devel php-apc php-soap php-mysql
# pecl install fileinfo
※後は/etc/php.ini、/etc/php.d/apc.ini, fileinfo.iniの設定で完了。

●PHPのインストール

XAMPPに入っているPHP5.2系の最後が1.7.1のPHP5.2.9なので、個人的にはこのバージョンを使用しています。
# wget http://museum.php.net/php5/php-5.2.9.tar.gz
# tar zxvf php-5.2.9.tar.gz
# cd php-5.2.9
# ./configure –with-apxs2 –with-bz2 –enable-calendar –with-curl –enable-exif –enable-ftp –with-gd –with-gettext –with-gmp –with-ldap –enable-mbstring –with-mcrypt –with-mysql –with-mysqli –with-openssl –with-pdo-mysql –with-pspell –enable-shmop –enable-soap –enable-sockets –enable-sysvmsg –enable-wddx –enable-xml –with-xsl –with-zlib –with-config-file-path=/etc –with-config-file-scan-dir=/etc/php.d
後はひたすら、エラーメッセージを見て必要なものをインストール⇔configureを繰り返します。

configure: error: no acceptable cc found in $PATH
# yum -y install gcc
./configure: line 6699: apxs: command not found
# yum -y install httpd-devel
configure: error: xml2-config not found. Please check your libxml2 installation.
# yum -y install libxml2-devel
configure: error: Cannot find OpenSSL’s
# yum -y install openssl-devel
configure: error: Please reinstall the libcurl distribution –
easy.h should be in /include/curl/
# yum -y install curl-devel
configure: error: libpng.(a|so) not found.
# yum -y install gd-devel
configure: error: Unable to locate gmp.h
# yum -y install gmp-devel
configure: error: mcrypt.h not found. Please reinstall libmcrypt.
# yum -y install libmcrypt-devel
Note that the MySQL client library is not bundled anymore!
# yum -y install mysql-devel
configure: error: Cannot find pspell
# yum -y install pspell-devel
configure: error: xslt-config not found. Please reinstall the libxslt >= 1.1.0 distribution
# yum -y install libxslt-devel
Thank you for using PHP.これでconfigureが完了。

# make
# make install
# cp -a php.ini-recommended /etc/php.ini
# mkdir /etc/php.d

●apcのインストール

# pecl install apc
エラーメッセージを見て必要なものをインストール、もう一度実行。
Cannot find autoconf. Please check your autoconf installation and the $PHP_AUTOCONF
environment variable is set correctly and then rerun this script.
ERROR: `phpize’ failed
# yum -y install autoconf
# pecl install apc

●PHPの設定変更

# vi /etc/httpd/conf.d/php.conf

LoadModule php5_module modules/libphp5.so

LoadModule php5_module modules/libphp5-zts.so

AddHandler php5-script .php
AddType text/html .php

DirectoryIndex index.php

php_value date.timezone Asia/Tokyo
SetEnv TZ Asia/Tokyo

デフォルトではモジュールのパスが違うので変更しておく。
# vi /etc/php.ini
extension_dir = “./”↓変更
extension_dir = “/usr/lib/php/modules”
# mkdir /usr/lib/php
# ln -s /usr/local/lib/php/extensions/no-debug-non-zts-20060613 /usr/lib/php/modules
後はそれぞれのモジュールが読み込まれるように設定する。
# vi /etc/php.d/apc.ini
extension=apc.so
# vi fileinfo.ini
extension=fileinfo.so

●Apacheの再起動

# apachectl configtest
Syntax OK
# /etc/rc.d/init.d/httpd restart

cakephpで管理機能を実装する

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

今回は、cakephpで開発すると意外と悩む、管理ユーザによる管理機能を実装する際の認証ロジックに関するソリューションを紹介します。

こんにちは。エンジニアのサンドリバー砂川です。

2010年も早いもので後3日。弊社も本日29日で、今年の最終営業日となります。

はじめに

はじめに、この記事は以下のような仕様のサイトを作ることを想定しています。サイトの一般会員(users)と、管理ユーザ(admin_users)の独立した二種類のアカウントを使用する一般的な認証機能を持つ(マイページ等)マスタデータ等を管理する管理画面を持ち、管理ユーザでログインしなければ閲覧出来ないものとする

一般的な認証機能 AuthComponent

cakephpには標準の認証機能として、AuthComponentというコンポーネントが存在します。

AuthComponentで普通の認証処理を実装するとこんな感じになります。
app/app_controller.php


class AppController extends Controller {
  var $components = array('Auth');
  var $uses = array('User');
  var $helpers = array('html', 'Form');

  function beforeFilter() {
    parent::beforeFilter();
    $this->layout = 'base';
    $this->setAuth();
  }

  function setAuth() {
    # 実際には、AuthComponentの初期値はusersテーブルを使用するので設定は不要。
    $this->Auth->userModel = 'User'; # 認証に使用するアカウントテーブルとしてusersテーブルを使用
    $this->Auth->fields['username'] = 'username'; # IDとしてusernameカラムを使用
    $this->Auth->loginRedirect = '/mypage'; # ログイン成功時にリダイレクトするurl
  }
}

app_controllerでAuthComponentを設定すると、全てのcontroller処理の前に認証チェックが行われ、beforeFilterに$this->Auth->allow(‘アクション名’);と設定しない限り、ログインしていない場合は/users/loginにリダイレクトされるようになります。

AuthComponentでは、デフォルトではusersテーブルをアカウントテーブルとして使用しますが、適宜指定することも可能です。今回の実装では、一般機能ではusers、管理機能ではadmin_usersを使用するように切り替えることで実装します

管理画面実装

さて、管理画面の実装ですが、cakephpには管理機能を実装する手段としてroutingプレフィックス機能が用意されています。簡単に説明すると通常、cakephpのroutingロジックは以下。


controller = books, action = admin_add
↓
/books/admin_add

しかし、routingプレフィックスにadminを指定すると一部urlが変化します。


controller = books, action = admin_add
↓
/books/admin/add

正直この機能は使い辛く、特に一般ユーザと管理ユーザで独立した認証処理を行いたい今回のケースでは使い物になりません。なのでcontrollerごと分離する方式で実装します。

まず、controllerの共通処理を記述するapp_controller.phpを継承、一般サイト領域の共通処理を記述するbase_controller.phpと、管理機能領域の共通処理を記述するadmin_controller.phpを作成します。
app/app_controller.php


class AppController extends Controller {
  var $components = array('Auth');
  var $uses = array('User');
  var $helpers = array('html', 'Form');

  # 全体共通処理のみ記述
  function beforeFilter() {
    parent::beforeFilter();
    $this->layout = 'base';
  }
}

app/controller/base_controller.php


class BaseController extends AppController {
  var $extra_components = array();
  var $extra_uses = array();
  var $extra_helpers = array();

  function __construct() {
    parent::__construct();
    $this->merge_extra();
  }

  function beforeFilter() {
    parent::beforeFilter();
    $this->layout = 'base';
    $this->setAdminAuth();
  }

  # 一般領域用にusersテーブルをアカウントテーブルとして使用するよう設定
  function setAuth() {
    $this->Auth->userModel = 'User';
    $this->Auth->fields['username'] = 'username';
    $this->Auth->loginRedirect = '/mypage';
  }

  function merge_extra() {
    $this->components = array_merge($this->components, $this->extra_components);
    $this->uses = array_merge($this->uses, $this->extra_uses);
    $this->helpers = array_merge($this->helpers, $this->extra_helpers);
  }
}

app/controller/admin_controller.php


class AdminController extends AppController {
  var $extra_components = array();
  var $extra_uses = array();
  var $extra_helpers = array();

  function __construct() {
    parent::__construct();
    $this->merge_extra();
  }

  function beforeFilter() {
    parent::beforeFilter();
    $this->layout = 'admin_base';
    $this->setAdminAuth();
  }

  # 管理画面領域用に、admin_usersをアカウントテーブルに使用するよう設定
  function setAdminAuth() {
    $this->Auth->userModel = 'AdminUser';
    $this->Auth->fields['username'] = 'mail_address';
    $this->Auth->loginRedirect = '/admin_top';
  }

  function merge_extra() {
    $this->components = array_merge($this->components, $this->extra_components);
    $this->uses = array_merge($this->uses, $this->extra_uses);
    $this->helpers = array_merge($this->helpers, $this->extra_helpers);
  }
}

一般ユーザが使用するcontrollerはbase_controllerを、管理ユーザが使用するcontrollerはadmin_controllerをそれぞれ継承して使用します。

また、一般機能領域の共通処理はbase_controller、管理機能領域の共通処理はadmin_controller、全てのcontrollerの共通処理はapp_controllerに、それぞれ記述することにします。
例:一般controller


App::import('Controller', 'Base');
class MypageController extends BaseController {
  var $Name = 'Mypage';
  var $extra_uses = array('Book');
  var $extra_components  = array('RequestHandler');
  var $extra_helpers = array('bk');

  function index() {
  }
}

例:管理controller


App::import('Controller', 'Admin');
class BookController extends AdminController {
  var $Name = 'Books';
  var $extra_uses = array('Book');
  var $extra_components  = array('RequestHandler');
  var $extra_helpers = array('bk');

  function index() {
  }
}

こうすることで一般機能領域では一般ユーザ、管理機能領域では管理ユーザでの認証を適用することができます。

注意点

この方式の注意点として、通常$usesや$componentsのような各controllerで追加している設定は、代わりに$extra_usesのように追加しなければならない点が挙げられます。これはcakephp内部実装上の理由で以下のような問題が発生するためです。


App
$uses = array('A);
↓
Appを継承したAppFoo
$uses = array('B');
↓
最終的な$uses
$uses = array('A', 'B'); # $usesや$componentsはマージされて適用される

App
$uses = array('A);
↓
Appを継承したBase
$uses = array('B');
↓
Baseを継承したBaseBar
$uses = array('C');
↓
最終的な$uses
$uses = array('B', 'C); # Appで指定したAがマージされない。

この問題に対しては、$extra_usesで指定した配列を一旦マージした後、$usesに設定することで対処しています。


App
$uses = array('A);
↓
Appを継承したBase
$uses = array('B');
↓
Baseを継承したBaseBar
$extra_uses = array('C');
↓
Baseの$usesとBaseBarの$extra_usesをマージ
$uses = array('B', 'C');
↓
最終的な$uses
$uses = array('A', 'B', 'C);

以上です。全ての問題点を綺麗に解決出来ているわけではありませんが、管理機能を実装する際に参考になる点もあるかと思います。

最近人気な記事