DEV Community

Cover image for 📦 Laravel Tasks: a simple package to trigger use cases with validation and authorization
Víctor Falcón
Víctor Falcón

Posted on

📦 Laravel Tasks: a simple package to trigger use cases with validation and authorization

With this package 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 🇪🇸)

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:

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;
    }
}
Enter fullscreen mode Exit fullscreen mode

And then trigger it from our controller:

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

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.

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);
    }
}
Enter fullscreen mode Exit fullscreen mode

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:

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.'
        ]);
    }
Enter fullscreen mode Exit fullscreen mode

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 logo victor-falcon / laravel-task

A simple way to trigger tasks in a clean and simple way

Laravel Task

GitHub Workflow Status Packagist Packagist Packagist

🇪🇸 Documentación en español aqui

Table of content:

Installation

Install via composer

# PHP >= 8
composer require victor-falcon/laravel-task
# Previous PHP versions
composer require victor-falcon/laravel-task:1.1.4
Enter fullscreen mode Exit fullscreen mode

Usage

1. Basic usage

Create a simple task using:

artisan task:make Shop/CreateUserShop
Enter fullscreen mode Exit fullscreen mode

You can pass Shop/CreateUserShop to create the class in a sub-folder or just the task name. The default path is app/Tasks.

<?php

declare(strict_types=1);

namespace App\Tasks\Shop;

use VictorFalcon\LaravelTask\Task;
use VictorFalcon\LaravelTask\Taskable;

final class CreateUserShop implements Task
{
    use Taskable;

    private User $user;

    public function __construct(User $user)
    {
        $this->user = $user;
    }

    public function handle(ShopCreator $creator): Shop
    {
        // Create your shop
    }
}
Enter fullscreen mode Exit fullscreen mode

and trigger…

Top comments (0)