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.
Utilization
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;
2Â
3use IlluminateConsoleCommand;
4use operate Termwind{render};
5Â
6class AppStats extends Command
7{
8 protected $signature = 'app:stats';
9Â
10 protected $description = 'Show the applying stats';
11Â
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>
19Â
20 <div class="mt-1">
21 <span class="font-bold text-green">Totals</span>
22Â
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>
28Â
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>
34Â
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>
41Â
42 <div class="mt-1">
43 <span class="font-bold text-green">Well being Checks</span>
44Â
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>
51Â
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);
61Â
62 return self::SUCCESS;
63 }
64}
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;
2Â
3use IlluminateConsoleCommand;
4use operate Termwind{render};
5Â
6class AppStats extends Command
7{
8 protected $signature = 'app:stats';
9Â
10 protected $description = 'Show the applying stats';
11Â
12 public operate deal with(): int
13 {
14 render(view('cli.app-stats'));
15Â
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:
- The totals
- 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.
1@props([
2 'title',
3 'value',
4])
5Â
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>
10</div>
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:
1@props([
2 'title',
3 'subText',
4 'connected' => false,
5])
6Â
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>
11Â
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
17</div>
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>
5Â
6 <div class="mt-1">
7 <span class="font-bold text-green">Totals</span>
8Â
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>
13Â
14 <div class="mt-1">
15 <span class="font-bold text-green">Well being Checks</span>
16Â
17 <x-cli.connection title="Mailcoach" subText="Publication" :linked="true" />
18 <x-cli.connection title="Vonage" subText="SMS" :linked="false" />
19 </div>
20</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;
2Â
3use AppModelsUser;
4use IlluminateConsoleCommand;
5Â
6ultimate class UsersSearch extends Command
7{
8 protected $signature = 'customers:search';
9Â
10 protected $description = 'Seek for customers within the system';
11Â
12 public operate deal with(): int
13 {
14 $searchTerm = $this->ask('Search time period: ');
15Â
16 $customers = $this->searchUsers($searchTerm);
17Â
18 $rows = $customers->map(fn (Consumer $consumer): array => [
19 $user->name,
20 $user->email,
21 $user->email_verified_at ?? 'No!',
22 ])->all();
23Â
24 $this->information('Discovered '.depend($customers).' customers');
25 $this->desk(['Name', 'Email', 'Approved'], $rows);
26Â
27 return self::SUCCESS;
28 }
29}
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;
2Â
3use AppModelsUser;
4use IlluminateConsoleCommand;
5use operate Termwind{ask, render};
6Â
7ultimate class UsersSearch extends Command
8{
9 protected $signature = 'customers:search';
10Â
11 protected $description = 'Seek for customers within the system';
12Â
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);
20Â
21 $customers = $this->searchUsers($searchTerm);
22Â
23 render(view('cli.user-search', [
24 'users' => $users,
25 ]));
26Â
27 return self::SUCCESS;
28 }
29}
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>
5Â
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>
13Â
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
22</div>
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!
Conclusion
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.