109
98

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Laravel 標準搭載のデバッグ機能 tinker コマンドのご紹介

Last updated at Posted at 2020-05-06

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の使いどころ?

私はちょっとした確認やブラウザ叩くの面倒だった時とかに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.phpdefine('STDIN', fopen('php://stdin', 'r')); の行をファイルの先頭に追加します。

server.php
<?php

define('STDIN', fopen('php://stdin', 'r'));

// ... 省略

ブレークポイントの設定

eval(\Psy\sh()); のコードを1行追加します。
例として routes/web.php に置きます。

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_tokenemail_verified_at のフィールドは値が入力されていません。

$hidden 非表示するかのプロパティに記述されている passwordremember_token は tinker上でモデルを表示する際にもフィールドは出力されません。
$user->toArray(), $user->all(), $user->toJson() にも影響します。

$casts プロパティでキャスト宣言が行えます。主に日付の形式を設定することが多いです。

app/User.php
<?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を利用する際はここを永続化してあげれば幸せになれます。

参考

109
98
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
109
98

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?