Generating Vue Files With Artisan Command

In larger projects, often we find ourselves making new files – controllers, events, jobs and so on – as the project goes. For these classes, we have all the commands we need, however, if the project is front-end heavy we need to make the files manually. Let’s see how to make a generator command for our front-end files!

The Base Idea

We all know the commands that start with make. For example, php artisan make:event or php artisan make:model. It’s a huge help, that we can use a command that takes care of all the class generating tasks instead of us. Just imagine, what if we would need to make all the classes manually. It’s not only more energy consumption but there is a bigger change to make mistakes – like typos, miss imports and so on.

We know that we are covered on the back-end, but still, sometimes we need to work with front-end and JS heavy applications, that means we need to manually create JavaScript, CSS or Vue files. Laravel provides presets with various boilerplates, but when you are deeper in the project, you are alone.

So let’s move on, and take a look at how can we create an artisan command that uses the same make signature that we got used to and generates the files we need.

Creating the Stubs

Before we move on the command itself, we have to take a look at the skeleton of the generated files. These skeletons are the stubs. When we are generating the files the command grabs the stub’s content, replaces the placeholders and creating the final file with the proper content.

Let’s create a stubs folder in the app/Console directory. Here we can place our stubs for every generator command we have. For now, let’s create one file, called vue-template.stub. Here is how it looks:

<script>
    export default {
        data() {
            return {
                //
            };
        }
    }
</script>

<template>
    <!-- Your {Component} component's template -->
</template>
The HTML comment and the {Component} string are placed there only, to show how the replacement works with the command,

As you can see, this is typical .vue single file markup. After we generated our file, we will get this skeleton and we are ready to go.

The Generator Command

Now here is a tricky part, so pay attention. A normal command and a generator command have not the same markup. We will generate a normal command just to have the file in the right place, but after we will replace all its content based on Laravel’s other generator commands.

A generator command has to extend the Illuminate\Console\GeneratorCommand class. It comes with a different signature of the Illuminate\Console\Command class.

To make the command run php artisan make:command VueMakeCommand. Open the file and delete everything and insert the following code:

<?php

namespace App\Console\Commands;

use Illuminate\Console\GeneratorCommand;

class VueMakeCommand extends GeneratorCommand
{
    /**
     * The console command name.
     *
     * @var string
     */
    protected $name = 'make:vue-template';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Create a new Vue template';

    /**
     * The type of class being generated.
     *
     * @var string
     */
    protected $type = 'Vue template';

    /**
     * Get the stub file for the generator.
     *
     * @return string
     */
    protected function getStub()
    {
        return __DIR__ . '/../stubs/vue-template.stub';
    }

    /**
     * Determine if the class already exists.
     *
     * @param  string  $rawName
     * @return bool
     */
    protected function alreadyExists($rawName)
    {
        $name = class_basename(str_replace('\\', '/', $rawName));

        $path = "{$this->laravel['path']}/../resources/js/components/{$name}.vue";

        return file_exists($path);
    }

    /**
     * Replace the namespace for the given stub.
     *
     * @param  string  $stub
     * @param  string  $name
     * @return $this
     */
    protected function replaceNamespace(&$stub, $name)
    {
        $name = class_basename(str_replace('\\', '/', $name));

        $stub = str_replace('{Component}', $name, $stub);

        return $this;
    }

    /**
     * Get the destination class path.
     *
     * @param  string  $name
     * @return string
     */
    protected function getPath($name)
    {
        $name = class_basename(str_replace('\\', '/', $name));

        return "{$this->laravel['path']}/../resources/js/components/{$name}.vue";
    }
}

Since the generator command originally was made to create PHP files, the naming conventions are not so close to any JS relevant stuff, but still, it perfectly does the job.

Since Laravel will append the root namespace to the parameter we provided, we need to remove all the unrelevant strings. That’s why there is class_basename everywhere. The getStub() method provides the path to the stub file we created before. The alreadyExists() method checks if the file exists or not and if yes the command will return an error message (this is important not to override existing files). The replaceNamespace() method allows us to replace anything in our stub we want. This is very handy, especially if there are larger stubs as well. The getPath() provides to the generator the path and the file name to generate.

Generating Vue Templates

There is nothing left but to generate the templates with artisan. Let’s run the php artisan make:vue-template Form command. If it ran successfully, we can find a Form.vue file in the resources/js/components folder. Also in the template, we can see that in the comment the {Component} string was replaced to Form. From this point, we can work on our fresh Vue template.

This was a very basic example of the power of generating files in Laravel. Of course, you can modify this command as you wish. If you need to create CSS, JS or Blade templates, you can create a new generator command and a new stub and for the rest of the time, you can enjoy saving time.

Special thanks for the following recource(s): Icon made by Eucalyp from www.flaticon.com
Need a web developer? Maybe we can help, get in touch!