2

I came across this article on Spatie Actions https://freek.dev/1371-refactoring-to-actions and I would like to make a command to generate the files for me, similar how you can generate Model or livewire components etc.

php artisan make:action PublishPostAction Post

This is as far as I got

<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;

class GenerateActionTemplate extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'make:action {name} {model}';

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

    /**
     * Execute the console command.
     *
     * @return int
     */
    public function handle()
    {
        $name = $this->argument('name');
        $model = $this->argument('model');

        $fileContents = <<<'EOT'
        <?php

        namespace App\Actions;

        class PublishPostAction // name
        {
            private $post;

            public function execute(Post $post) // model
            {
                $this->post = $post;
            }

        }

        EOT;

        $this->info($name . 'has been created successfully!');
    }
}
  • How would I do the logic, so if I do like make:action post.PublishPostAction would create a new folder called post in App\Actions\Post\
  • In the EOT how would I pass in the variables?

Any help or link to an example would be great! I have looked through a few tutorials and was able to scrap this up and laravel docs don't really show any example to generate a new file.

2
  • btw there is a GeneratorCommand abstract class that the commands that generate files like Models and Controllers use, Illuminate\Console\GeneratorCommand ... for the file content you can use a 'stub' file that allows for placeholders Commented Sep 9, 2022 at 1:26
  • thank you for this, im a bit novice so will take big to figure out what this means but I'm on the right path at least haha Commented Sep 9, 2022 at 1:28

1 Answer 1

2

Here is the full code to get this working. You need to create 2 files.

// action.stub

<?php

namespace {{ namespace }};

use {{ namespacedModel }};

class {{ class }}
{
    private ${{ modelVariable }};

    public function execute({{ m }} ${{ modelVariable }})
    {
        $this->{{ modelVariable }} = ${{ modelVariable }};
    }
}

// makeAction.php
<?php

namespace App\Console\Commands;

use Illuminate\Console\GeneratorCommand;
use InvalidArgumentException;
use Symfony\Component\Console\Input\InputOption;

class makeAction extends GeneratorCommand
{
    protected $signature = 'make:action {name} {--m=}';

    protected $description = 'Create action file';

    protected $type = 'Action file';

    protected function getNameInput()
    {
        return str_replace('.', '/', trim($this->argument('name')));
    }
    /**
     * Build the class with the given name.
     *
     * @param  string  $name
     * @return string
     */
    protected function buildClass($name)
    {
        $stub = parent::buildClass($name);

        $model = $this->option('m');

        return $model ? $this->replaceModel($stub, $model) : $stub;
    }

    /**
     * Replace the model for the given stub.
     *
     * @param  string  $stub
     * @param  string  $model
     * @return string
     */
    protected function replaceModel($stub, $model)
    {
        $modelClass = $this->parseModel($model);

        $replace = [
            '{{ namespacedModel }}' => $modelClass,
            '{{ m }}' => class_basename($modelClass),
            '{{ modelVariable }}' => lcfirst(class_basename($modelClass)),
        ];

        return str_replace(
            array_keys($replace), array_values($replace), $stub
        );
    }

    /**
     * Get the fully-qualified model class name.
     *
     * @param  string  $model
     * @return string
     *
     * @throws \InvalidArgumentException
     */
    protected function parseModel($model)
    {
        if (preg_match('([^A-Za-z0-9_/\\\\])', $model)) {
            throw new InvalidArgumentException('Model name contains invalid characters.');
        }

        return $this->qualifyModel($model);
    }

    /**
     * Get the stub file for the generator.
     *
     * @return string
     */
    protected function getStub()
    {
        return  app_path().'/Console/Commands/Stubs/action.stub';
    }



    /**
     * Get the default namespace for the class.
     *
     * @param  string  $rootNamespace
     * @return string
     */
    protected function getDefaultNamespace($rootNamespace)
    {
        return $rootNamespace.'\Actions';
    }

    /**
     * Get the console command arguments.
     *
     * @return array
     */
    protected function getOptions()
    {
        return [
            ['model', 'm', InputOption::VALUE_OPTIONAL, 'Model'],
        ];
    }
}


Command to run

PHP artisan make:action task.AddTaskAction --m=Task

it will create the following file

<?php

namespace App\Actions\task;

use App\Models\Task;

class AddTaskAction
{
    private $task;

    public function execute(Task $task)
    {
        $this->task = $task;
    }
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.