Laravel tinker(REPL)
Laravelフレームワークに標準搭載されている対話シェルです。
また、psysh のラッパーライブラリです。
REPL(リプル)
Read Eval Print Loop の略で対話型実行環境のことです。
キーボードから打ち込まれた命令を読み込み(Read)、評価・実行し(Eval)、結果を画面に表示し(Print)、また命令待ちの状態に戻る(Loop)処理系。
手軽にコードを実行できますが、誤字があればもちろんエラーになるので短いコードを実行して結果を確認する使い方をされます。
PHP の対話シェル
php
コマンドの -a
オプションを付けるとPHP標準の対話シェルが使用できます。
Laravelのコードはオートローダーを読み込んでいないので実行できません。
PHPの標準関数等を試す場合はこちらで十分でしょう。
$ php -a
tinker 使い方
軽くtinkerの使い方をご紹介します。
$ php artisan tinker
>>> exit
tinkerから抜けたい場合は exit
で抜けれます。
tinker上で実行していることを分かりやすくするように >>>
を表記してます。
また、tinker上では ;
を省略できます。今回は丁寧に ;
書いてます☺️
tinkerの使いどころ?
- テストデータを作るときFakerの値を確認したい時
- 試しにコントローラを動かしたい時
- EloquentのSQLの実行結果を見たい時
- 実行時のconfigの値を確認したい時
私はちょっとした確認やブラウザ叩くの面倒だった時とかにtinker使ってます。
help コマンド
help
コマンドを実行すると利用できるコマンド一覧が表示されます。
>>> help
help Show a list of commands. Type `help [foo]` for information about [f
ls List local, instance or class variables, methods and constants.
dump Dump an object or primitive.
doc Read the documentation for an object, class, constant, method or pr
show Show the code for an object, class, constant, method or property.
wtf Show the backtrace of the most recent exception.
whereami Show where you are in the code.
throw-up Throw an exception or error out of the Psy Shell.
timeit Profiles with a timer.
trace Show the current call stack.
buffer Show (or clear) the contents of the code input buffer.
clear Clear the Psy Shell screen.
edit Open an external editor. Afterwards, get produced code in input buf
sudo Evaluate PHP code, bypassing visibility restrictions.
history Show the Psy Shell history.
exit End the current session and return to caller.
clear-compiled Remove the compiled class file
down Put the application into maintenance mode
env Display the current framework environment
optimize Cache the framework bootstrap files
up Bring the application out of maintenance mode
migrate Run the database migrations
inspire Display an inspiring quote
コマンド名を引数に渡すとそのコマンドの詳細な説明を確認できます。
>>> help ls
Usage:
ls [--vars] [-c|--constants] [-f|--functions] [-k|--classes] [-I|--interfaces] [-t|--
Aliases: dir
Arguments:
target A target class or object to list.
Options:
--vars Display variables.
--constants (-c) Display defined constants.
--functions (-f) Display defined functions.
--classes (-k) Display declared classes.
--interfaces (-I) Display declared interfaces.
--traits (-t) Display declared traits.
--no-inherit Exclude inherited methods, properties and constants.
--properties (-p) Display class or object properties (public properties by default).
--methods (-m) Display class or object methods (public methods by default).
--grep (-G) Limit to items matching the given pattern (string or regex).
--insensitive (-i) Case-insensitive search (requires --grep).
--invert (-v) Inverted search (requires --grep).
--globals (-g) Include global variables.
--internal (-n) Limit to internal functions and classes.
--user (-u) Limit to user-defined constants, functions and classes.
--category (-C) Limit to constants in a specific category (e.g. "date").
--all (-a) Include private and protected methods and properties.
--long (-l) List in long format: includes class names and method signatures.
--help (-h) Display this help message.
Help:
List variables, constants, classes, interfaces, traits, functions, methods,
and properties.
Called without options, this will return a list of variables currently in scope.
If a target object is provided, list properties, constants and methods of that
target. If a class, interface or trait name is passed instead, list constants
and methods on that class.
e.g.
>>> ls
>>> ls $foo
>>> ls -k --grep mongo -i
>>> ls -al ReflectionClass
>>> ls --constants --category date
>>> ls -l --functions --grep /^array_.*/
>>> ls -l --properties new DateTime()
ls コマンド(変数の表示)
ls
コマンドはローカル、インスタンス、またはクラスの変数、メソッド、定数をリスト表示します。
>>> $foo = 'bar';
=> "bar"
$foo
ローカル変数を定義した場合
>>> ls
Variables: $foo
>>> ls -l
Variables:
$foo "bar"
-g
グローバル変数オプションを付けるとグローバル変数も覗けます。
>>> ls -gl
Global Variables:
$app Illuminate\Foundation\Application {#2 …15}
$argc 2
$argv [ …2]
$GLOBALS [ …14]
$input Symfony\Component\Console\Input\ArgvInput {#25}
$kernel App\Console\Kernel {#28}
$_COOKIE []
$_ENV [ …39]
$_FILES []
$_GET []
$_POST []
$_REQUEST []
$_SERVER [ …152]
$__composer_autoload_files [ …22]
REPLデバッグ
準備
server.php
に define('STDIN', fopen('php://stdin', 'r'));
の行をファイルの先頭に追加します。
<?php
define('STDIN', fopen('php://stdin', 'r'));
// ... 省略
ブレークポイントの設定
eval(\Psy\sh());
のコードを1行追加します。
例として routes/web.php
に置きます。
Route::get('/{name}', function (string $name) {
$message = 'Hello ' . $name;
eval(\Psy\sh());
return $message;
});
補足: PhpStorm コードスニペット
eval(\Psy\sh());
を手入力するのは割と手間なので、コードスニペットとして登録すると便利です。
-
Editor
>Live Templates
>PHP
を選択して+
-
Abbreviation
:tinker
-
Template text
:eval(\Psy\sh());
-
Define
:PHP
を選択
-
tinker
を打ったあとにtab
キー押下で変換できます。
ビルトインサーバーを利用してステップ実行する
Laravelビルトインサーバーを起動します。
http://127.0.0.1:8000/yourname
$ php artisan serve
Laravel development server started: http://127.0.0.1:8000
[Wed May 6 17:10:33 2020] PHP 7.4.5 Development Server (http://127.0.0.1:8000) started
[Wed May 6 17:10:36 2020] 127.0.0.1:50088 Accepted
[Wed May 6 17:10:36 2020] 127.0.0.1:50089 Accepted
Psy Shell v0.10.3 (PHP 7.4.5 — cli-server) by Justin Hileman
From /laravel/routes/web.php:18:
16: Route::get('/{name}', function (string $name) {
17: $message = 'Hello ' . $name;
> 18: eval(\Psy\sh());
19:
20: return $message;
ブレークポイントで処理が一時停止します。(ブラウザの描画も停止します)
exit
を入力すると処理を継続します。
help
コマンドなどtinker上のコマンドも使用できます。
whereami
, show
, trace
等を使うとデバッグが便利です。
Laravelコードのお試し実行
tinkerではLaravelのコードも実行できます。
今回はEloquentモデルからデータの作成と取得の一例をご紹介します。
簡単に試せることをお伝えしたいだけですので、詳しいことは公式ドキュメントをご参照ください。
ファクトリーメソッドでUserモデルクラスを作成
>>> factory(App\User::class)->create();
=> App\User {#3042
name: "Prof. Armani Eichmann Jr.",
email: "porter.feil@example.com",
email_verified_at: "2020-05-05 10:00:49",
updated_at: "2020-05-05 10:00:49",
created_at: "2020-05-05 10:00:49",
id: 1,
}
Userモデルクラスを new して作成
>>> $user = new App\User();
>>> $user->name = 'foo';
>>> $user->email = 'foo@example.com';
>>> $user->email_verified_at = now();
>>> $user->password = bcrypt('secret');
>>> $user->remember_token = Str::random(10);
>>> $user->save();
>>> $user; // 変数名で中身を表示できます。
=> App\User {#3039
updated_at: "2020-05-05 10:08:52",
created_at: "2020-05-05 10:08:52",
name: "foo",
email: "foo@example.com",
email_verified_at: "2020-05-05 10:09:23",
id: 2,
}
Userモデルクラスを create して作成
>>> $attributes = [
'name' => 'bar',
'email' => 'bar@example.com',
'email_verified_at' => now(),
'password' => bcrypt('secret'),
'remember_token' => Str::random(10),
];
>>> App\User::create($attributes);
=> App\User {#3072
name: "bar",
email: "bar@example.com",
updated_at: "2020-05-05 10:15:31",
created_at: "2020-05-05 10:15:31",
id: 3,
}
User::create
の場合の補足です。
$fillable
複数代入を許可するかのプロパティに記述のないremember_token
と email_verified_at
のフィールドは値が入力されていません。
$hidden
非表示するかのプロパティに記述されている password
と remember_token
は tinker上でモデルを表示する際にもフィールドは出力されません。
$user->toArray()
, $user->all()
, $user->toJson()
にも影響します。
$casts
プロパティでキャスト宣言が行えます。主に日付の形式を設定することが多いです。
<?php
namespace App;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
class User extends Authenticatable
{
use Notifiable;
/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = [
'name', 'email', 'password',
];
/**
* The attributes that should be hidden for arrays.
*
* @var array
*/
protected $hidden = [
'password', 'remember_token',
];
/**
* The attributes that should be cast to native types.
*
* @var array
*/
protected $casts = [
'email_verified_at' => 'datetime',
];
}
モデルの取得(全件)
>>> App\User::all();
=> Illuminate\Database\Eloquent\Collection {#3024
all: [
App\User {#3025
id: 1,
name: "Prof. Armani Eichmann Jr.",
email: "porter.feil@example.com",
email_verified_at: "2020-05-05 10:00:49",
created_at: "2020-05-05 10:00:49",
updated_at: "2020-05-05 10:00:49",
},
App\User {#3026
id: 2,
name: "foo",
email: "foo@example.com",
email_verified_at: "2020-05-05 10:09:23",
created_at: "2020-05-05 10:08:52",
updated_at: "2020-05-05 10:08:52",
},
App\User {#3027
id: 3,
name: "bar",
email: "bar@example.com",
email_verified_at: null,
created_at: "2020-05-05 10:15:31",
updated_at: "2020-05-05 10:15:31",
},
],
}
モデルの取得(ID指定)
>>> App\User::find(2);
=> App\User {#3030
id: 2,
name: "foo",
email: "foo@example.com",
email_verified_at: "2020-05-05 10:09:23",
created_at: "2020-05-05 10:08:52",
updated_at: "2020-05-05 10:08:52",
}
モデルの取得(条件指定)
>>> App\User::where('name', 'bar')->get();
=> Illuminate\Database\Eloquent\Collection {#3021
all: [
App\User {#3016
id: 3,
name: "bar",
email: "bar@example.com",
email_verified_at: null,
created_at: "2020-05-05 10:15:31",
updated_at: "2020-05-05 10:15:31",
},
],
}
SQLの取得
>>> App\User::where('name', 'bar')->toSql();
=> "select * from `users` where `name` = ?"
応用
show コマンド(クラスを表示)
>>> show App\User
9: class User extends Authenticatable
10: {
11: use Notifiable;
12:
13: /**
14: * The attributes that are mass assignable.
15: *
16: * @var array
17: */
18: protected $fillable = [
19: 'name', 'email', 'password',
20: ];
21:
22: /**
23: * The attributes that should be hidden for arrays.
24: *
25: * @var array
26: */
27: protected $hidden = [
28: 'password', 'remember_token',
29: ];
30:
31: /**
32: * The attributes that should be cast to native types.
33: *
34: * @var array
35: */
36: protected $casts = [
37: 'email_verified_at' => 'datetime',
38: ];
39: }
show コマンド(メソッドを表示)
>>> show App\Providers\RouteServiceProvider::map
38: /**
39: * Define the routes for the application.
40: *
41: * @return void
42: */
43: public function map()
44: {
45: $this->mapApiRoutes();
46:
47: $this->mapWebRoutes();
48:
49: //
50: }
doc コマンド(PHPマニュアル)
日本語ファイルをダウンロードして、
~/.local/share/psysh/
または /usr/local/share/psysh/
に配置します。
$ mkdir ~/.local/share/psysh/
$ curl -Lo ~/.local/share/psysh/php_manual.sqlite http://psysh.org/manual/ja/php_manual.sqlite
docコマンドが使用できるようになり、PHPマニュアルをtinker上で確認できます。
>>> doc abs
function abs($number)
Description:
絶対値
$number の絶対値を返します。
Param:
mixed $number 処理する数値。
Return:
number $number の絶対値を返します。もし $number の型が float であった場合、 返り値
なります。それ以外の場合は 返り値の型は integer となります(float は、 integ
り大きい値をとることがありえるからです)。
See Also:
* gmp_abs()
* gmp_sign()
tinker 構成ファイルの公開
$ php artisan vendor:publish --provider="Laravel\Tinker\TinkerServiceProvider"
config/tinker.php
ファイルが出力されます。
名前空間のエイリアス設定が行えます。
tinkerコマンド履歴
~/.config/psysh/psysh_history
に tinkerのコマンド履歴が残っていきます。
開発環境でdockerを利用する際はここを永続化してあげれば幸せになれます。