PsySH公式サイト日本語訳

http://psysh.org/

英語力がないのでいつものように適当超訳です。
使用したバージョンはv0.7.2。

## >>> psysh

pshpyは対話式のデバッグコンソールで、PHPの[REPL](http://d.hatena.ne.jp/keyword/REPL)だよ。[^1]

### Have eight seconds? Try PsySH

8秒で始めるPsySH。

```bash
	$ wget https://git.io/psysh
	$ chmod +x psysh
	$ ./psysh
```

↑どっちか↓

```bash
	$ composer g require psy/psysh:@stable
	$ psysh
```


### Stop die()ing all the time

PsySHはJavaScriptでいうF12みたいに、インタラクティブなデバッガとして利用できるよ。
これでvar_dump()とdie()の繰り返しから開放されるよ。
ブレークしたい行に`eval(\Psy\sh());`って書くだけでいいよ。

### Auto[tab][tab]Complete

変数、関数、クラス、メソッド、プロパティ、あとファイル名もTABで補完できるよ。[^2]

### Name all the spaces

もう名前空間で苦労しない。
PHPのシェルでnamespaceを指定するのは大変だけど、PsyPHならよしなに計らってくれるよ。

```php
namespace Alpha{
	use stdClass as Bravo;
	class Charlie extends Bravo{}
}
namespace Delta{
	use Alpha\Charlie as Foxtrot;
	class Golf extends Foxtrot{}
}
namespace{
	use stdClass as Hotel;
	use Alpha\Charlie as India;
	use Delta\Golf as Juliett;
	
	$kilo = new Juliett();
	;var_dump(
		 $kilo instanceof Alpha\Charlie // true
		,$kilo instanceof Delta\Golf // true
		,$kilo instanceof Hotel // true
		,$kilo instanceof India // true
		,$kilo instanceof stdClass // true
	);
}
```

とか書いてあるんだけど、素の`php -a`でもたいして変わらなかったから何が利点なのかよくわからなかった。

### Read documentation in context

関数の使い方がわからない？
`doc array_map`で解説が出るぞ。
プロパティの意味がわからない？
`doc $response->statusTexts`って書くよろし。
doc自体のヘルプは`help doc`で確認できるよ。

ただ[予めマニュアルをダウンロード](https://github.com/bobthecow/psysh#downloading-the-manual)しておかないと↓って出る。

```php
PHP manual not found
    To document core PHP functionality, download the PHP reference manual:
    https://github.com/bobthecow/psysh#downloading-the-manual
```

### Reflect like a boss

listコマンドは全てを知っている。
全ての変数、定数、クラス、インターフェイス、トレイト、関数、メソッド、プロパティを探してくれるぞ。

```php
>>> list GMP_VERSION
InvalidArgumentException with message 'Unknown class or function: GMP_VERSION'
```

とか書いてあるんだけど、なんか関数とクラスしか見てくれない。
しかも関数は何も返ってこないので実質クラス専用。
よくわからない。

やってることはReflectionClass::exportだけど、出力が整形されるため見やすい。

### Use the source!

実装したオブジェクト、クラス、インターフェイス、トレイト、定数、メソッド、プロパティのソースをshowコマンドで即見ることができるぞ。
これはわりと便利、かと思いきや見れるだけで修正はできないのであまり意味がなかった。

### Forget to catch that last exception?

最後に発生した例外をキャッチすることができるぞ。
ただ過去に遡ることはできないっぽいので、デバッグ時にうっかりコマンドを間違ったら今度はそちらが出てくるようになってしまい、元の例外がわからなくなってしまう。
最後から2番目の例外とか取得できればよかったんだけど。

### Learn from your history and repeat your past

コマンド履歴を`history`で確認できるぞ。
Linuxのhistoryと同じなんだけど、XAMPP上では何故か履歴が全く出てきてくれなかった。

### Roll your own commands

これで満足できなければ、独自にカスタムコマンドを書くこともできるぜ。
そのために手厚いサポートを用意しているから、`~/.config/psysh/config.php`に登録するんだ。

`~`はユーザのホームディレクトリなので、設定ファイルの置き場はカレントディレクトリやDocumentRootとは全く関係なく`/home/username/.config/psysh/config.php`とか`C://Users/username/.config/psysh/config.php`とかになる。
問題は特定のプロジェクト配下にだけコマンドを追加したいとかいう場合、そのような指定方法がないっぽい。
デフォルトで`/etc/xdg/psysh/config.php`というグローバルな場所も見てくれるみたいだが、ここだと完全にサーバ毎の共通になるためプロジェクトで分けられないし、あとWindowsにはそんなディレクトリが無い。
一応Psy\Configurationにはコンフィグファイルを指定できるようなことが書いてあるのだが、そこに値を渡す方法がわからなかった。
そもそも`eval(\Psy\sh());`って一体何が呼ばれてるんですかね。

## How is this thing better than $shell_ive_used_since_2008?

概要については[OSCON 2013](http://conferences.oreilly.com/oscon/oscon2013)で公開した[Interactive Debugging in PHPのスライド](https://presentate.com/bobthecow/talks/php-for-pirates)をチェックしてくれ。
$shell_ive_used_since_2008については全く意味がわからない。

## Usage

### PsySH as a REPL

いちどインストールしたら`./psysh`って打つだけで簡単にREPLなコンソールを使えるよ。
composerの場合`vendor\bin\psysh`になる。

PHPのコードを入力し、その結果を対話的に見ることができるよ。

```php
>>> $x=1;
=> 1
>>> PDO::FETCH_ASSOC;
=> 2
```

echoとか打たなくても結果が即画面に出てくるので、デバッグに便利。

### PsySH as a Debugger

デバッガとして使いたいときは、Composerをincludeすればいいよ。

```php
	require_once('/path/to/composer/vendor/autoload.php');
	
	// ブレークはどちらでもいい模様
	eval(\Psy\sh());
	extract(\Psy\Shell::debug(get_defined_vars()));
	
	// 任意の値を渡す
	extract(\Psy\Shell::debug(['hoge'=>'fuga'])); // $hogeに入る

```

元記事では`require('/path/to/psysh');`ってなってるんだけど何処だこれ。

```php
	class HOGE{
		public function fuga(){
			\Psy\Shell::debug(get_defined_vars(), $this);
		}
	}

	$h = new HOGE();
	$h->fuga(); // Fatal error: Uncaught Error: Cannot re-assign $this
```

元記事では第二引数で$thisを渡すことができるとなっていますが、PHP7.1では[$thisガードが堅くなった](http://qiita.com/rana_kualu/items/572494021917fbb93c95#fix-inconsistent-behavior-of-this-variable)ため動作しなくなっています。
さらにPsysh上で$thisって打つと落ちます。
まあそのうち修正されるでしょう。

### Magic Variables

```php
>>> 10
=> 10
>>> $_
=> 10

>>> $_e
PHP error:  Undefined variable: _e on line 1
>>> $_e
=> Psy\Exception\ErrorException {
     #message: "PHP error:  Undefined variable: _e on line 1",
     #line: 1,
   }
```

`$_`で直前に評価した値、`$_e`で直前に発生した例外を取得できるよ。

### Configuration

なるだけ正しい設定を自動検出するようにしてるけど、`~/.config/psysh/config.php`とかに設定書いておけば上書きできるよ。

```php
return array(
	/**
	* 表示に使うコマンド。
	* 初期値は`less`。
	* php.iniの`cli.pager`で設定できる。
	*/
    'pager' => 'more',
	
	/**
	* historyに保存する件数。0で無制限。
	*/
    'historySize' => 0,
	
	/**
	* trueにするとhistoryに同じコマンドが入ってきたときに重複を削除する。
	* bashのHISTCONTROL=erasedupsと同じ。
	*/
    'eraseDuplicates' => false,
	
	/**
	* pcntlがインストールされていれば、プロセスはデフォルトでfork()で動作する。
	* が、明示的に有効無効を切り替えたいときに指定可能。
	*/
    'usePcntl' => false,
	
	/**
	* readlineがインストールされていればデフォルトでそっちを使う。
	* が、使いたくない場合は設定変更できる。
	*/
    'useReadline' => false,
	
	/**
	* 行末にセミコロンがないときは自動補完するけど、補完してほしくない場合はtrueにする。
	*/
    'requireSemicolons' => true,
	
	/**
	* デフォルトではUTF-8で出力するけど、それを無効にできる。
	* "couple of UTF-8"ってなんだ？
	*/
    'useUnicode' => false,
	
	/**
	* Psyshは表示するエラーレベルは現在の設定を使用するが、エラーの記憶自体は全レベルで行っている。
	* エラーの記憶基準を変えたい場合はここで設定。
	*/
    'errorLoggingLevel' => E_ALL & ~E_NOTICE,
	
	/**
	* これを書いておけばpsysh起動時に自動的にincludeしてくれる。
	*/
    'defaultIncludes' => array(
        __DIR__ . '/include/bootstrap.php',
    ),
	
	/**
	* psyshコマンドを追加することができる。
	* ParseCommand/ReflectingCommand/PsyVersionCommandは存在するのにデフォルトでは読み込まれてない模様。
	*/
    'commands' => array(
        new \Psy\Command\ParseCommand,
    ),
	
	/**
	* SymfonyのVarDumperを書くことができるよ。
	* よくわからんけど。
	* @see http://symfony.com/doc/current/components/var_dumper/advanced.html#casters
	*/
    'casters' => array(
        'MyFooClass' => 'MyFooClassCaster::castMyFooObject',
    ),

    /**
    * タブ補完を無効にできるよ。
    * なんでそうしたいかは知らないけど。
    */
    'tabCompletion' => false,
	
	/**
	* タブ補完辞書を自分で書くことができるよ。
	* なお仕組みはよくわからなかった。
	*/
    'tabCompletionMatchers' => array(
        new \Psy\TabCompletion\Matcher\MongoClientMatcher,
        new \Psy\TabCompletion\Matcher\MongoDatabaseMatcher,
    ),

    /**
    * 複数の設定ファイルで同じ設定項目の上書きがあった場合、現状では最も優先順位の高いファイルを優先するよ。
    * trueにすると重複があればE_USER_NOTICEが発生するようになるよ。
    * 将来はデフォルトがtrueになる予定だよ。
    */
    'warnOnMultipleConfigs' => true,

    /**
    * 出力の色指定は、デフォルトでは対応してるかどうか調べて適切な方を選んでるよ。
    */
    'colorMode' => \Psy\Configuration::COLOR_MODE_FORCED,   // カラーを強制する
    'colorMode' => \Psy\Configuration::COLOR_MODE_DISABLED, // 白黒を強制する
);
```

## 感想

正直そんなに使いやすいとは思わなかった。
そもそも私はコマンドラインでのデバッグをあまり行わないからということもあるが、何よりステップ実行できないのが残念。
これが何故かブラウザ上でコマンドが打てるようになるとかだったら掌くるくる回転させて感動に打ち震えるのだが、実際はブラウザ上でpsyshを呼び出しても何も起きないんだなこれが。
ウィンドウを開いておいてブラウザアクセスするとPsySHが開くようにする方法もあるらしいんだけど、XAMPPではどうやるのかよくわからなかった。

[^1]: PHP本体にもphp -aという[対話シェル](http://php.net/manual/ja/features.commandline.interactive.php)が存在するが、それより高性能ということらしい。
[^2]: 補完機能はphp -aにも存在する。