Package Artisan commands in 5 minutes
Tags: laravel, php, phar, artisan
Published: 2021-04-16 11:12:14

---
title: Package Artisan commands in 5 minutes
published: true
description: How to make a phar package of an Artisan command
tags: Laravel,PHP,phar,Artisan
//cover_image: https://direct_url_to_image.jpg
---

A while ago, I wrote a [Laravel command that validates Blade templates](https://github.com/bdelespierre/laravel-blade-linter) in order to become part of my continuous integration pipeline.

It just compiles the given Blade templates and then uses the PHP internal linter to validate them.

Yesterday, [someone just asked me](https://github.com/bdelespierre/laravel-blade-linter/issues/7) if I planned to distribute it as a standalone phar archive. 

I thought it would be interesting so here's how I did it.

## First, make a standalone executable

Laravel Blade Linter is distributed as a Laravel package and is intended to be run as follow:

```bash
php artisan blade:lint <files>
```

Since it's an Artisan command, it cannot run outside of a Laravel project...

**Or can it?**

Turns out Artisan commands are built on top of Symfony console, so you can start them like this:

```php
// create the Symfony console application
$application = new Application();
$application->add(new BladeLinterCommand);
$application->run();
```

But the command leverage Laravel's services, so we need to provide them to it:

```php
// create an empty container
$laravel = new Container();

$laravel['config'] = fn() => new Config([
    // use current directory as view path
    'view.paths' => getcwd(),

    // send compiled views to /tmp
    'view.compiled' => sys_get_temp_dir(),
]);

// register services the command needs
(new FilesystemServiceProvider($laravel))->register();
(new ViewServiceProvider($laravel))->register();

// set the container so the Config::get calls resolve
Facade::setFacadeApplication($laravel);

// prepare the command
$command = new BladeLinterCommand();
$command->setLaravel($laravel);
```

And now it runs properly inside its Symfony application shell!

```bash
# now the command can run outside of Laravel!
bin/blade-linter <files>
```

The final script is available [here](https://github.com/bdelespierre/laravel-blade-linter/blob/master/bin/blade-linter).

## Time to package it

Building a phar archive is easier than I thought it would be. All you need is [phar-composer](https://github.com/clue/phar-composer).

```bash
# install phar-composer globally
composer global require clue/phar-composer
```

Then register the executable we made above in `composer.json`:

```json
{
    "bin": [
        "bin/blade-linter"
    ]
}
```

Now we can build the phar:

```bash
phar-composer build ./
```

The result is an executable archive that can be distributed as a standalone application.

```bash
$ laravel-blade-linter.phar lint tests/views/
PHP Parse error:  syntax error, unexpected ')' in tests/views/invalid.blade.php on line 1
```

And voilà

---

Don't forget to leave a like and tell me in the comments what you think of this article.

---

From the same author:

- [PHPUnit from scratch in 5 minutes](https://dev.to/bdelespierre/phpunit-from-scratch-in-5-minutes-48fa)
- [How to setup Git commit hooks for PHP](https://dev.to/bdelespierre/how-to-setup-git-commit-hooks-for-php-42d1)
- [How to list files recursively in a directory with PHP iterators](https://dev.to/bdelespierre/how-to-list-files-recursively-in-a-directory-with-php-iterators-5c0m)