📦 Laravel Tasks: a simple package to trigger use cases with validation and authorization
Published: 2021-04-07 18:51:33

With [this package](https://github.com/victor-falcon/laravel-task) you can trigger use cases or tasks with his own validation and authorization, so you can use them in controllers, commands or wherever you want.

## Video about Laravel Tasks (in Spanish 🇪🇸)
{% youtube g3KeId4alVs %}

## Basic example in a controller
Imagine that you have and endpoint to update product information. Without this package you should make something like:

1. Validating the request object to check it has expecting params.
2. Send this params to a desire service with the current logged-in user to check that the user is the owner of the products and, if it's, update the desire product.
3. Return a response in JSON.

With this package we just need to create a task like this:

```php
final class UpdateProduct extends Task
{
    use Taskable;

    private $product;

    public function __construct(Product $product)
    {
        $this->product = $product;
    }

    public function rules(): array
    {
        return [
            'title' => 'required|string|min:6',
            'content' => 'required|string|min:240',
        ];
    }

    public function authorize(): bool
    {
        return $this->user()->can('update', $this->product);
    }

    public function handle(): Post
    {
        $this->product->update($this->data);

        return $this->product;
    }
}
```

And then trigger it from our controller:

```php
class ProductPostController extends Controller
{
    public function __invoke(Product $product, Request $request): Response
    {
        return UpdateProduct::trigger($product)
                ->withValid($request->all())
                ->result();
    }
}
```

Just doing we are validating, authorizing the user and returning the updated `Product`.

---

As you can see it's really easy and simple to create and trigger tasks wherever you want. You can also trigger this same task in a command, for example, and it will work in the same exact way.

## Testing a task

Also, this package it's created with testing in mind, so you can feature testing each task and ensure it's working as you expected.

This, for example, it's a simple test to check that our `UpdateProduct` task is working as we want.

```php
class ProductUpdateTest extends TestCase
{
    use DatabaseMigrations;

    public function test_it_updates_expected_product(): void
    {
        $user = $this->withAUser();
        $product = $this->withAProductForUser($user);

        $data = [
            'title' => 'New title',
            'content' => 'Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum '
                .'has been the industry\'s standard dummy text ever since the 1500s, when an unknown printer took '
                .'a galley of type and scrambled it to make a type specimen book.'
        ];
        UpdateProduct::trigger($product)->by($user)->withValid($data);

        $this->assertDatabaseHas('product', $data);
    }
}
```

Also, to check that we are returning a valid expection if the current user it's not the owner of the product we are trying to update we can write a simple test like this one:

```php
public function test_that_you_can_not_edit_a_product_that_you_dont_own(): void
    {
        $user = $this->withAUser();
        $product = $this->withAProductForUser($user);
        $randomUser = $this->withAUser();

        $this->expectException(AuthorizationException::class);

        Update::trigger($product)->by($randomUser)->withValid([
            'title' => 'New title',
            'content' => 'Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum '
                .'has been the industry\'s standard dummy text ever since the 1500s, when an unknown printer took '
                .'a galley of type and scrambled it to make a type specimen book.'
        ]);
    }
```

As you see each task is really simple to test. With simple methods like `by()` you can pass the user that is executing the task if you want to override the log-in one and test a different case.

## Useful commands

This package comes with two commands that will be really helpful when you are working with it.

With `artisan task:make AnyTaskName` you can create a new task inside the default folder `app/Tasks`.

Also, with `artisan task:ide-help` you can generate a helper file for your IDE, so it will help you to fill methods and get responses types.

You also can publish the configuration file and customize some things like the default folder with `artisan vendor:pubsh --tag=laravel-task`.

## Official documentation

You can read full package documentation in GitHub.

{% github victor-falcon/laravel-task %}