Tuesday, May 16, 2023
HomePHPSupercharging Your Artisan Instructions With Termwind

Supercharging Your Artisan Instructions With Termwind

In case you’re constructing a Laravel utility, package deal, or CLI (command-line interface) utility, you may possible create your individual customized Artisan instructions at some stage. When creating these instructions, you would possibly wish to make the output distinctive and stand out from the remainder of the console output. To do that, you possibly can the superior Termwind package deal.

On this article, we’re going to try what Termwind is, how one can set up it, and how one can use it in your individual Artisan instructions. We’ll then replace an outdated instance Artisan command step-by-step to make use of Termwind and see the way it improves the output.

What’s Termwind?

Termwind is a PHP package deal created and maintained by Nuno Maduro (and different superior contributors corresponding to Francisco Madeira) that means that you can use Tailwind-like CSS courses in your PHP code so as to add styling to your CLI output.

It is an important instrument to make use of if you wish to make your instructions’ output look distinctive and stand out from the group. So it’s extremely useful to make use of in the event you’re constructing a CLI utility or a Laravel package deal that gives any Artisan instructions.

It gives the power so that you can construct your output utilizing HTML and Tailwind-like courses corresponding to text-blue-500, flex and space-x-1. You possibly can take a look at a full record of the courses out there within the package deal’s documentation.


Set up

To get began with utilizing Termwind in your Laravel apps, you may want to put in it utilizing Composer by operating the next command:

1composer require nunomaduro/termwind

That is it! Termwind is now put in and able to go.

Displaying Output Utilizing Inline HTML

Now that we’ve got Termwind put in, let’s check out how we will use it to render some output to the CLI.

The quickest technique to render the output is to cross some HTML as a string on to the package deal’s render operate.

To present this a little bit of context, let’s check out a easy instance. We’ll think about that we’ve got an Artisan command that we will use to output some statistics about our Laravel utility. For the sake of this text, we’ll be utilizing hardcoded statistics simply so we will focus purely on Termwind.

So let’s check out the command:

1namespace AppConsoleCommands;


3use IlluminateConsoleCommand;

4use operate Termwind{render};


6class AppStats extends Command


8 protected $signature = 'app:stats';


10 protected $description = 'Show the applying stats';


12 public operate deal with(): int

13 {

14 render(<<<'HTML'

15 <div class="mx-2 my-1">

16 <div class="space-x-1">

17 <span class="px-1 bg-blue-500 text-white">Utility Data</span>

18 </div>


20 <div class="mt-1">

21 <span class="font-bold text-green">Totals</span>


23 <div class="flex space-x-1">

24 <span class="font-bold">Customers</span>

25 <span class="flex-1 content-repeat-[.] text-gray"></span>

26 <span class="font-bold text-green">150</span>

27 </div>


29 <div class="flex space-x-1">

30 <span class="font-bold">Posts</span>

31 <span class="flex-1 content-repeat-[.] text-gray"></span>

32 <span class="font-bold text-green">200</span>

33 </div>


35 <div class="flex space-x-1">

36 <span class="font-bold">Feedback</span>

37 <span class="flex-1 content-repeat-[.] text-gray"></span>

38 <span class="font-bold text-green">175</span>

39 </div>

40 </div>


42 <div class="mt-1">

43 <span class="font-bold text-green">Well being Checks</span>


45 <div class="flex space-x-1">

46 <span class="font-bold">Mailcoach</span>

47 <i class="text-gray">Publication</i>

48 <span class="flex-1 content-repeat-[.] text-gray"></span>

49 <span class="font-bold text-green">CONNECTED</span>

50 </div>


52 <div class="flex space-x-1">

53 <span class="font-bold">Vonage</span>

54 <i class="text-gray">SMS</i>

55 <span class="flex-1 content-repeat-[.] text-gray"></span>

56 <span class="font-bold text-red">ERROR!</span>

57 </div>

58 </div>

59 </div>

60 HTML);


62 return self::SUCCESS;

63 }


The above command will output the next to the CLI:

As you possibly can see, we will generate some actually cool output utilizing Termwind. However having the HTML instantly within the command class can change into messy in a short time. It isn’t very readable or maintainable. For instance, if we wished to make use of the identical kinds in different instructions, we would probably be duplicating lots of the shared HTML.

It’s price noting, although, that for smaller quantities of output, this method could be completely superb. It is simply once you begin to have lots of output that it could possibly change into a bit tedious to keep up.

Termwind’s type operate can assist us to group kinds collectively in order that we will reuse them in a number of locations. Nevertheless, this does not essentially clear up the difficulty of the particular HTML that builds the construction of the output. I’d advocate trying out the type operate within the documentation to be taught extra about how you need to use it to make your upkeep less complicated.

Displaying Output Utilizing a View

Now that we have seen how one can output some HTML on to the CLI, let’s check out how we will use a Blade view to render the output. I desire utilizing this method because it retains the HTML separate from the command class and makes it simpler to keep up and reuse throughout completely different instructions.

To start out, let’s create a brand new cli listing in our tasks sources/views listing. We’ll retailer all our CLI-specific views right here.

We’ll then create a brand new app-stats.blade.php view within the cli listing. This would be the view that we’ll use to render the output for our app:stats command, and it’ll comprise the HTML from our earlier instance (all the things between <<<'HTML' and HTML).

Now that we’ve got the HTML within the Blade view, we will replace our command class to make use of it. We’ll do that by utilizing the view helper operate to render the view and cross the output of it to Termwind’s render operate:

1namespace AppConsoleCommands;


3use IlluminateConsoleCommand;

4use operate Termwind{render};


6class AppStats extends Command


8 protected $signature = 'app:stats';


10 protected $description = 'Show the applying stats';


12 public operate deal with(): int

13 {

14 render(view('cli.app-stats'));


16 return self::SUCCESS;

17 }

As you possibly can see, this has made the command class a lot simpler to grasp and keep. We will now give attention to the logic of the command and never have to fret concerning the HTML cluttering this class.

An enormous advantage of utilizing this method is that it additionally permits us to make use of Blade parts to make our output much more reusable. We will create a element for every of the completely different sections of the output after which use them in our view.

Let’s check out how we will use some Blade parts to enhance our command’s maintainability.

We’ll begin by creating a brand new parts/cli listing in our sources/views listing. Just like our sources/views/cli listing, that is the place we’ll hold all our CLI-specific Blade parts.

We will establish two most important elements of our command’s output that could possibly be cut up into parts in our instance above:

  1. The totals
  2. The well being checks

So we’ll create a element for every of those. Please keep in mind although, you possibly can create as few or as many parts as you would like to suit your undertaking’s wants.

Let’s begin by creating a brand new totals.blade.php element within the sources/views/parts/cli listing. This element can be used to render the totals for every statistic that we’ve got.


2 'title',

3 'value',



6<div class="flex space-x-1">

7 <span class="font-bold">{{ $title }}</span>

8 <span class="flex-1 content-repeat-[.] text-gray"></span>

9 <span class="font-bold text-green">{{ $worth }}</span>


As you possibly can see, this element could be very easy and has 2 completely different properties outlined utilizing the @props Blade directive. It accepts two properties, title and worth. This can be a good way to make sure that we do not overlook to cross any required properties to the element.

We will now additionally create a brand new connection.blade.php element within the sources/views/parts/cli listing:


2 'title',

3 'subText',

4 'connected' => false,



7<div class="flex space-x-1">

8 <span class="font-bold">{{ $title }}</span>

9 <i class="text-gray">{{ $subText }}</i>

10 <span class="flex-1 content-repeat-[.] text-gray"></span>


12 @if($linked)

13 <span class="font-bold text-green">CONNECTED</span>

14 @else

15 <span class="font-bold text-red">ERROR!</span>

16 @endif


You will have seen that the element has 3 completely different properties outlined utilizing the @props Blade directive. This enforces that we should cross a title property, subText property, and an optionally available linked property every time we use the element.

As we will see from our instance earlier, if the linked property is ready to true, the element will output the CONNECTED textual content in inexperienced. In any other case, it can output the ERROR! textual content in purple.

Now that we’ve got the parts created and prepared, we will convert our sources/views/cli/app-stats.blade.php view to make use of them:

1<div class="mx-2 my-1">

2 <div class="space-x-1">

3 <span class="px-1 bg-blue-500 text-white">Utility Data</span>

4 </div>


6 <div class="mt-1">

7 <span class="font-bold text-green">Totals</span>


9 <x-cli.stat title="Customers" worth="150" />

10 <x-cli.stat title="Posts" worth="200" />

11 <x-cli.stat title="Feedback" worth="175" />

12 </div>


14 <div class="mt-1">

15 <span class="font-bold text-green">Well being Checks</span>


17 <x-cli.connection title="Mailcoach" subText="Publication" :linked="true" />

18 <x-cli.connection title="Vonage" subText="SMS" :linked="false" />

19 </div>


As you possibly can see, the HTML is now a lot simpler to learn and perceive. We have managed to cut back the quantity of duplicated HTML by calling the parts utilizing <x-cli.stat ... /> and <x-cli.connection ... /> Blade syntax. One factor that I like about this method is that as a result of we will use Blade, it makes constructing CLI outputs really feel similar to constructing net views.

Changing an Present Command

Now that we have seen how we will output HTML to the CLI utilizing Termwind, let’s briefly take a look at how we will convert an current command to make use of Termwind.

Lets say that we’ve got an Artisan command that does the next:

  • Asks the consumer for a search time period.
  • Searches the database for any customers which have an e-mail deal with that accommodates the search time period.
  • Outputs the outcomes to the CLI.

That is solely a easy instance however ought to give us a great likelihood to spotlight a number of of the options that Termwind gives. For the sake of the instance, we additionally will not be masking how we search the database for the customers, as this isn’t the main focus of this text. However we will assume that the searchUsers technique within the instance beneath will return a Assortment of Consumer fashions.

Our current command would possibly look one thing like so:

1namespace AppConsoleCommands;


3use AppModelsUser;

4use IlluminateConsoleCommand;


6ultimate class UsersSearch extends Command


8 protected $signature = 'customers:search';


10 protected $description = 'Seek for customers within the system';


12 public operate deal with(): int

13 {

14 $searchTerm = $this->ask('Search time period: ');


16 $customers = $this->searchUsers($searchTerm);


18 $rows = $customers->map(fn (Consumer $consumer): array => [

19 $user->name,

20 $user->email,

21 $user->email_verified_at ?? 'No!',

22 ])->all();


24 $this->information('Discovered '.depend($customers).' customers');

25 $this->desk(['Name', 'Email', 'Approved'], $rows);


27 return self::SUCCESS;

28 }


The command above would supply the next output:

If we wished to replace the command to make use of Termwind, our class could seem like so:

1namespace AppConsoleCommands;


3use AppModelsUser;

4use IlluminateConsoleCommand;

5use operate Termwind{ask, render};


7ultimate class UsersSearch extends Command


9 protected $signature = 'customers:search';


11 protected $description = 'Seek for customers within the system';


13 public operate deal with(): int

14 {

15 $searchTerm = ask(<<<HTML

16 <span class="mt-1 ml-2 mr-1 bg-green px-1 text-black">

17 Search time period:

18 </span>

19 HTML);


21 $customers = $this->searchUsers($searchTerm);


23 render(view('cli.user-search', [

24 'users' => $users,

25 ]));


27 return self::SUCCESS;

28 }


Let’s check out what’s modified.

As you might have seen, we’ve got changed the $this->ask name with Termwind’s ask operate. It will present us with an analogous expertise to the prevailing command, however with the additional advantage of with the ability to use Termwind’s styling.

We’ve additionally changed the $this->information and $this->desk calls by transferring the remainder of the command’s output to a sources/views/cli/user-search.blade.php Blade view (like we lined earlier on this article). As we will see, we have handed the $customers assortment to the view in the very same means that we may cross information to an internet view. The Blade view seems like so:

1<div class="m-1">

2 <div class="text-right mb-1 w-full">

3 <span class="text-indigo-500">Discovered [<b>{{ $users->count() }}</b>] customers</span>

4 </div>


6 @foreach($customers as $consumer)

7 <div>

8 <div class="flex space-x-1">

9 <span class="font-bold">{{ $user->identify }}</span>

10 <span class="text-gray">[{{ $user->email }}]</span>

11 <span class="flex-1 content-repeat-[.] text-gray"></span>

12 <span class="text-gray">Accredited:</span>


14 @if($user->email_verified_at)

15 <span class="font-bold text-green">{{ $user->email_verified_at }}</span>

16 @else

17 <span class="font-bold text-red">NO!</span>

18 @endif

19 </div>

20 </div>

21 @endforeach


Within the Blade file, we’re displaying the entire variety of customers discovered, then looping by the customers Assortment handed to the view and outputting the customers’ names, emails, and whether or not they have been authorised.

On account of making these adjustments, the command now outputs the next:

We’ve now efficiently transformed the Artisan command to make use of Termwind!


Hopefully, this text ought to have given you an summary of what Termwind is and the way you need to use it to construct superior CLI outputs to your Artisan instructions. You need to now be capable of take your current instructions and convert them to make use of Termwind, and even begin constructing new instructions from scratch.

If you wish to learn extra into Termwind, you possibly can take a look at the documentation on GitHub.


Most Popular

Recent Comments