Laravel Artisan: The Tinker Command

December 7, 2016

The ability to easily interactive with your application to experiment or debug issues is an incredibly important thing. To help with this, Laravel provides a tinker command out of the box. The tinker command uses the PsySH library to setup a REPL (read-eval print loop) environment within the context of your Laravel application (this chapter may refer to Tinker, the Tinker REPL or Tinker environment; these are all referring to the same thing). The Tinker REPL allows you to interact with your application in a way that is not dissimilar to interacting with client-side code using products like Chrome's Developer Tools.

To get started using Tinker, simply issue the tinker Artisan command in the root application directory:

1# Start a Tinker session.
2php artisan tinker

If the Tinker session has started successfully, the console will display output similar to the following:

1Psy Shell v0.7.2 (PHP 7.0.8 — cli) by Justin Hileman
2>>>

#Executing Arbitrary Code Statements

The Tinker REPL allows you to enter PHP code and have it evaluated immediately, similar to how Chrome's Developer Tools allow JavaScript developers to experiment directly with a running application. The following example demonstrates entering a PHP echo statement; the results of the statement are displayed directly below the statement:

1Psy Shell v0.7.2 (PHP 7.0.8 — cli) by Justin Hileman
2>>> echo 'Hello, from Tinker'
3Hello, from Tinker
4=> null
5>>>

However, what makes Tinker a powerful and invaluable tool is the ability to interact with framework components and classes, as well as execute code in the context of a Laravel application. The following examples showcase using the Tinker REPL environment to create a new user (lines starting with >>> are user input; lines starting with => are output):

1Psy Shell v0.7.2 (PHP 7.0.8 — cli) by Justin Hileman
2>>> $user = new App\User;
3=> App\User {#654}
4>>> $user->name = 'John Doe';
5=> "John Doe"
6>>> $user->email = 'example@example.com';
7=> "example@example.com"
8>>> $user->password = Hash::make('password');
9=> "$2y$10$4FuGuqTEMSvoTRCObRCi4OUeBz9Me/7XR7mpNNKpFhtEXT8NuqwZm"
10>>> $user;
11=> App\User {#654
12 name: "John Doe",
13 email: "example@example.com",
14 }
15>>> $user->save();
16=> true

In the previous example, the first thing that we did was create a new App\User instance and assign it to the $user variable. The $user variable persists throughout the Tinker session; this is why we are able to set the properties on it before calling its save() method. Every time we set a property value using Tinker, the assignment results will be displayed below. Similarly, each time a method is called the value returned by the method will be displayed.

The following example demonstrates retrieving a App\User instance from the database using Tinker:

1Psy Shell v0.7.2 (PHP 7.0.8 — cli) by Justin Hileman
2>>> $user = App\User::find(1);
3=> App\User {#667
4 id: "1",
5 name: "John Doe",
6 email: "example@example.com",
7 created_at: "2016-08-03 23:37:14",
8 updated_at: "2016-08-03 23:37:14",
9 }
10>>>

The JSON representation of the App\User Eloquent model is displayed as the result of the find method call. Remember that, by default, Eloquent models hide the password and remember_me fields when they are cast to JSON. However, these can easily be accessed directly from within a Tinker session:

1...
2
3>>> $user->password;
4=> "$2y$10$4FuGuqTEMSvoTRCObRCi4OUeBz9Me/7XR7mpNNKpFhtEXT8NuqwZm"
5>>>

Tinker allows you to write any code expression, as long as it is valid; this also means ensuring that the namespaces are correct when referencing any classes. Interestingly, the REPL behind Tinker allows the use of the use statement to import classes into scope. The following example session demonstrates this by importing the App\User model and referencing it throughout the session:

1Psy Shell v0.7.2 (PHP 7.0.8 — cli) by Justin Hileman
2>>> use App\User;
3=> null
4>>> factory(User::class, 5)->create();
5=> Illuminate\Database\Eloquent\Collection {#688
6 all: [
7 App\User {#684
8 name: "Ethyl Ratke",
9 email: "erica33@example.com",
10 updated_at: "2016-08-04 19:26:48",
11 created_at: "2016-08-04 19:26:48",
12 id: 27,
13 },
14 App\User {#682
15 name: "Jordyn Goodwin Sr.",
16 email: "nathen.bernier@example.com",
17 updated_at: "2016-08-04 19:26:48",
18 created_at: "2016-08-04 19:26:48",
19 id: 28,
20 },
21 App\User {#680
22 name: "Jameson Larkin",
23 email: "lynn99@example.org",
24 updated_at: "2016-08-04 19:26:48",
25 created_at: "2016-08-04 19:26:48",
26 id: 29,
27 },
28 App\User {#679
29 name: "Dr. Ronny Fay DVM",
30 email: "oberbrunner.corbin@example.net",
31 updated_at: "2016-08-04 19:26:48",
32 created_at: "2016-08-04 19:26:48",
33 id: 30,
34 },
35 App\User {#681
36 name: "Mr. Elbert Durgan",
37 email: "cleta.jenkins@example.com",
38 updated_at: "2016-08-04 19:26:48",
39 created_at: "2016-08-04 19:26:48",
40 id: 31,
41 },
42 ],
43 }
44>>> $user = User::find(30);
45=> App\User {#697
46 id: "30",
47 name: "Dr. Ronny Fay DVM",
48 email: "oberbrunner.corbin@example.net",
49 created_at: "2016-08-04 19:26:48",
50 updated_at: "2016-08-04 19:26:48",
51 }
52>>>

#Entering Multi-Line Code Statements

At times it is easier to enter arbitrary code that spans multiple lines. However, by default, pressing the Enter key will cause the Tinker REPL to read and evaluate the line that was entered. To get around this, end the first line with the \ character. This allow you to continue the expression input on multiple lines; each line that will be part of the input will be prefixed with .... The REPL will continue to accept multi-line input until a valid terminator is encountered or a parsing error occurs.

If the current line contains the beginning of a PHP statement, such as an incomplete function declaration, the Tinker REPL will automatically switch to the multi-line expression mode.

The example session demonstrates this approach to supplying input to the Tinker REPL:

1>>> function sayHello($name) {
2... return "Hello {$name}"; }
3=> null
4>>> sayHello("World")
5=> "Hello World"

In the previous example, we did not have to supply the \ character. The following example session uses the \ character to force the REPL into multi-line input mode:

1>>> function sayHello($name) {} \
2... function sayGoodBye($name) {}
3=> null
4>>>

#Tinker Commands

Like the Artisan command-line application, Tinker provides many numerous commands and utilities that simplify the process of debugging and executing code from the command-line. The following table lists all the commands that Tinker provides (these commands can be discovered within the Tinker REPL by issuing the help command):

Command Description Alias
help Show a list of commands. Type help [foo] for information about [foo]. ?
ls List local, instance or class variables, methods and constants. list, dir
dump Dump an object or primitive.
doc Read the documentation for an object, class, constant, method or property. rtfm, man
show Show the code for an object, class, constant, method or property.
wtf Show the backtrace of the most recent exception. last-exception, wtf?
whereami Show where you are in the code.
trace Show the current call stack.
throw-up Throw an exception out of the Psy Shell.
buffer Show (or clear) the contents of the code input buffer. buf
clear Clear the Psy Shell screen.
history Show the Psy Shell history. hist
exit End the current session and return to caller. quit, q
clear-compiled Remove the compiled class file.
down Put the application into maintenance mode.
env Display the current framework environment.
optimize Optimize the framework for better performance.
up Bring the application out of maintenance mode.
migrate Run the database migrations.
inspire Display an inspiring quote.

Just like when interacting with most command-line utilities, each of the commands allow you to view help about any given command. To do this within Tinker, simply issue the help command (or any of its aliases) followed by the name of the command you would like to learn more about.

The ordering of arguments is important when issuing commands within the Tinker REPL environment. For example, when using the Artisan command line application, retrieving help information is done by supplying the -h argument after the command name; i.e., php artisan migrate -h. Within the Tinker REPL environment, the help command is its own command and accepts the command to help with as its argument; i.e., ? buffer.

The following example session shows the help information for the clear command:

1>>> ? clear
2Usage:
3 clear
4
5Options:
6 --help (-h) Display this help message.
7
8Help:
9 Clear the Psy Shell screen.
10
11 Pro Tip: If your PHP has readline support, you should be able to use
12 ctrl+l too!
13
14>>>

Some absolutely amazing
people

The following amazing people help support this site and my open source projects ♥️
If you're interesting in supporting my work and want to show up on this list, check out my GitHub Sponsors Profile.