O Laravel oferece ferramentas poderosas para desenvolver APIs RESTful seguras e escaláveis. Este tutorial demonstra como implementar um sistema CRUD completo com autenticação JWT, combinando eficiência e segurança em aplicações modernas.

Configuração do Ambiente Laravel

Instale o Laravel através do Composer com o comando abaixo:

composer create-project --prefer-dist laravel/laravel api-crud-jwt
cd api-crud-jwt
php artisan serve

Configure seu arquivo .env com as credenciais do banco de dados:

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=laravel_api
DB_USERNAME=seu_usuario
DB_PASSWORD=sua_senha

Criando o Model e Migration

Gere o model Product com sua respectiva migration:

php artisan make:model Product -m

Defina a estrutura da tabela na migration criada:

id();
            $table->string(\'name\');
            $table->text(\'description\');
            $table->decimal(\'price\', 8, 2);
            $table->integer(\'stock\');
            $table->timestamps();
        });
    }

    public function down()
    {
        Schema::dropIfExists(\'products\');
    }
}

Execute a migration:

php artisan migrate

Configurando o Model Product

Atualize o model app/Models/Product.php:

 \'decimal:2\',
        \'stock\' => \'integer\'
    ];
}

Implementando Autenticação JWT

Instale o pacote JWT Auth:

composer require tymon/jwt-auth

Publique o arquivo de configuração:

php artisan vendor:publish --provider="Tymon\\JWTAuth\\Providers\\LaravelServiceProvider"
php artisan jwt:secret

Configure o model User para JWT em app/Models/User.php:

getKey();
    }

    public function getJWTCustomClaims()
    {
        return [];
    }
}

Criando o AuthController

Gere o controlador de autenticação:

php artisan make:controller AuthController

Implemente os métodos de login e registro:

all(), [
            \'name\' => \'required|string|max:255\',
            \'email\' => \'required|string|email|max:255|unique:users\',
            \'password\' => \'required|string|min:6|confirmed\',
        ]);

        if ($validator->fails()) {
            return response()->json($validator->errors(), 422);
        }

        $user = User::create([
            \'name\' => $request->name,
            \'email\' => $request->email,
            \'password\' => Hash::make($request->password),
        ]);

        $token = JWTAuth::fromUser($user);

        return response()->json([
            \'message\' => \'Usuário registrado com sucesso\',
            \'user\' => $user,
            \'token\' => $token
        ], 201);
    }

    public function login(Request $request)
    {
        $credentials = $request->only(\'email\', \'password\');

        if (!$token = JWTAuth::attempt($credentials)) {
            return response()->json([\'error\' => \'Credenciais inválidas\'], 401);
        }

        return response()->json([
            \'message\' => \'Login realizado com sucesso\',
            \'token\' => $token,
            \'user\' => auth()->user()
        ]);
    }

    public function logout()
    {
        JWTAuth::invalidate(JWTAuth::getToken());
        return response()->json([\'message\' => \'Logout realizado com sucesso\']);
    }
}

Desenvolvendo o ProductController

Crie o controlador para o CRUD de produtos:

php artisan make:controller ProductController --api

Implemente todos os métodos CRUD:

json([
            \'success\' => true,
            \'data\' => $products
        ]);
    }

    public function store(Request $request)
    {
        $validator = Validator::make($request->all(), [
            \'name\' => \'required|string|max:255\',
            \'description\' => \'required|string\',
            \'price\' => \'required|numeric|min:0\',
            \'stock\' => \'required|integer|min:0\'
        ]);

        if ($validator->fails()) {
            return response()->json([
                \'success\' => false,
                \'errors\' => $validator->errors()
            ], 422);
        }

        $product = Product::create($request->all());

        return response()->json([
            \'success\' => true,
            \'message\' => \'Produto criado com sucesso\',
            \'data\' => $product
        ], 201);
    }

    public function show($id)
    {
        $product = Product::find($id);

        if (!$product) {
            return response()->json([
                \'success\' => false,
                \'message\' => \'Produto não encontrado\'
            ], 404);
        }

        return response()->json([
            \'success\' => true,
            \'data\' => $product
        ]);
    }

    public function update(Request $request, $id)
    {
        $product = Product::find($id);

        if (!$product) {
            return response()->json([
                \'success\' => false,
                \'message\' => \'Produto não encontrado\'
            ], 404);
        }

        $validator = Validator::make($request->all(), [
            \'name\' => \'string|max:255\',
            \'description\' => \'string\',
            \'price\' => \'numeric|min:0\',
            \'stock\' => \'integer|min:0\'
        ]);

        if ($validator->fails()) {
            return response()->json([
                \'success\' => false,
                \'errors\' => $validator->errors()
            ], 422);
        }

        $product->update($request->all());

        return response()->json([
            \'success\' => true,
            \'message\' => \'Produto atualizado com sucesso\',
            \'data\' => $product
        ]);
    }

    public function destroy($id)
    {
        $product = Product::find($id);

        if (!$product) {
            return response()->json([
                \'success\' => false,
                \'message\' => \'Produto não encontrado\'
            ], 404);
        }

        $product->delete();

        return response()->json([
            \'success\' => true,
            \'message\' => \'Produto excluído com sucesso\'
        ]);
    }
}

Configurando as Rotas da API

Configure as rotas em routes/api.php:

group(function () {
    Route::post(\'/logout\', [AuthController::class, \'logout\']);
    Route::apiResource(\'/products\', ProductController::class);
});

Configuração do Middleware JWT

Configure o guard JWT em config/auth.php:

\'guards\' => [
    \'web\' => [
        \'driver\' => \'session\',
        \'provider\' => \'users\',
    ],
    \'api\' => [
        \'driver\' => \'jwt\',
        \'provider\' => \'users\',
    ],
],

Testando a API

Teste sua API usando ferramentas como Postman ou Insomnia. Para sistemas mais robustos de desenvolvimento web, considere implementar testes automatizados.

Método HTTPEndpointDescriçãoAutenticação
POST/api/registerRegistrar usuárioNão
POST/api/loginFazer loginNão
GET/api/productsListar produtosJWT
POST/api/productsCriar produtoJWT
GET/api/products/{id}Mostrar produtoJWT
PUT/api/products/{id}Atualizar produtoJWT
DELETE/api/products/{id}Excluir produtoJWT

Boas Práticas de Segurança

Para APIs em produção, implemente estas medidas de segurança:

  • Configure CORS adequadamente no arquivo config/cors.php
  • Use HTTPS em produção
  • Implemente rate limiting nas rotas da API
  • Valide todos os inputs do usuário
  • Configure logs de segurança para monitoramento

Para projetos que exigem alta disponibilidade, considere hospedar sua aplicação Laravel em um servidor VPS dedicado.

Tratamento de Erros Personalizado

Crie um handler de exceções personalizado em app/Exceptions/Handler.php para padronizar as respostas de erro da API:

public function render($request, Throwable $exception)
{
    if ($request->is(\'api/*\')) {
        if ($exception instanceof ModelNotFoundException) {
            return response()->json([
                \'success\' => false,
                \'message\' => \'Recurso não encontrado\'
            ], 404);
        }
    }
    
    return parent::render($request, $exception);
}

Este sistema CRUD com Laravel, APIs RESTful e JWT fornece uma base sólida para aplicações modernas, combinando performance, segurança e escalabilidade. A estrutura modular permite expansões futuras e manutenção eficiente.