PHPackages                             louisk/artisan-faz-pra-mim - 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. louisk/artisan-faz-pra-mim

ActiveLibrary

louisk/artisan-faz-pra-mim
==========================

Laravel 5 Generator

0108PHP

Since Jul 7Pushed 6y ago1 watchersCompare

[ Source](https://github.com/keviinlouis/ArtisanFazPraMim)[ Packagist](https://packagist.org/packages/louisk/artisan-faz-pra-mim)[ RSS](/packages/louisk-artisan-faz-pra-mim/feed)WikiDiscussions master Synced 2d ago

READMEChangelogDependenciesVersions (1)Used By (0)

Artisan Faz Pra mim
===================

[](#artisan-faz-pra-mim)

TODOS
-----

[](#todos)

- Atrelar relations no store e no update
- Corrigir os Bugs encontrados
- Copiar Classe Request
- Analisar se vale a pena deixar o base files na vendor

Como Usar
---------

[](#como-usar)

Tenha certeza que seu banco está modelado, de preferencia em ingles, e seu `.env` está configurado corretamente

Rode o comando
`composer require louisk/artisan-faz-pra-mim`

Se o seu projeto for Laravel menor que v5.5, registre em `config/app.php`

```
   /*
   * Package Service Providers...
   */
  Louisk\ArtisanFazPraMim\FazPraMimServiceProvider::class,

```

Rode o comando para configurar seu projeto, como pastas e quais features você quer, o comando irá gerar o `config/faz-pra-mim.php`
Caso queira o projeto default, não precisa configurar
`php artisan vendor:publish --tag=faz-pra-mim`

Rode o comando para gerar seu projeto
`php artisan faz-pra-mim`

Pronto!

Estrutura Projeto Artisan Faz Pra Mim
-------------------------------------

[](#estrutura-projeto-artisan-faz-pra-mim)

- Controller
- Service
- Rules
- Resource
- Observer
- JWT
- Routes
- Generators

#### Controller

[](#controller)

##### Objetivo

[](#objetivo)

- Controlar regras de quem está solicitando um serviço
- Controlar o tipo de retorno para quem está solicitando o serviço

##### Diretório

[](#diretório)

- `app/Http/Controllers/{Guard}`
- Substituir a {guard} pelo tipo de usuário, por exemplo Cliente ou Admin

##### Exemplo de função:

[](#exemplo-de-função)

```
public function index(Request $request): OficinaResource
{
    $data = $request->toCollection();

    $data['ativo'] = true;

    $data['plano_ativo'] = true;

    if (auth()->user()->carroAtual) {
        $data['veiculo'] = auth()->user()->carroAtual->modelo->veiculo_id;
        $data['marca'] = auth()->user()->carroAtual->modelo->veiculo->marca_id;
    }

    $this->oficinaService->relationsCount = ['avaliacoes'];

    $model = $this->oficinaService->index($data);

    return new OficinaResource($model);
}

```

##### Considerações

[](#considerações)

- Quando um `cliente` solicita uma listagem de `oficinas`, deve-se mostrar apenas as ativas e as que possuem plano ativo, alem de mostrar a quantidade de avaliações que ela tem.
- Se caso o cliente possuir um carro, deve-se procurar oficinas para aquela marca e veiculo.
- Geralmente usa-se a função `auth()` nas controllers e não nas services
- Ao conseguir o resultado, deve-se retornar uma ` Resource` caso seja API, ou uma `View` caso seja web.

#### Service

[](#service)

##### Objetivo

[](#objetivo-1)

- Servir para qualquer controller (qualquer um poder chamar a service)
- Chamar a validação dos dados independente de quem estiver chamando
- Conter a maioria da logica do sistema
- Retornar a `Model` caso não seja o método de listagem (`index`) ou uma `Collection` ou `LengthAwarePaginator` caso seja o método `index`
- Usar sempre o `Eloquent`, em casos de dashboard, utilizar `\DB::table()`

##### Diretório

[](#diretório-1)

- `app/Services`

##### Documentação

[](#documentação)

- Relations:
- Queries:
- Query por relation:

##### Exemplo de função

[](#exemplo-de-função-1)

```
 public function store(Collection $data): Anuncio
    {

        if ($data->get('credito') && (!$data->get('parcelas') || $data->get('parcelas') put('parcelas', 1);
        }

        $this->validateWithArray($data->toArray(), AnuncioRules::store());

        if (auth()->user() instanceof Usuario && auth()->user()->oficina->creditos_anuncios thumbnail_id;

        if (!$data->get('validade')) {
            $data['validade'] = now()->addDays(15);
        }

        \DB::beginTransaction();

        $model = Anuncio::create($data->all());

        $modelos = $data->get('modelos', []);
        $veiculos = $data->get('veiculos', []);
        $marcas = $data->get('marcas', []);

        if (count($modelos) > 0) {
            $model->modelos()->sync($modelos);
        }
        if (count($veiculos) > 0) {
            $model->veiculos()->sync($veiculos);
        }
        if (count($marcas) > 0) {
            $model->marcas()->sync($marcas);
        }

        \DB::commit();
        return $this->show($model->getKey());
    }

```

##### Considerações

[](#considerações-1)

- Tentar ao máximo não utilizar o método `auth()`
- Sempre colocar `\DB::beginTransaction();` e `\DB::commit();` nas modificações do banco
- Sempre que precisar, criar relações baseadas na model
- Sempre utilizar as validações `$this->validateWithArray($data->toArray(), AnuncioRules::store());`
- Sempre validar mudança de status das models
- Se preciso, criar uma função para Validar se o usuário pode alterar uma model (exceção para o uso do método `auth()` )

#### Rules (Validations)

[](#rules-validations)

##### Objetivo

[](#objetivo-2)

- Ter metodos estáticos para serem usados em qualquer lugar do código (Geralmente em services e em outros casos em controllers)
- Conter as regras para criação e edição de todas as `Models`

##### Diretório

[](#diretório-2)

- `app/Validators`

##### Documentação

[](#documentação-1)

- Validações disponiveis:
- Validações customizadas:

##### Exemplo de função

[](#exemplo-de-função-2)

```
 public static function store(): array
 {
     return [
         'titulo' => 'required|min:3|string',
         'descricao' => 'required|min:10|string',
         'valor_original' => 'required|numeric|greater_than_field:valor_promocional',
         'valor_promocional' => 'required|numeric|lower_than_field:valor_original',
         'mao_obra' => 'required|numeric',
         'peca_original' => 'nullable|numeric',
         'dinheiro' => 'required|boolean',
         'debito' => 'required|boolean',
         'credito' => 'required|boolean',
         'parcelas' => 'nullable|required_if:credito,true|min:1',
         'validade' => 'nullable|date_format:"Y-m-d"|before:"'.now()->addDays(16)->toDateString().'"',
         'servico_id' => 'required|exists:servicos,id',
         'oficina_id' => 'required|exists:oficinas,id',
         'marcas' => 'array',
         'marcas.*' => 'exists:marcas,id',
         'veiculos' => 'array',
         'veiculos.*' => 'exists:veiculos,id',
         'modelos' => 'array',
         'modelos.*' => 'exists:modelos,id',
         'raio' => 'required|integer|min:1',
     ];
 }

```

##### Considerações

[](#considerações-2)

- Tentar ao máximo validar todos os tipos de campos
- Em campos que são array, validar os campos, por exemplo `'modelos' => 'array'` e `'modelos.*' => 'exists:modelos,id'`
- Se preciso, mandar parametros para as rules, para verificações especificas
- Sempre retornar um array
- Para criar validações customizadas, há duas formas, `Validator::extend()` ou criação de uma classe `Rule em `app/Rules`
- Quando utilizar o `Validator::extend()`, fazer um provider e coloque todos lá, não se esqueça de registar a provider `config/app.php`

#### Observers

[](#observers)

##### Objetivo

[](#objetivo-3)

- Gerenciar as notificações
- Gerenciar mudança de status
- Rotinas obrigatorias para os métodos

##### Diretório

[](#diretório-3)

- `app/Observers`

##### Documentação

[](#documentação-2)

- Observers:

##### Exemplo de função

[](#exemplo-de-função-3)

```
public function updated(Anuncio $anuncio)
    {
        if ($anuncio->getOriginal('status') !== $anuncio->status) {
            switch ($anuncio->status) {
                case Anuncio::EM_AVALIACAO:

                    break;
                case Anuncio::INATIVO:

                    break;
                case Anuncio::EXPIRADO:
                    $this->notificaOficinaAnuncioExpirado($anuncio);
                    break;
                case Anuncio::ATIVO:
                    if (auth()->user() instanceof Administrador) {
                        $this->notificaOficinaAnuncioAprovado($anuncio);
                    }
                    break;
                case Anuncio::REPROVADO:
                    $anuncio->oficina->adicionarCreditos();
                    $this->notificaOficinaAnuncioReprovado($anuncio);
                    break;
                case Anuncio::REVISAO:
                    $this->notificaOficinaAnuncioRevisao($anuncio);
                    break;
            }
        }
    }

```

##### Considerações

[](#considerações-3)

- Sempre verificar se o campo original (antigo) é diferente do atual (atualizado)
- Mandar notificações
- As funções disponiveis são: retrieved, creating, created, updating, updated, saving, saved, deleting, deleted, restoring, restored
- Se possivel, crie um provider para registrar os observers e registre em
- Para registrar, use ` User::observe(UserObserver::class);` em um provider `config/app.php`\#### Observers

#### Resource

[](#resource)

##### Objetivo

[](#objetivo-4)

- Montar response para os Clients
- Gerenciar tipos de retornos

##### Diretório

[](#diretório-4)

- `app/Http/Resources`

##### Documentação

[](#documentação-3)

- Resource API:

##### Exemplo de função

[](#exemplo-de-função-4)

```
public function toResource($resource)
{
    $data = [
        'id' => $resource->getKey(),
        'status' => (int) !$resource->trashed(),
        'nome' => $resource->nome,
        'tipo' => $resource->tipo,
        'meses' => $resource->meses,
        'quilometros' => $resource->quilometros,
        'quilometros_aviso' => $resource->quilometros_aviso,
        'meses_aviso' => $resource->meses_aviso,
        'thumbnail' => new ThumbnailResource($resource->thumbnail),
        'aviso_normal' => $resource->aviso_normal,
        'aviso_manutencao' => $resource->aviso_manutencao,
    ];
    if (request()->has('especialidade')) {
        $data['especialidade'] = new EspecialidadeResource($resource->especialidade);
    }

    return $data;
}

public function toCollection($collection)
{
    if(!request()->has('groupEspecialidade')){
        return parent::toCollection($collection);
    }else{
        $especialidades = [];
        foreach($collection as $value){
            if(!isset($especialidades[$value->especialidade->id])){
                $especialidades[$value->especialidade->id]['nome'] = $value->especialidade->nome;
            }
            $especialidades[$value->especialidade->id]['servicos'][] = $this->toItemOfCollection($value);

        }
        return $especialidades;
    }
}

```

##### Considerações

[](#considerações-4)

- Sempre cuidar para não fazer consultas no banco de dados em Resources
- Manter sempre um padrão nas respostas
- Ter cuidado ao mudar a resource, pois há possibilidade de gerar exception para os clients sides
- Se basear nas telas do design

### JWT

[](#jwt)

##### Objetivo

[](#objetivo-5)

- Gerenciar o token pelo guard
- Gerenciar o refresh do token

##### Diretório

[](#diretório-5)

- `app/Http/Middleware/CheckToken.php`
- Caso não houver este arquivo, copiar de

##### Documentação

[](#documentação-4)

- Pacote:

##### Descrição

[](#descrição)

- Para autenticação foi utilizado JWT, onde ao fazer login um token é retornado e esse token precisa ser passado via header Authorization do tipo Bearer
- Exemplo: `Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjgwMDAvYXBpL2xvZ2luIiwiaWF0IjoxNTE2Mjc5MTcyLCJleHAiOjE1MTYyODI3NzIsIm5iZiI6MTUxNjI3OTE3MiwianRpIjoib2h0a0VxVUtIdkkzakxMdSIsInN1YiI6MSwicHJ2IjoiZjkzMDdlYjVmMjljNzJhOTBkYmFhZWYwZTI2ZjAyNjJlZGU4NmY1NSJ9.cOjyx6-x3_KHwGgfSh9bSX0g90hNOcyFGB4sMBoMRCI`
- Cada token gerado se expira no tempo registrado no `.env`, logo quando ele for expirado, um parametro new\_token no header do response será retornado, substituindo o token antigo.
- Para isso, cada response deverá ser interceptado para a verificação da existencia do header new\_token.
- Para utilização nas rotas, registrar a middleware em `app/Http/Kernel.php` como `jwt` e registar a middleware na rota como `jwt:{guard}` (exemplo: `jwt:cliente`)
- No `config/auth.php`, registre a guard como `jwt`

##### Considerações

[](#considerações-5)

- Registrar sempre no .env as variaveis `JWT_SECRET`, `JWT_TTL`, `JWT_REFRESH_TTL`, `JWT_BLACKLIST_GRACE_PERIOD`
- Rodar o comando `php artisan jwt:secret`

##### Exemplo de função na rota

[](#exemplo-de-função-na-rota)

```
Route::group(['middleware' => 'jwt:admin'], function(){
    ...
});

```

##### Exemplo em Kernel.php

[](#exemplo-em-kernelphp)

```
protected $routeMiddleware = [
    ...
    'jwt' => CheckToken::class
    ...
];

```

##### Exemplo de Guard

[](#exemplo-de-guard)

```
'guards' => [
    ...
    'admin' => [
        'driver' => 'jwt',
        'provider' => 'admin'
    ],
    ...
],

```

##### Exemplo da middleware

[](#exemplo-da-middleware)

```
public function handle($request, \Closure $next, $guard = null)
{
    $this->checkForToken($request); // Ver se tem o token

    if(!$guard){
        throw new \Exception('Guard inválido', 500);
    }

    Config::set('auth.defaults.guard', $guard);

    try {
        $user = $this->auth->parseToken()->getPayload()['sub'];
        if (!$this->checkModels($user->class, $guard) || !auth()->guard($guard)->onceUsingId($user->id)) { // Check user not found. Check token has expired.
            throw new UnauthorizedHttpException('jwt-auth', 'Usuario não encontrado'); //Se der problema com o token, virá um header chamado WWW-Authenticate com o valor de jwt-auth
        }
        return $next($request); // Se o usuario for autenticado e logado com token válido, continua request

    } catch (TokenExpiredException $t) { // Token expirado, usuario não logado
        $payload = $this->auth->manager()->getPayloadFactory()->buildClaimsCollection()->toPlainArray(); // Pega os dados do token para autenticação

        $refreshed = JWTAuth::refresh(JWTAuth::getToken()); // Faz refresh do token
        $user = $payload['sub'];

        auth()->guard($guard)->onceUsingId($user->id); // Autentica pelo ID

        $response = $next($request); // Pega a request

        $response->header('new_token', $refreshed); // Adiciona o header com o novo token

        return $response; // Responde com o novo token no header

    } catch (JWTException $e) {
        throw new UnauthorizedHttpException('jwt-auth', 'Token Inválido', $e, Response::HTTP_UNAUTHORIZED); //Se der problema com o token, virá um header chamado WWW-Authenticate com o valor de jwt-auth
    }
}

public function getClassBybGuard($guard)
{
    $provider = config('auth.guards.'.$guard.'.provider');
    $class = config('auth.providers.'.$provider.'.model');

    return $class;

}

public function checkModels($class, $guard)
{
   $classAuth = $this->getClassBybGuard($guard);

   return $classAuth == $class;
}

```

#### Routes

[](#routes)

##### Objetivo

[](#objetivo-6)

- Ter um arquivo de rota para cada um
- Gerenciar usuários logaveis no sistema
- Registrar os arquivos em `app/Providers/RouteServiceProvider`

##### Diretório

[](#diretório-6)

- `routes`

##### Documentação

[](#documentação-5)

- Rotas:

##### Exemplo de função na rota

[](#exemplo-de-função-na-rota-1)

```
Route::post('/login', 'AdminController@login');
Route::post('/solicitar-redefinir-senha', 'AdminController@solicitarRedefinirSenha');
Route::post('/redefinir-senha', 'AdminController@redefinirSenha')->name('redefinir-senha');

Route::group(['middleware' => 'jwt:admin'], function(){
    Route::get('/dashboard', 'DashboardController@dashboard');
    Route::get('/dashboard/oficinas/{cidade?}', 'DashboardController@getLatLongOficinasPelaCidade');

    Route::get('/me', 'AdminController@me');
    Route::get('/me/logout', 'AdminController@logout');
    Route::put('/me', 'AdminController@update');
    Route::delete('/me', 'AdminController@destroy');

    Route::get('configuracao', 'ConfiguracaoController@index');
    Route::put('configuracao', 'ConfiguracaoController@update');
});

```

#### Exemplo de função para registrar na Service Provider

[](#exemplo-de-função-para-registrar-na-service-provider)

##### Considerações

[](#considerações-6)

- Sempre colocar a guard do jwt caso seja API
- Sempre colocar as coisas agrupadas usando ` Route::group();`

#### Generators

[](#generators)

##### Objetivo

[](#objetivo-7)

- Gerar Models
- Gerar Migrations

##### Documentação

[](#documentação-6)

- Pacote para Migration:
- Pacote para Models:

##### Considerações

[](#considerações-7)

- Sempre focar na modelagem do banco de dados
- Ler bem a documentação dos pacotes

###  Health Score

20

—

LowBetter than 14% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity9

Limited adoption so far

Community7

Small or concentrated contributor base

Maturity37

Early-stage or recently created project

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

### Community

Maintainers

![](https://www.gravatar.com/avatar/f945238a006edc59a89ffd9ac5aa68597e07a7abeab077b06b2d5301818b4450?d=identicon)[keviinlouis](/maintainers/keviinlouis)

---

Top Contributors

[![louis-kevin](https://avatars.githubusercontent.com/u/1619231?v=4)](https://github.com/louis-kevin "louis-kevin (38 commits)")

### Embed Badge

![Health badge](/badges/louisk-artisan-faz-pra-mim/health.svg)

```
[![Health](https://phpackages.com/badges/louisk-artisan-faz-pra-mim/health.svg)](https://phpackages.com/packages/louisk-artisan-faz-pra-mim)
```

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
