EDDYMENS

Published a year ago

How To Refresh A Laravel 10 Tinker Session

Table of contents

You may have run into the annoying situation of needing to exit and restart your Tinker session each time you modify your code.

In this walkthrough we will look at one way you can easily refresh your Tinker session by using the script below.

01: <?php 02: 03: use Illuminate\Support\Facades\Process; 04: 05: $__tinkerModeDefinedVars__ = get_defined_vars(); 06: 07: $_reload = function ($lineStart = null, $endLine = null) use ($__tinkerModeDefinedVars__) { 08: 09: $histFile = '.__tinkerMode__history.php'; //stores executable history 10: 11: $argsIsSet = ($lineStart !== null && $endLine !== null); 12: 13: if ($argsIsSet) { 14: $oldShell = $__tinkerModeDefinedVars__['__psysh__']; 15: $oldShell->runCommand("hist --show $lineStart..$endLine --save $histFile"); //get history from old shell 16: 17: //replace old executable history 18: $rawHistory = file_get_contents($histFile); 19: $formattedHistory = str_replace("\n", ';', $rawHistory); 20: file_put_contents($histFile, '<?php ' . $formattedHistory); 21: } 22: 23: $tinkerMod = __DIR__ . '/tinkerMod.php'; 24: $histFile = (($argsIsSet) ? $histFile : ''); 25: Process::forever()->tty()->run("clear && php artisan tinker $tinkerMod $histFile"); //start a new shell 26: };

View all source [↗]

How to use

  • Include the tinkerMod.php file when starting your session i.e.: php artisan tinker tinkerMod.php.
  • To restart your session, call on the $_reload() function.

Re-running specific lines

  • Once your session is loaded with tinkerMod.php type out the history or hist command to get the history of everything your typed out.
  • Note the start and end line numbers you would like to run.
  • You can now pass this into the reload function to reload your session and replay the desired history i.e.: $_reload(3,8).
  • You might want to clear your history from time to time (hist --clear) to make it easy to search through your history log.
  • You might want to add tinkerMod.php, .tinkerModehistory.php to your .gitignore file if you do not want to commit them as part of your project.
  • The current implementation doesn't handle multiline code very well. Thus if you copy-pasted code into your Tinker session, the script is not able to handle the replay very well.

Example of copy-pasted codeTinker multiline copy+paste [→]

Why the reload problem remains largely unsolved

Starting a new shell within the current shell giving your the reload effect is the easiest part.

The hardest part has to do with the things you create before and after you start that session.

Let's say you are provided with the ideal Tinker session. It automatically reloads when you make changes to your code.

So say you created a class then play with it within Tinker, and you go like oh I should update one of the methods within that class to now return an array instead of a boolean.

You make that change and reload the session, sure, from now on every instance of that class you create will return an array but what about the earlier instance that returns a boolean? Does some code depend on it? If you try using it, it might lead to undesired and most likely confusing results.

There is a quick fix though, which is to instantiate all your old code, this works.

One of the maintainers of the Psysh [↗] (the library Tinker runs on top of) talks about the gymnastics that will be required to go around this in a thread [↗] on GitHub.

Code walkthrough

The script is set to achieve two main goals:

Start a new session

A new Tinker session when the $_reload function is called without parameters. It achieves this using the Laravel Process [↗] class on line 25. It clears the screen and then starts a new Tinker session whiles loading up tinkerMod.php in the process so you can keep reloading when you need to.

Rerun code

When a start and end line is provided to the $_reload function. The function fetches an instance of the old shell session on line 14 i.e.: $__tinkerModeDefinedVars__['__psysh__']; It then runs the hist --show x..y --save history.php command (line: 15) to store the history you will like to run to a PHP file. This is further cleaned up to make it executable by appending a < ?php at the beginning of the file and ; to terminate each line.

Once this is done the file is loaded up and executed during the new shell creation on line 25.

References

Here is another article you might like 😊 How to remove new (untracked) files from a git repo