This article is a guest post by Sam Ciaramilaro
Tinkerwell is an amazing tool by Beyond Code. Like many who use it, I find it an invaluable tool in my development toolbox. But, soon after I began using Tinkerwell, I discovered a little hidden gem.
Tinkerwell allows you to create "provisional" on-the-fly classes directly in the editor. For example:
// Within the Tinkerwell Editorclass StringFormatter{ public function format(string $string) { return strtolower($string); }} $formatter = new StringFormatter();$formatter->format('TACOS'); // Tinkerwell Output=> "tacos"
Pretty slick. But, not only can you create these classes in Tinkerwell, you can use them directly with your Laravel applications. For example, you can declare a class in Tinkerwell, instantiate it, and use that instance object as parameter or dependency in your Laravel application.
To illustrate this, let's say you have a service class that performs string formatting, which takes an instance of a FormatterInterface
in its constructor. Here's how the interface, the service class, and a concrete implementation of the interface might look like.
// Service classclass StringFormattingService{ private \App\Formatting\Formatter $formatter; public function __construct(Formatter $formatter) { $this->formatter = $formatter; } public function format(string $string): string { return $this->formatter->format($string); }} // Formatter interface.interface Formatter{ public function format(string $string): string;} // Concrete implementation of the Formatter interface.class LowercaseFormatter implements Formatter{ public function format(string $string): string { return strtolower($string); }} // AppServiceProvider: Bind the interface to the implementation.public function register(){ $this->app->bind(Formatter::class, App\Formatters\LowercaseFormatter::class);}
To see how this functionality works within our application, we can test it Tinkerwell.
// Tinkerwell Editor$formatterService = app()->make(App\Formatters\StringFormattingService::class);$formatterService->format('Tacos'); // Tinkerwell Output=>'tacos'
Now, let's see how we can test this new implementation of the Formatter
interface within Tinkerkwell. We'll create a provisional class that implements the Formatter
interface. Then, we'll instantiate the StringFormattingService
class, and pass in the new formatter into its constructor.
// Tinkerwell Editorclass UppercaseFormatter implements App\Formatters\Formatter{ public function format(string $string): string { return strtoupper($string); }} $formatter = new UppercaseFormatter();$formatterService = new App\Formatters\StringFormattingService($formatter);$formatterService->format('Tacos'); // Tinkerwell Output=>'TACOS'
Cool, right? We've just created a class outside of our application, and were then able to use it together with code from our Laravel application.
Now for the really interesting stuff. Not only can we manually inject our new class, but we can also override the existing interface binding in the Service Container from within Tinkerwell, replacing it with the new implementation.
// Tinkerwell Editorclass UppercaseFormatter implements App\Formatters\Formatter{ public function format(string $string): string { return strtoupper($string); }} // Bind the Formatter interface to the new class.app()->bind(App\Formatters\Formatter::class, UppercaseFormatter::class);$formatterService = app(App\Formatters\StringFormattingService::class);$formatterService->format('Tacos'); // Tinkerwell Output=>'TACOS'
This gives us the ability to interact with code and data on a remote server, without having to alter the codebase running on it. Imagine what possibilities this affords us?
Since we could interact with a remote server, we have the possibility of accessing and transforming that data via code, without ever having to make a change to the codebase!
Sometimes, the dataset we're testing with locally just doesn't match all the variety that exists in a production system. Let's say we have an Artisan command that generates a report, and this command has a dependency on our StringFormatterService
. If we needed to change how the report was formatted, we could easily create an different implementation of the Formatter implementation class in Tinkerwell that contains the desired changes, connect to the remote server, and bind this new class to the Service Container. We could then run the Artisan command from within Tinkerwell, and the report would now be using the new service. All without ever having to touch the existing codebase. Now, that's pretty powerful!
I'd like to say that I'm not advocating for or against running rogue code on a production server as a best practice, but I'm just pointing out that the possibility exists. As always, let best judgment prevail.
“The ability to SSH directly into a server and run diagnostics directly from Tinkerwell is insanely amazing! Can't imagine doing development without it at this point.”Jake Bennett
Director of Technology and Innovation
“Tinkerwell takes the guess work out of development. It’s one of the few apps that lives on my toolbar - I reach for it daily.”
Daniel Ferguson
CTO at Imperial Wealth
The must-have companion to your favorite IDE. Quickly iterate on PHP code within the context of your web application.
Buy now Learn more