PHPackages                             tjdft/laravel - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Framework](/categories/framework)
4. /
5. tjdft/laravel

ActiveLibrary[Framework](/categories/framework)

tjdft/laravel
=============

Pacote unificado para desenvolvimento de aplicações Laravel no TJDFT.

3.0.1(yesterday)0261↓73.3%MITPHPCI passing

Since Oct 3Pushed yesterdayCompare

[ Source](https://github.com/tjdft/laravel)[ Packagist](https://packagist.org/packages/tjdft/laravel)[ RSS](/packages/tjdft-laravel/feed)WikiDiscussions main Synced yesterday

READMEChangelog (10)Dependencies (47)Versions (49)Used By (0)

[![](logo.png)](logo.png)

 [ ![](https://camo.githubusercontent.com/c039534acbbb6d930f60cb7ddd7a610bf34f8efa1fe8ec4dd734d729051e636f/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f746a6466742f6c61726176656c3f63616368655365636f6e64733d3630) ](https://packagist.org/packages/tjdft/laravel) [ ![](https://camo.githubusercontent.com/a2c8a8ca76c48248f2d11fb7628a2cb5d779c091fca991fa7b28a41fb66cf441/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f746a6466742f6c61726176656c3f6c6162656c3d737461626c6526636f6c6f723d626c75652663616368655365636f6e64733d3630) ](https://packagist.org/packages/tjdft/laravel) [ ![](https://camo.githubusercontent.com/147ae7d3b4c20f9f5495d256efc314087163469cb11feb811b4f49f74a46374b/68747470733a2f2f636f6465636f762e696f2f67682f746a6466742f6c61726176656c2f67726170682f62616467652e7376673f746f6b656e3d58513739375744455041) ](https://codecov.io/gh/tjdft/laravel) [ ![](https://camo.githubusercontent.com/e8091f826d2eb2d902abac6385fde96da2814ce60ae48fcf6c575898f710658c/68747470733a2f2f706f7365722e707567782e6f72672f746a6466742f6c61726176656c2f6c6963656e73652e737667) ](https://packagist.org/packages/tjdft/laravel)

Introdução
==========

[](#introdução)

Pacote unificado para desenvolvimento de aplicações Laravel no TJDFT.

**Integrações:**

- Keycloak
- API RH
- Sentry
- SMAX

**Funcionalidades:**

- Auditoria
- Permissões
- Impersonate
- GraphQL Faker

**UI:**

- Componentes **maryUI** + pacotes de ícones.
- Página de **erro** padronizada.
- Arquivos de **translation** em `pt_BR`.

**Utils:**

- Validações adicionais para formatos brasileiros (CPF, CNPJ, CEP, etc).
- Utilitários `Numero` e `Data` para formatações diversas.
- Trait `HasSearchAny` para busca simplificada em **múltiplos campos**.
- Trait `WithPaginationAndReset` para paginação simplificada com **Livewire**.
- Trait `HasSpinnerPlaceholder` para exibir um spinner em componentes `lazy`.
- Trait `TestUtils` com métodos auxiliares para testes automatizados.
- Ativa extensões úteis do **PostgreSQL** (unaccent, pg\_trgm, ...).

Setup
=====

[](#setup)

**Estrutura**

```
  |__ .docker/
  |   |__ Dockerfile
  |   |__ compose.yaml
  |   |__ deploy.sh
  |
  |__ .gitlab-ci.yml
  |
  |__ ...
```

**compose.yaml**

```
name: meuapp

volumes:
    redis-volume:
    postgres-volume:
    postgres-teste-volume:

services:
    ######## APP ########
    app:
        build:
            context: ..
            dockerfile: .docker/Dockerfile
            target: base
        volumes:
            - ../:/var/www/html:cached
        ports:
            - "8010:8080"
            - "5070:5070"

    ######## REDIS ########
    redis:
        image: redis:8.2.2
        volumes:
            - redis-volume:/data
        ports:
            - "6310:6379"

    ######## POSTGRES ########
    postgres:
        image: postgres:17.2
        environment:
            - POSTGRES_DB=meuapp
            - POSTGRES_USER=meuapp
            - POSTGRES_PASSWORD=meuapp
        volumes:
            - postgres-volume:/var/lib/postgresql/data
        ports:
            - "54100:5432"

    ######## POSTGRES TESTE ########
    postgres-teste:
        image: postgres:17.2
        environment:
            - POSTGRES_DB=meuapp
            - POSTGRES_USER=meuapp
            - POSTGRES_PASSWORD=meuapp
        volumes:
            - postgres-teste-volume:/var/lib/postgresql/data
        ports:
            - "54101:5432"
```

**Dockerfile**

```
# Base
FROM [RL-REGISTRY]/tjdft/laravel:4.2 AS base
COPY --chown=www-data:www-data . .

# Build
FROM base AS build
RUN cp .env.example .env
RUN composer install --prefer-dist --no-interaction --no-progress --quiet --ansi --no-dev
RUN yarn install --silent && yarn build && yarn cache clean && rm -rf node_modules

# Production
FROM build AS production
ENV RUN_DEPLOY=true
```

**deploy.sh**

```
#!/usr/bin/zsh

# Migrations
php artisan migrate --force

# Seeders
php artisan db:seed --force

# Storage link
php artisan storage:link

# Otimiza a aplicação
php artisan optimize
php artisan icons:cache
```

**.gitlab-ci.yml**

```
image: [URL-REGISTRY]/tjdft/laravel:4.2

include:
    -   project: "cosoft/nusof5/pipelines/laravel"
        file: "template-podman.yml"

variables:
    OPENSHIFT_PROJECT: meuapp
    SONAR_PROJECT: meuapp

test:
    extends: .test
    services:
        - name: postgres:17
          alias: postgres-teste
    variables:
        DB_HOST: postgres-teste
        POSTGRES_DB: meuapp
        POSTGRES_USER: meuapp
        POSTGRES_PASSWORD: meuapp
sonar:
    extends: .sonar

build:
    extends: .build

deploy:
    extends: .deploy
```

**Inicie o container**

```
cd .docker/

docker compose up -d

docker compose exec app zsh
```

**Crie o projeto**

```
laravel new meuapp --git --pest --yarn --database=pgsql --no-interaction
mv meuapp/*(D) .
rm -rf meuapp
```

**Ajuste o `.env`**

```
DB_CONNECTION=pgsql
DB_HOST=postgres
DB_PORT=5432
DB_DATABASE=meuapp
DB_USERNAME=meuapp
DB_PASSWORD=meuapp
```

**Migrate**

```
php artisan migrate
```

**Inicie**

```
yarn dev

```

Instalação
==========

[](#instalação)

Adicione o pacote.

```
composer require tjdft/laravel
```

Instale maryUI incluído no pacote.

```
php artisan mary:install --yarn --no-css
```

Ajuste `config/app.php`

```
'timezone' => 'America/Sao_Paulo',
```

Ajuste `tests/Pest.php`.

```
pest()->extend(Tests\TestCase::class)->in('Feature', 'Unit');
```

Ajuste `resources/css/app.css`.

```
@import 'tailwindcss';
@import "../../vendor/tjdft/laravel/resources/css/tjdft.css";

/* ... */
```

Ajuste `vite.config.js`.

```
// ...

input: [
    "resources/css/app.css",
    "resources/js/app.js",
    "vendor/tjdft/laravel/resources/css/tinymce.css"
]

// ...

server: {
    host: "0.0.0.0",
        port: 5070,
        hmr: {
        host: "localhost",
            clientPort: 5070
    },

    //...
}
```

Ajuste `bootstrap/app.php`.

```
use TJDFT\Laravel\Exceptions\ExceptionHandler;
// ...

->withMiddleware(function (Middleware $middleware) {
    // Para proxy reverso (Openshift)
    $middleware->trustProxies(at: '*');
})
->withExceptions(function (Exceptions $exceptions) {
    // Tratamento personalizado de exceções
    ExceptionHandler::register($exceptions);
})
```

Ajuste `app/Models/User.php`.

```
use TJDFT\Laravel\Traits\HasGrant;
use TJDFT\Laravel\Traits\HasImpersonate;
use TJDFT\Laravel\Traits\HasSearchAny;
use Illuminate\Database\Eloquent\Casts\Attribute;
// ...

class User extends Authenticatable
{
    use HasGrant, HasImpersonate, HasSearchAny;

    //...

    protected $guarded = ['id'];

    //...

    public function primeiroNome(): Attribute
    {
        return Attribute::make(
            get: fn() => str($this->nome)->explode(' ')->first(),
        );
    }

    protected function casts(): array
    {
        return [
            'localizacao' => 'object'
        ];
    }
}
```

Ajuste `tests/TestCase.php`.

```
use Illuminate\Foundation\Testing\TestCase as BaseTestCase;
use TJDFT\Laravel\Traits\TestUtils;

abstract class TestCase extends BaseTestCase
{
    // Helpers para testes automatizados
    use TestUtils;

    // Equivale ao `setUp()` do PHPUnit
    protected function boot(): void
    {
        // Adicione aqui qualquer coisa que precise ser executada antes dos testes.
    }
}
```

Ajuste `.env` / `.env.example`.

```
APP_LOCALE=pt_BR

# ...
# ...
# ...

DB_SSLMODE=false

# ...
# ...
# ...

# Sentry
TJDFT_SENTRY_LARAVEL_DSN=

# Fotos
TJDFT_FOTOS_URL=https://

# Schema onde devem ser ativadas as extensões do PostgreSQL
# Use apenas se o schema principal da aplicação for diferente de `public`.
TJDFT_PGSQL_EXTENSIONS_SCHEMA=core

# API RH
TJDFT_POLVO_API_URL=https:///graphql
TJDFT_POLVO_AUTH_URL=https:///auth/realms//protocol/openid-connect/token
TJDFT_POLVO_CLIENT_ID=
TJDFT_POLVO_CLIENT_SECRET=
TJDFT_POLVO_CACHE_TTL='1 hour'

# Keycloak
TJDFT_KEYCLOAK_BASE_URL=https:///auth
TJDFT_KEYCLOAK_REALMS=
TJDFT_KEYCLOAK_CLIENT_ID=
TJDFT_KEYCLOAK_CLIENT_SECRET=

# SMAX
TJDFT_SMAX_URL=https://
TJDFT_SMAX_TENANT_ID=
TJDFT_SMAX_REQUESTS_OFFERING=
TJDFT_SMAX_LOGIN=
TJDFT_SMAX_PASSWORD=
TJDFT_SMAX_FALLBACK_EMAILS=
```

Ajuste a migration existente `users`.

```
Schema::create('users', function (Blueprint $table) {
    $table->id();
    $table->uuid()->index()->nullable();
    $table->string('login')->index();
    $table->string('matricula')->nullable();
    $table->string('cpf')->index()->nullable();
    $table->string('nome');
    $table->string('email')->nullable();
    $table->string('foto')->nullable();
    $table->json('localizacao')->nullable();
    $table->string('rh_tipo')->nullable();
    $table->string('rh_status')->nullable();
    $table->timestamps();

    $table->unique(['cpf', 'matricula']);
});
```

Rode as migrations.

```
# Esta ação destruirá e recriará o banco!

php artisan migrate:fresh --seed
```

**Pronto!**

---

🚨 Configuração padrão ativada por este pacote.

```
// Proíbe comandos destrutivos em produção
DB::prohibitDestructiveCommands($this->app->isProduction());

// Moeda
Number::useLocale('pt-BR');
Number::useCurrency('BRL');

// now() + json_encode()
Date::serializeUsing(function ($date) {
    return $date->format('Y-m-d H:i:s');
});
```

---

🔥 Utilize estes composer scripts.

```
// ...

"scripts": {
    "test": [
        "@php artisan config:clear --ansi",
        "@php artisan test --parallel --compact --no-coverage"
    ],
    "test:watch": [
        "Composer\\Config::disableProcessTimeout",
        "phpunit-watcher watch --compact --filter='xxxxxx' < /dev/tty"
    ],
    "test:coverage": [
        "php -d pcov.enabled=1 ./vendor/bin/pest --compact --coverage --log-junit=.coverage/report.xml --coverage-html=.coverage/html --coverage-clover=.coverage/clover.xml --coverage-cobertura=.coverage/cobertura.xml"
    ],
    "start": [
          "Composer\\Config::disableProcessTimeout",
          "composer install",
          "php artisan key:generate",
          "php artisan migrate:fresh --seed",
          "php artisan optimize:clear",
          "php artisan storage:link",
          "rm -rf public/build",
          "yarn cache clean",
          "yarn install",
          "yarn dev"
    ],

  // ...
}

// ...
```

Autenticação
============

[](#autenticação)

Este pacote implementa o fluxo de autenticação OAuth2 via `Keycloak` para as rotas protegidas do sistema.

```
// Rotas protegidas
Route::middleware('auth')->group(function () {

    Route::livewire('/paginas/create', 'pages::paginas.criar');

    // ...
});
```

Para o **logout** de usuários utilize a rota `/auth/logout/keycloak`.

```

```

Usuários com **mais de um vínculo no RH** serão redirecionados automaticamente para a rota `/auth/perfil` para seleção do perfil de acesso.

```

```

Autorização
===========

[](#autorização)

Utilize a rota `/auth/permissions` para acessar o gerenciamento de permissões.

```

```

Estas são as permissions iniciais registradas automaticamente pelo pacote.

```
// Permissão master
Permission::create([
    'name' => 'permissoes.gerenciar',
    'description' => 'Permissões / Gerenciar',
]);

// Permissão de impersonate
Permission::create([
    'name' => 'impersonate',
    'description' => 'Impersonate',
]);
```

Crie permissions da sua aplicação.

```
// database/seeders/PermissionsSeeder.php

use Illuminate\Database\Seeder;
use TJDFT\Laravel\Models\Permission;

// ...

class PermissionsSeeder extends Seeder
{
    public function run(): void
    {
        // Evita duplicação
        if (Permission::where('name', 'comprovante.processar')->count()) {
            return;
        }

        // Processar comprovantes
        Permission::create([
            'name' => 'comprovante.processar',
            'description' => 'Comprovantes de Rendimentos / Processar',
        ]);

        // Visualizar comprovantes
        Permission::create([
            'name' => 'comprovante.visualizar',
            'description' => 'Comprovantes de Rendimentos / Visualizar',
        ]);

        // Defina os administradores iniciais do sistema
        User::create([
            'cpf' => '0123456789',
            'matricula' => '123456',
            'login' => 't123456',
            'nome' => 'Maria Silva'
        ])->givePermissionTo([
            'permissoes.gerenciar',
            'impersonate',
            'comprovante.processar',
            'comprovante.visualizar'
        ]);

        // ...
    }
}
```

Adicione `PermissionSeeder` aos seeders da aplicação.

```
// database/seeders/DatabaseSeeder

class DatabaseSeeder extends Seeder
{
    public function run(): void
    {
        $this->call([
            // ...

            PermissionsSeeder::class,
        ]);
    }
}
```

Rode as migrations.

```
# Esta ação destruirá e recriará o banco!

php artisan migrate:fresh --seed
```

Lógica personalizada para definir permissions dinamicamente.

```
// app/Actions/AtualizarPermissionsLoginAction.php
