% defaults write com.apple.screencapture location ~/Pictures/screenshot
% killall SystemUIServerあるべき初期データの姿が不明。今動いてるDBが全て。という場合にmigrationをはじめるのが難しい。また、複合主キーを使ってる場合はそもそもmigration出来ない。なので無理矢理afterでdumpファイルを読み込んで対応。
<?php
class xxxxxxxxxxxxxxxxx extends CakeMigration
{
public $description = '';
public $migration = array(
'up' => array(),
'down' => array(),
);
public function before($direction)
{
return true;
}
public function after($direction)
{
if ($direction == 'up') {
$config = $this->db->config;
`mysql -u{$config['login']} -p{$config['password']} {$config['database']} < db/20121010154033_create_initialize.sql`;
}
return true;
}
}レガシーコード改善ガイドが届いたので読みました。とても勇気づけられたし、レガシー改善のコーディングテクニックがいろいろと参考になりました。
個人的にはコーディング以外の開発環境やツール、スクリプト言語ならではな部分も知りたかったのでレガシーコード改善ガイド風に思いついたのを書いていこうと思います。
このPHPのコードを追える気がしません
まずは深呼吸して、コードベースをeval, create_function, extractでgrepしましょう。意外と少ないでしょう?だったら大丈夫。findとgrepとviがあればいつかは何とかなります。
バージョン管理されてません
テスト環境みたいなのがあるはず(もしくは本番環境)なのでFTPとかSCPでそれを全部もってきてgithubに突っ込む。今後、開発はそこにコミットして、アップするときもそこからアップしてねと言う。
githubを借りる許可が出なかったらその辺のマシンにgitをreposを立てる。みんなでreposを使う合意が取れなかったら自分だけでもgitで管理する。githubの利点はpull requestとコードレビューがしやすい点。
ソフトウェア資産を失わないようにという話をすれば大抵聞き入れてくれるはず。
ステージング環境がありません
その辺のマシン、もしくはさくらVPS1Gを借りてreposにpushされたらそこにデプロイされるようにしよう。(capistranoとかで)
本番環境しかないのでテストにつかうまともな初期データがありません
おそらく本番環境のDBの状態=仕様になっているのでしょう。3桁に迫るテーブルがある場合、まっさらなスキーマから手で初期データを作っていると日が暮れてしまいます。本番のDBをdumpしてきてそれをベースにテストを実行しましょう。ボトムアップではなく、トップダウンで初期データを少しずつあるべき状態にしてきましょう。
中長期的な作業をする時間がありません
本業(デスマ)も「このくらいやってれば普通以上だろう」ぐらいやりつつ開いた時間でやろう。もしくは業務時間外でやりましょう。
頑張る気が起きません
ひどい状態なら怒られない範囲でブログに書けばネタになるし同僚や誰かが助けてくれるかもしれません。着実に改善していくところをRPGみたいに楽しもう。ナイトメアモードのゲームだと思えばやりがいがあります。
こんなこと書いてたけど普通にできた。(simpletestは必要)
% cake testsuite app all
知らんかった・・・。
ついでに、phpunitを使ったseleniumのテストも一緒にできるshell作った。
app/vendors/shells/tasks/integrations.php:
<?php
class IntegrationsTask extends Shell
{
public function startup() {}
public function execute()
{
$this->out(`phpunit app/tests/integrations`);
}
}
app/vendors/shells/test.php:
class TestShell extends Shell
{
public $tasks = array('Cases', 'Integrations');
public function startup() {}
public function main()
{
$arg = isset($this->args[0]) ? $this->args[0] : '';
switch ($arg) {
case 'cases':
$this->Cases->execute();
break;
case 'integrations':
$this->Integrations->execute();
break;
default:
$this->Cases->execute();
$this->Integrations->execute();
}
}
}
% cake testとりあえず本番でエラーが起きてたら開発MLへメールしたい。レガシーPHP案件にとりかかる時はいつもやるphp.iniでメール飛ばす設定をしようとしたら、CakePHPがエラーを捕まえているので飛ばない。
大抵のフレームワークではググるとMailを飛ばすLoggerが見つかるもんだが、CakePHP1.3用のが見つからなかったので書いときました。
<?php
/**
* メールを送るロガー
*
* 使い方:
* // app/config/bootstrup.php:
* CakeLog::config('mailLog', array(
* 'engine' => 'MailLog',
* 'to' => 'to@example.com',
* 'from' => 'from@example.com'
* ));
*/
class MailLog
{
private $to;
private $from;
/**
* オプションを設定する
*
* @param array $options メールのto、fromの設定
* @return void
*/
public function __construct($options = array())
{
if (isset($options['to'])) {
$this->to = $options['to'];
}
if (isset($options['from'])) {
$this->from = $options['from'];
}
}
/**
* ログをメールで送る(ログを書く)
*
* @param string $type エラーの種類
* @param string $message エラーの内容
* @return void
*/
public function write($type, $message)
{
$subject = "[{$type}] ".mb_substr($message, 0, 32);
mb_send_mail($this->to, $subject, $message, "From: {$this->from}");
}
}
PSR0, PSR1, PSR2にしたがってPHPのソースコードをフォーマットしてくれるphp-cs-fixerを使う。(全部のルールに対応してるわけじゃない)
% sudo curl http://cs.sensiolabs.org/get/php-cs-fixer.phar -o /usr/local/bin/php-cs-fixer
% sudo chmod a+x /usr/local/bin/php-cs-fixer
% sudo php-cs-fixer self-update
% php-cs-fixer fix app/models/foo.php
vimから使う
~/.vimrc:
Bundle 'stephpy/vim-php-cs-fixer'
let g:php_cs_fixer_path = "/usr/local/bin/php-cs-fixer"
nnoremap <silent><leader>pcd :call PhpCsFixerFixDirectory()<CR>
nnoremap <silent><leader>pcf :call PhpCsFixerFixFile()<CR>
これでテンション上げてレガシーPHPを直す。
ヘッドレスブラウザとか言ってらんない人用。
selenium
% sudo su
% mkdir /usr/lib/selenium/
% cd /usr/lib/selenium/
% wget http://selenium.googlecode.com/files/selenium-server-standalone-2.25.0.jar
% mkdir -p /var/log/selenium/
% chmod a+w /var/log/selenium/
seleniumのinit scriptを書く。
% sudo vi /etc/init.d/selenium
#!/bin/bash
case "${1:-''}" in
'start')
if test -f /tmp/selenium.pid
then
echo "Selenium is already running."
else
export DISPLAY=:99
java -jar /usr/lib/selenium/selenium-server-standalone-2.25.0.jar > /var/log/selenium/selenium-output.log 2> /var/log/selenium/selenium-error.log & echo $! > /tmp/selenium.pid
echo "Starting Selenium..."
error=$?
if test $error -gt 0
then
echo "${bon}Error $error! Couldn't start Selenium!${boff}"
fi
fi
;;
'stop')
if test -f /tmp/selenium.pid
then
echo "Stopping Selenium..."
PID=`cat /tmp/selenium.pid`
kill -3 $PID
if kill -9 $PID ;
then
sleep 2
test -f /tmp/selenium.pid && rm -f /tmp/selenium.pid
else
echo "Selenium could not be stopped..."
fi
else
echo "Selenium is not running."
fi
;;
'restart')
if test -f /tmp/selenium.pid
then
kill -HUP `cat /tmp/selenium.pid`
test -f /tmp/selenium.pid && rm -f /tmp/selenium.pid
sleep 1
export DISPLAY=:99
java -jar /usr/lib/selenium/selenium-server-standalone-2.25.0.jar > /var/log/selenium/selenium-output.log 2> /var/log/selenium/selenium-error.log & echo $! > /tmp/selenium.pid
echo "Reload Selenium..."
else
echo "Selenium isn't running..."
fi
;;
*) # no parameter specified
echo "Usage: $SELF start|stop|restart|reload|force-reload|status"
exit 1
;;
esac
% sudo chmod 755 /etc/init.d/selenium
% sudo update-rc.d selenium defaults
xvfbとfirefox(iceweasel)
% apt-get install xvfb iceweasel
xvfbのinit scriptを書く。
% sudo vi /etc/init.d/xvfb
#!/bin/bash
XVFB=/usr/bin/Xvfb
# XVFBARGS=":99 -fbdir /var/run -ac"
XVFBARGS=":99 -nolisten tcp -fbdir /var/run"
PIDFILE=/var/run/xvfb.pid
case "$1" in
start)
echo -n "Starting virtual X frame buffer: Xvfb"
start-stop-daemon --start --quiet --pidfile $PIDFILE --make-pidfile --background --exec $XVFB -- $XVFBARGS
echo "."
;;
stop)
echo -n "Stopping virtual X frame buffer: Xvfb"
start-stop-daemon --stop --quiet --pidfile $PIDFILE
echo "."
;;
restart)
$0 stop
$0 start
;;
*)
echo "Usage: /etc/init.d/xvfb {start|stop|restart}"
exit 1
esac
exit 0
% sudo chmod a+x xvfb
% update-rc.d xvfb defaults散財したくなったのでAppleTV買いました。

AirPlay目当てで買ったんですが、AirPlayはMacBook Air(Late 2011)以降の対応だそうです。(持ってるのはMacBook Air Mid 2010)
やっちまった・・・。
出す出す言ってなかなか出来なかった怖話iPhoneアプリが出来ました。
http://itunes.apple.com/jp/app/bu-hua/id564486792?ls=1&mt=8
App Store初申請なので最初は絶対リジェクトされると思ってたんですがあっさり通ってびっくり。
@jishihaさんに聞いた「iOS6対応で申請がいっぱいきてるからそのどさくさで簡単に通るとおもいますよ」というここを強い言葉を信じでえいやと提出してよかったです。
結局、PhoneCap -> Titanium -> PhoneGap -> Nativeというように紆余曲折を経ました。
星5のステマしておきました。
祝Github導入
お陰様でsvnからGithubに移行。気軽にブランチ作れてとっても快適。lingrやjenkinsとの連携もやっぱりスムーズ。@hrysdとはしゃぎました。

cakeplusプラグイン
i18n関連が面倒だと書いたらコメント欄でk1LoWさんが教えて下さったcakeplusプラグインを入れてみた。超改善された。あざーす!
レガシー認証
以前も書いたが、全コントローラー、全アクションに認証処理がベタ書きされてる。そこでその処理をLegacyAuthComponetという名前で分けた。
<?php
/**
* 旧認証
*
* 古い認証機能をラップしたもの。
* 管理者ログインしていない場合はログイン画面に
* リダイレクトする
*
* 使い方:
* class FooController extends AppController
* {
* public $compornents = array('LegacyAuth');
* }
*/
class LegacyAuthComponent
{
public $name = 'LegacyAuth';
public $controller;
public function startup(&$controller)
{
$this->controller =& $controller;
$this->adminLoginRequired();
}
public function adminLoginRequired()
{
if (isset($_SESSION['ses_login']['id'])) {
$id = $_SESSION['ses_login']['id'];
} else {
$id = null;
}
if (!($id > 0)) {
$this->controller->Session->setFlash(__('admin_login_required', true));
$this->controller->redirect('/login/');
}
}
}
?>
プログラマーを求めて
一人だけでいいんだけどとにかくPHPプログラマーが見つからない。PHPの老舗、アシアルさんに相談したが、直近では空いている人がいないとのこと。しかし同じくPHP老舗であり、PHPCon2012でもニアミスしていたアリウープの柏岡様を紹介していただいた。
なんとこのブログの記事を読んでいたとのことで、ぶっちゃけたところからお話することができてとても話が速かった。しかしアリウープさんもお忙しいとのことでまだ決まるかどうかわからない状態。
それとは別で以前、ちょっと一緒にやっていくのは難しそうと書いた会社様より、「具体的に何が悪いのか、どういう人材を探しているのか説明して欲しい」との電話があり、上司の方とお話した。
どうも、こちらの話しているユニットテスト/自動テストと先方の話しているテストが違っているような気がする。
「よくわからないけど要はそういうツールがあるんですよね?だったらうちもできますよ。普通やりますよね、自動テスト」という感じ。
「でも先日見せてもらったコードにはユニットテスト無かったですよね?」(ついでにいうと使ってるライブラリはPEAR DBとSmartyだけでしたよね?)というようにちょっと話が噛み合わなかった。
僕らはそんなにすごいプログラマーを募集してるわけじゃないんです。ただ、プライベート(仕事外)でコードを書いてるPHPプログラマーだったら誰でも歓迎なんです。
しかしSIerから離れて随分経つので忘れていました。世の中にはプライベートでコードを書かないプログラマーが沢山いるという事実を・・・。
レガシーPHP改善日記
この日記が終わるかもだと・・・?
ハハハ、あんなメール、俺にとってはご褒美だ。