2009年11月20日金曜日

PHPでグラデーション画像を作成する



PHP GDは、image関数を使って画像のサイズをリサイズする時によく利用します。


サンプルもググルとたくさんあるので使ってる方も多いかと思います。


いろいろな用途に使われているGDですが、意外とグラデーションをかけた画像を


GDで作成してるサンプルが無いことに気がつきまして書いてみました。





というのも、ものぐさな私はPhotoShopとかでいちいち画像を切り抜くのが非常に大嫌いなもので


ちょっとしたデザインの変更で背景のグラデーション部分を再度切り抜き直したりすることが


発生するとキーーーーっとなってしまいます。





そんなおりプロトタイプのときくらいは、動的に画像を生成してもいいでしょ!


っと、ものぐさな考えを実践すべくだらだらサンプルを探していたのですが


ちょうどいいのが見つからずあきらめて書くことにしました。


まぁ、単純にグラデーションを書ける方向にimageLine で色を変えた線を引く!


ということをやっただけです。かなりあっさりした感じでかけます。


つまり、ことさらサンプルあげるほどでもないというのが実状だったのかも。。。




$sc = 'ffffff'; // 開始色
$ec = '6699aa'; // 終了色

$w = 150; // 画像幅
$h = 50; // 画像高さ

$im = imagecreatetruecolor($w, $h);
$bgc = imagecolorallocate($im, 255, 255, 255);

$al = gradDiv($sc, $ec, $h);
$sc = str2hec($sc);

for($i=0; $i<$h; $i++){
$bgc = imagecolorallocate($im
, $sc['R'] + $al['R'] * $i
, $sc['G'] + $al['G'] * $i
, $sc['B'] + $al['B'] * $i );
imageLine($im, 0, $i, $w, $i, $bgc);
}

header('Content-Type: image/png');
imagepng($im);
imagedestroy($im);

exit;

function gradDiv($sc, $ec, $l){

$S = str2hec($sc);
$E = str2hec($ec);

return array( 'R'=>($E['R'] - $S['R']) / $l
, 'G'=>($E['G'] - $S['G']) / $l
, 'B'=>($E['B'] - $S['B']) / $l);
}

function str2hec($col){
$R = hexdec(substr($col, 0, 2));
$G = hexdec(substr($col, 2, 2));
$B = hexdec(substr($col, 4, 2));

return array('R'=>$R, 'G'=>$G, 'B'=>$B);
}


上記のPHPで以下のようなグラデーションのかかった画像が表示できます。


f:id:bushimichi:20091120013603p:image


ちょっとした変更にもすぐ対応できるので


プロトタイプ用のサイトを作るときなどに重宝します。





2009年11月19日木曜日

OpenIDでmixi id を利用する時には証明書が2つ必要



サンプルにしたがって、mixi OpenIDのサンプルコードを動かしてみた時の備忘録


インストール方法などは以下の参考サイトを参照


参考:http://d.hatena.ne.jp/botchy/20080820/1219255653


mixi 証明書の取得は、以下の2つ必要


https://mixi.jp


https://id.mixi.jp


取得方法は、参考サイトを見てください。


この2つの証明書がmixi OpenIDの曲者です。


これを1つの証明書 both.crtにする必要があります。


どちらかの証明書にもう片方を追記します。(テキストエディッタで編集)


最初はわからなくて別々にcurl_setopt してましたが全くダメでした。








あとは上記の証明書を読み込むようにOpenID Libraryのソースに書き加えます。


Auth/Yadis/ParanoidHTTPFetcher.php 132行目と196行目付近



if ($this->isHTTPS($url)) {
curl_setopt($c, CURLOPT_CAINFO, '/path/to/both.crt');
}


忘れるとまたはまりそうなのでそのための備忘録です。





2009年11月1日日曜日

PHPで、先月、翌月などを扱うときの注意



※ かなり初歩的な話ですのでご了承ください





PHPで、先月、翌月の月を取得するような場合、以下のようなプログラムを書いてしまいませんか?




echo '先月 => '. date('m', strtotime('-1 month')) .'<br>';
echo '今月 => '. date('m') .'<br>';
echo '翌月 => '. date('m', strtotime('+1 month')) .'<br>';


------ 結果 ------

前月 => 10
今月 => 11
翌月 => 12


(今日を11月01日とした場合です)



上記の結果は期待した結果で現状11月01日の場合は問題ありません。





ところが、10月31日の場合を例にとって見ます。




echo '前月 => '. date('m', strtotime('2009-10-31 -1 month')) .'<br>';
echo '今月 => '. date('m', strtotime('2009-10-31') ) .'<br>';
echo '翌月 => '. date('m', strtotime('2009-10-31 +1 month')) .'<br>';


------ 結果 ------
先月 => 10
今月 => 10
翌月 => 12



大変なことに、先月が10になってしまいました。


もっと、過去にもどって見てみると







for($i=1;$i<=12;$i++){
echo $i. 'ヶ月前 => '. date('m', strtotime('2009-10-31 -'.$i.' month')) .'<br>';
}

------ 結果 ------
1ヶ月前 => 10
2ヶ月前 => 08
3ヶ月前 => 07
4ヶ月前 => 07
5ヶ月前 => 05
6ヶ月前 => 05
7ヶ月前 => 03
8ヶ月前 => 03
9ヶ月前 => 01
10ヶ月前 => 12
11ヶ月前 => 12
12ヶ月前 => 10



もう、ありえないことになってしまいますね。


よく見ると31日のある日とない日で計算が狂ってしまうという内容です。


2月にいたっては、29~31日もアウトですね。





これはおそらく10月31日の1ヶ月前は9月31日となり


9月31日とは9月30日の次の日だから10月1日のことになるってことでしょう。


そのため、10月31日の1ヶ月前の月は10月って事になります。





strtotime の -1 month とは、日付はそのままで月だけ1減らすという意味で


決して先月にシフトするという意味ではない。


関数を作った側の理屈はなんとなくあっている気がするのですが


使ってる側にしてみると間違いやすいポイントかなと思います。





従いまして、先月、翌月とかを正確に取得するには現在の日を考慮いれて


今月の1日から起算して1ヶ月前とかになるようにします。




echo '先月 => '. date('m', strtotime(date('Y-m-1').' -1 month')) .'<br>';
echo '今月 => '. date('m') .'<br>';
echo '翌月 => '. date('m', strtotime(date('Y-m-1').' +1 month')) .'<br>';

------ 結果 ------

前月 => 10
今月 => 11
翌月 => 12







for($i=1;$i<=12;$i++){
echo $i. 'ヶ月前 => '. date('m', strtotime(date('Y-m-1').' -'.$i.' month')) .'<br>';
}

------ 結果 ------

1ヶ月前 => 10
2ヶ月前 => 09
3ヶ月前 => 08
4ヶ月前 => 07
5ヶ月前 => 06
6ヶ月前 => 05
7ヶ月前 => 04
8ヶ月前 => 03
9ヶ月前 => 02
10ヶ月前 => 01
11ヶ月前 => 12
12ヶ月前 => 11






ぶっちゃけ、昨日上記のバグを発見したからこのエントリーなんですけどね(汗)


かなり初歩的なバグが混入していて情けない思いをしました。未熟者です。


こんなのは常識だよーって言われそうですが、知らない人がいましたら後学のために参考になれば幸いです。





hamachi 0.9.9.9-20 linux が突然つながらなくなったら。



最近、Windows用のhamachi がアップデートされて hamachi2 になったのですが


いままで通信できていたLinux用のhamachi(Linux 0.9.9.9-20)とつながらなくなってしまった。


Windows用のhamachiは結構な頻度でアップデートされていたが


Linux用はずっとアップデートされてなかったのでとうとう互換性がなくなって


見捨てられたんだ、とちょっとあせった。





よくよく調べてみると結構同様のことで皆さん困っているようで


コミュニティーサイトには、hamachi2との接続の際に


デフォルトのKeepAliveの設定が短く変更されたことが原因ではないか?って事らしい。


http://community.logmein.com/logmein/board/message?board.id=HamLinOSX&thread.id=79&view=by_date_ascending&page=2





そこで、KeepAlive設定を変更するには config ファイルに書け


みたいなことが掲載されていたので試してみた。





まず、linux側の各ユーザの .hamachiフォルダ(hamachiの設定が保存されている)


に、新規作成でconfigファイルを作成




touch ~/.hamachi/config






config ファイルの中に以下のKeepAliveの設定を書く




vi ~/.hamachi/config

KeepAlive 10






hamachi の再スタート




hamachi stop && hamachi start



一応上記の作業で無事に接続できました。


config ファイルを自分で新規作成するのがポイント!


初めはどこにあるのかわからず、探し回って苦労しました。








hamachiは、普段から結構利用していたので急に使えなくなると


慌てるもんですね。かなり依存度が高いことが自分なりに分かりました。


また、1つのツールに頼るのも良くないなぁと痛感。





2009年10月22日木曜日

一括してファイルの文字コードを検出する方法



Windows環境でファイルを操作し、Linux環境へファイルをアップロードする時に


意図せず、Shift_JIS ファイルをアップして文字化けしてしまったことありませんか?


実行時に簡単に分かる箇所ならテストすれば気がつきますが


アスキーコードだけで書かれた関数やクラスのファイルだったりすると、


エンコード問題が出ることは少ないので見落としがちです。


いちいちファイルを開いて確認するのは大変なので、一括して文字コードを確認する方法がないかと調べていたらありました。


以下のコマンドでOK。



find -name '*.php' | xargs nkf --guess


ファイル名と文字コードの一覧が表示されます。





ちなみに、一括して文字コードを変換することもできます。



# UTF-8 に変換
find -name '*.php' | xargs nkf --overwrite -w

# EUC-JP に変換
find -name '*.php' | xargs nkf --overwrite -e





【参考】 文字コード変換コマンドnkfの使い方まとめ





2009年9月8日火曜日

suPHPの設定でうまく動作しない時



【環境】


CentoOS5.3


Apache2.2.8


mod_suphp-0.7.0-1.el5.rf





最近、suPHPのセットアップをした時に、


過去に正しく設定した内容と同じ内容で設定したのに


InternetServerErrorがでて、エラーログに



SecurityException in Application.cpp:511: Unknown Interpreter: php


と出ていました。


問題になりそうな箇所が見当たらないので


Googleで調べていると、根拠はよく分からないのですが


/etc/suphp.conf の以下の部分を変更しろとのこと。。。



suphp.conf

[handlers]
;Handler for php-scripts
;x-httpd-php=php:/usr/bin/php-cgi
x-httpd-php="php:/usr/bin/php-cgi"

;Handler for CGI-scripts
;x-suphp-cgi=execute:!self
x-suphp-cgi="execute:!self"



ダブルクォーテーションで囲むとうまくかもね。とあったので


試してみたら、その通りちゃんと動きました。


過去には囲まなくても動作する環境もあったので


バージョン依存の問題かもしれません。





2009年9月4日金曜日

nanapiにレシピを書いてみた



ちょっと登録してみた勢いで書いてしまいました。





右回り、左回りが簡単に分かる方法


http://r.nanapi.jp/191/





たくさんのパスワードを覚えるレシピ


http://r.nanapi.jp/185/





意外とこういうサービスって無かったので、斬新で面白いです。


書いた人が、どういう評価されるか楽しいのがいいですし


活動に応じてレベルアップするのもいいですね。





また、ちょっと絵が描けたりして、レシピにボリュームを持たせられるところが


コンテンツ作るほうとしては気合が入っていい。


そのうち驚くほど大作が作られるかも。





「上手に絵を描く方法」みたいなタイトルで、


順を追って経過のわかる絵が何枚も綴られそうだな。





DELL PowerConnect2748 スイッチ



DELL スイッチの選び方


http://www.sssg.org/blogs/naoya/archives/1201#


こちらの記事を読んで



ほぼ仕様は同じだが、一番大きな違いに CLI(コマンドラインインターフェース)のサポートの違いがある。CLI を使うと、スイッチの各ポートの状態を把握しているのでよくあるといわれているスイッチのあるポートが故障しているか事前にチェックすることができるのが多い。値段はすこし高いが、この機能のサポートでインフラの中でもかなり重要なスイッチの故障が検出できるのはとても大きい。ミッションクリティカルなシステムには、PowerConnect 5448 を使った方が安心だろう。



ミッションクリティカルの場合は PowerConnect 5448 のほうがよいのか。。。


スイッチが故障したことはないので、あまりその辺は考慮していなかったなぁ。





ノンインテリジェントスイッチの PowerConnect 2748を何となく選んで使っていました。


転送量とか、ポートの数とかの数字は見てたつもりですが


仕様の比較ってのは結構適当だったきがします。


値段が何で違うかってそれなりの理由があるもんですね。(あたりまえか。。。)





2009年9月3日木曜日

採用面接



8月上旬から、FindJobでプログラマー、デザイナー、ディレクターなどの募集をして


100名ほど募集がきました。


いやはや、面接は難しい。


とりあえず、もらったメールの中から3分の1くらいまでに絞って、


1日に5人ずつくらい面接しているんだけど、メールの印象だけじゃぜんぜんわからない。


話をしていても、なかなかこれはいい人材だと思える人はそういるもんじゃない。


本格的に人材採用に取り組んだのはこれが初めてなのでちょっと苦労しています。


特にひどい人は、Webシステムの会社ってことを知らずに来たり、履歴書を持ってこなかったり


面接に来てるのに自己アピールが無かったり、


こっちも何を聞いたらその人のことが分かるのか悩んでおります。


基本的に


1.情熱やガッツがあること


2.夢ややりたい事があること


3.素直であること


4.Webが好きなこと


5.いい仲間と仕事がしたいと思っていること


おおむね、上記のようなことが前提になるのですが


意外と5条件をクリアーしている人っていないんです。


スキルとかできることは、ある程度もらったメールや


職歴を見れば分かるので、人間味のある部分をやっぱり見たいなぁって気になります。


数十分の面接ですべてが分かるわけ無いので、その人間性の片鱗だけでも伝われば


こっちもその気になるんですけどね。なかなか気の利いたアピールは無いですね。


面白い、いい人に来てほしいなぁ。


明日もまだ面接の予定なのでわが社の希望の星が見つかりますように!





2009年8月6日木曜日

PHPからRsyncを実行する時にはまったこと



PHPの exec , system 関数を使って、直接コマンドを実行することができます。


これをうまく使えば、PHP単体では実現しにくいことを


他のアプリと連携して実行することができます。


そんなわけで、ためしにWebのインターフェイスからボタンを押すと


サーバ上のファイルのバックアップをとるように、PHPからRsyncを実行させようとした時の話です。


下準備として、実行するRsyncを手打ちでまず実行できるか確認します。



# サーバ上の /xxx/xxxx/ のファイルをローカルの /xxx/xxxx/ に同期させると考えます。

rsync -auv -e ssh xxxx@example.com:/xxx/xxxx/ /xxx/xxxx/



※ssh を利用するためパスワードを入力せずに接続できるよう公開認証キーの設定をしておく


(この設定は、ネットでもたくさん情報ありますのでそちらをご覧ください)








上記の手打ちの rsync コマンドは難なく実行できたので


PHPから同様のコマンドを実行するようにして見ます。






system('rsync -auv -e ssh xxxx@example.com:/xxx/xxxx/ /xxx/xxxx/')








自信たっぷりに実行してみたのですが


ものの見事に、うまく動作できずはまってしまいました。





ポイントは2点、パーミッションパスです。





まず、パーミッションに関しては、PHPからrsyncを実行するので当然ユーザはhttpdの実行者(apache)になります。


先ほどsshをパスワードなしで接続できる設定をしたのは、apache ではなく他のユーザアカウントでした。


apacheでパスワードなしの設定をしても良いのですがその場合にrsyncでファイルを同期したときの所有者が


apache になってしまい都合が悪いです。





ユーザアカウント hogehoge とかで実行したいですね。


そこで、PHPをApacheのモジュールではなく、CGI経由で実行するようにします。


phpには、mod_suphp というCGI経由で実行するためのモジュールがあるのでインストールします。


(mod_suphpのインストール方法は割愛します)


インストールができたら、phpinfo() などで Server APIを確認します。CGI/FastCGI と出ていたら設定OKです。


suphpの設定が多少難易度が高いかもしれません。





次に、rsync の実行する際のパスです。


PHPのexec ,system 関数は、どうもそのままだと絶対パスで表記する必要があるらしく


上記のコマンドは、以下のようにする必要があります。sshのほうも絶対パスです。


(何か環境変数的なパラメータを初期化すればいけるのかもしれませんが。。。)



system('/usr/bin/rsync -auv -e /usr/bin/ssh xxxx@example.com:/xxx/xxxx/ /xxx/xxxx/')








このことがわからず四苦八苦したため、かなり時間のロスをしまいました。


知っていればどうってことないのですが、知らない場合はひたすらレスポンスが真っ白で何も値が返ってこない地獄を見ます。


(もう少し、エラー的なメッセージを表示させてくれたら助かるのに。。。)





たまにしかこういうプログラムは書かないから、


何度も同じ穴にはまりそう。


一応、備忘録として書き留めておくけど


書いたこと忘れたら意味ないよなぁ。。。。





2009年4月20日月曜日

Text_Wiki_MediaWiki パッケージのParse/Table.phpの修正



PEARのText_Wiki_MediaWiki に含まれる Parse/table.php の一部分を修正



var $regexRows = '#(?:^(\||!)-|\G)(.*?)^(.*?)(?=^(?:\|-|!-|\z))#msi';

var $regexRows = '#(?:^(\||!)-|\G)(.*?)^(.*?)(?=^(?:\|-|!-|\z)|$)#msi';



行の終端が、文字列の終端の場合に、うまく タグに変換されていなかったので


正規表現を修正しました。


PEAR Text_Wiki_MediaWiki の Parser は、だいぶ更新されていないみたいで


WikiPediaのデータをそのままParseしても、ちゃんと表示されない場合が多い。





2009年4月18日土曜日

別ポートで1台のサーバでPostgreSQLを複数起動する方法



テスト環境の設備の問題などで、あんまりサーバの台数がまかなえなかった時に


1台のPCで2役をしてもらいたい時なんかに有効です。


まずは、PostgreSQLをインストールして、デフォルトの状態で起動します。



postmaster -D /var/lib/pgsql/data -p 5432


次に、複数起動する場合は、ポートと、データの保存場所を変えてやれば


起動できます。




initdb -D /var/lib/pgsql/data2

# postgresql.conf 編集
tcpip_socket = true
port = 5433

postmaster -D /var/lib/pgsql/data2 -p 5433 &



あと、適当に pg_hba.conf を環境に合わせて編集したらOKかと。





mod_proxy でバックエンドにSSLを利用する設定



あまり実運用では、こういう場面は経験はないですが


mod_proxy で バックエンド側とSSL通信するような時の設定です。



SSLProxyEngine On
ProxyPass / https://example.com/
ProxyPassReverse / https://example.com/


ローカルのテスト環境に設置したSSLサイトを、無理やり外部からアクセスできるように


Proxyを通す必要があったため、こういうことになったのですが


実際の運用では必要ないかもしれませんね。参考程度ですね。





2009年3月19日木曜日

X-Forwarded-Forを使って、バックエンドでアクセス制限



バックエンドサーバーで、IPを使ったアクセス制限をすると


クライアントがフロントエンドのIPアドレスになってしまうため


意味が無い。そこで、X-Forwarded-Forを使って制限をする。




.htaccess

SetEnvIf X-Forwarded-For "192\.168\.0\.[0-9]{1,3}" apal

order deny,allow
deny from all
allow from env=apal



すぐに書き方を忘れてしまうので、備忘録です。





2009年2月13日金曜日

バックエンドサーバでも、リモートIPアドレスを取得する



気がつけば、2ヶ月近く日記を書いてなかった。。。。




$ip = $_SERVER['HTTP_X_FORWARDED_FOR'] ? $_SERVER['HTTP_X_FORWARDED_FOR'] : $_SERVER['REMOTE_ADDR'] ;



mod_proxy とかを使って、バックエンドでPHPを実行しているときとかに


クライアントの接続元IPアドレスを取得する際に利用。


知ってると、どうってことないけど、わからないときは結構調べたりするようなことかな。