is_callable() のススメ
PHP で、クラスに関数が定義されている場合のみ当該関数を call する〜なんてことをする際に、下記のようなコードを書いていたのですが、、、
<?php if (method_exists($hoge, 'func')) { $hoge->func(); }
「これって、func() が存在するけどその scope から呼べないケースどうなるん?private 関数とか。」という声を聞いて、これはまずそうだなと。
こんなとき、is_callable() ってのを使うと良いみたい。
PHP: is_callable - Manual
以下、サンプルコード。
<?php class Hoge { public function this_is_public() {} protected function this_is_protected() {} private function this_is_private() {} } $hoge = new Hoge(); if (method_exists($hoge, 'this_is_public')) { echo 'aaa' . PHP_EOL; } if (method_exists($hoge, 'this_is_protected')) { echo 'bbb' . PHP_EOL; } if (method_exists($hoge, 'this_is_private')) { echo 'ccc' . PHP_EOL; } if (is_callable(array($hoge, 'this_is_public'))) { echo 'ddd' . PHP_EOL; } if (is_callable(array($hoge, 'this_is_protected'))) { echo 'eee' . PHP_EOL; } if (is_callable(array($hoge, 'this_is_private'))) { echo 'fff' . PHP_EOL; } $hoge->this_is_public(); //$hoge->this_is_protected(); // Fatal error: Call to protected method Hoge::this_is_protected() from context '' in ... //$hoge->this_is_private(); // Fatal error: Call to private method Hoge::this_is_private() from context '' in ...
$ php ./test.php aaa bbb ccc ddd
method_exists() はアクセス指定が何であろうと、関数さえ定義されてれば true 判定。
is_callable() はアクセス可能な場合のみ、true 判定。
冒頭のケースでは、明らかに後者のが適切ですね。。。
試しに上のクラスを継承したら protected な関数も is_callable() = true と判定されました。
<?php class Hoge { ... } class Fuga extends Hoge { public function test() { if (is_callable(array($this, 'this_is_public'))) { echo 'ddd' . PHP_EOL; } if (is_callable(array($this, 'this_is_protected'))) { echo 'eee' . PHP_EOL; } if (is_callable(array($this, 'this_is_private'))) { echo 'fff' . PHP_EOL; } } } $fuga = new Fuga(); $fuga->test();
$ php ./test.php aaa bbb ccc ddd ddd eee
git add の dryrun
man 眺めてて偶然発見。
あんま使い機会なさそうですが、、、配下にディレクトリごとまるっとコピーして、そいつを git add する際に、どんくらい add されるかを俯瞰する、なんてケースには使えるかな。
$ cd /path/to/working/dir $ git add . -n
git でタグを切る/チェックアウトする
修正を push。
$ git push git.sample.jp:path.to.repos
このタイミングでタグを切っておこうと思い立つ。
hash で指定してみる。
git log --pretty=oneline
目的の hash でタグ切る。今回は tags_ver_1.0.0 という名前で。
git tag tags_ver_1.0.0 123456789012345678901234567890abcdeabcd
レポジトリに反映。
git push origin tags_ver_1.0.0
タグを指定してチェックアウトしてみる。
$ git clone git.sample.jp:path.to.repos $ git branch * master
branch は master のみ。
タグ一覧を確認。
$ git tag -l tags_ver_1.0.0
さっき切ったタグが表示される。こいつをチェックアウト。
$ git checkout tags_ver_1.0.0 Note: checking out 'tags_ver_1.0.0'. You are in 'detached HEAD' state. You can look around, make experimental changes and commit them, and you can discard any commits you make in this state without impacting any branches by performing another checkout. If you want to create a new branch to retain commits you create, you may do so (now or later) by using -b with the checkout command again. Example: git checkout -b new_branch_name HEAD is now at 123456... fix invalid permission description $ git branch * (no branch) master
何かプチ怒られしました。
branch を作成せずに tag を checkout すると、detached HEAD なる状態になるようです。
タグを切った状態のスナップショットが欲しいだけならばコレで全く問題ありませんが、ここを起点にさらにバリバリ開発を継続するのであれば、ブランチを作成してチェックアウトしたほうがよさそうです。
$ git checkout -b tags_ver_1.0.0
print_a でお手軽 debug
php 開発で多用するのが、var_dump やら var_export やらによる debug 出力。
こんなカンジ。ちょっとめんどいですよね。
var_dump(var_export($hoge, true));
print_a を使うと、とてもお手軽です。
print_a を利用するには、debuglib.php というファイルを読み込む必要があるので、下記から取得。
phpdebuglib.de - このウェブサイトは販売用です! - phpdebuglib リソースおよび情報
使い方はとっても簡単。例えば下記のようなソースコードだと、
<?php require_once "/path/to/debuglib.php"; class Hoge { var $foo = 'foo'; var $bar = 123; }; $hoge = new Hoge(); $fuga = array( 'aaa' => '111', 'bbb' => '222', 'ccc' => array( 'ddd' => '333', 'eee' => '444', ), 'fff' => '555', 'ggg' => $hoge, ); print_a($fuga); // 使ってみた
使うときに毎回 require するのはめんどくさいので、php.ini で自動で読み込んでおくとよいと思います。
自分の環境では下記に。
/etc/php5/apache/php.ini
; Automatically add files before or after any PHP document. auto_prepend_file = "/path/to/debuglib.php"
追加した後は apache の reload をお忘れなく。
OS やら kernel やらの version を調べるコマンド
掲題の件、下記 2 コマンドをよく使う。
主に debian 環境にて。
■OS
$ cat /proc/version Linux version 2.6.26-2-xen-686 (Debian 2.6.26-26lenny2) (dannf@debian.org) (gcc version 4.1.3 20080704 (prerelease) (Debian 4.1.2-25)) #1 SMP Thu Jan 27 05:44:37 UTC 2011
■kernel
$ uname -a Linux hostname 2.6.26-2-xen-686 #1 SMP Thu Jan 27 05:44:37 UTC 2011 i686 GNU/Linux
レポジトリからディレクトリを削除
下記コマンドで消せる。
git rm -r hoge/ git rm -r --cached hoge/
前者だとディレクトリ自体も消えます。
後者だとディレクトリは残った上で、インデックスからのみ削除されます。
上のコマンド叩いて git status すると、deleted 状態になっていることが確認出来ます。
git status # On branch master # Changes not staged for commit: # (use "git add/rm <file>..." to update what will be committed) # (use "git checkout -- <file>..." to discard changes in working directory) # # deleted: hoge/foo # deleted: hoge/bar
あとはいつも通り commit してあげれば OK。
なお、削除したディレクトリを復元はこんな。
git reset
削除時に --cached つけないとディレクトリ自体が消えてしまうので、復元するにはもう一度 checkout しなおす必要があるような。
input buffer overflow, can't enlarge buffer because scanner uses REJECT
gtags -v したら、下記エラーメッセージを出力して処理が止まってしまいました。
(snip) [31363] extracting tags of path/to/file/xxx.php [31364] extracting tags of path/to/file/yyy.php input buffer overflow, can't enlarge buffer because scanner uses REJECT
エラーメッセージでググってみると、下記サイトがヒット。
http://www.stack.nl/~dimitri/doxygen/faq.html
一度に256K 以上の入力文字にマッチする 場合に起こるとか。ファイルがでかすぎる、と。
解決策として、「ファイル分割」か「ファイル自体を無視」の二択が紹介されているので、今回は後者で対処。
gtags.conf を修正します。
自分の debian 環境では、/usr/share/gtags/gtags.conf にありました。
念のため、home ディレクトリにコピって作業。
cp /usr/share/gtags/gtags.conf ~/conf/ emacs ~/conf/gtags.conf
デフォルトではこんなカンジ。
default:\ :tc=gtags:tc=htags: #--------------------------------------------------------------------- # Configuration for gtags(1) # See gtags(1). #--------------------------------------------------------------------- common:\ :skip=GPATH,GTAGS,GRTAGS,GSYMS,HTML/,HTML.pub/,html/,tags,TAGS,ID,y.tab.c,y.tab.h,cscope.out,cscope.po.out,cscope.in.out,SCCS/,RCS/,CVS/,CVSROOT/,{arch}/,autom4te.cache/:
この :skip に、問題となったファイルを追記。今回はフォルダごとまるっと追記。
default:\ :tc=gtags:tc=htags: #--------------------------------------------------------------------- # Configuration for gtags(1) # See gtags(1). #--------------------------------------------------------------------- common:\ :skip=GPATH,GTAGS,GRTAGS,GSYMS,HTML/,HTML.pub/,html/,tags,TAGS,ID,y.tab.c,y.tab.h,cscope.out,cscope.po.out,cscope.in.out,SCCS/,RCS/,CVS/,CVSROOT/,{arch}/,autom4te.cache/, path/to/file/
この gtags.conf を使用して、再度 gtags -v 実施。
gtags -v --gtagsconf ~/conf/gtags.conf
これで、先ほど止まった箇所(path/to/file/)を華麗にパスして処理継続してくれるはず。
その先で詰まったら、また同様に無視する対象を gtags.conf に追記。
ちなみに、、、今回問題となったと思われるファイル。
$ wc -l path/to/file/yyy.php 65598 path/to/file/yyy.php
うん。でかいな。