Que tal automatizar tarefas com Artisan? #2
Tags: laravel, beginners, php
Published: 2022-09-06 20:25:32

Na primeira parte deste artigo vimos alguns conceitos básicos sobre o **Artisan**.

Nesta segunda e última parte vamos mais a fundo na classe criada, fazendo alterações nas propriedades e incrementando o método `handle()`.

---

Para iniciar vamos alterar a propriedade `$signature` para `'project:test'`. 

Em seguida vamos editar a propriedade `$description` mudando o valor atual para `'Execute some commands using Artisan'`.

Para confirmar as alterações vamos ao terminal, no diretório raiz do projeto e digitamos o seguinte:

```php
php artisan help project:test
```

:point_down:


![Getting help from MyCommand](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0ghr4xhevz433d3mwwhf.jpg)

:warning: Faremos algumas interações com banco de dados. Portanto, a partir deste ponto, vou assumir que você já tenha realizado esta configuração.

Para obter detalhes sobre conexão com banco de dados em aplicações Laravel sugiro dar uma lida [neste post](https://dev.to/marciopolicarpo/multi-banco-de-dados-em-aplicacoes-laravel-2ob8).


---

### Chamando outros comandos

Com uma lista tão extensa de comandos disponíveis nada mais justo que poder utilizá-los não acha?

O comando é semelhante ao que seria no terminal. Por exemplo, para executar uma migração digitaríamos o seguinte no terminal:

```php
php artisan migrate
```

Para executar a mesma ação dentro da classe de comandos que criamos, faríamos assim:

```php
$this->call('migrate');
```

Lembrando que, quando falamos da classe MyCommand todas as ações devem ficar dentro do método `handle()`.

---

Por enquanto, sem novidade. Entretanto surge a necessidade de criarmos usuários fictícios para a aplicação.

Sem problemas. :sunglasses:
:point_down:

```php
php artisan db:seed
```

Embora estas ações possam ser executadas individualmente sem muita dificuldade, não seria mais produtivo executá-las com uma única instrução? :confused:


Com o editor de código de sua preferência, vamos modificar a classe `MyCommand`, mais especificamente o método `handle()`, que deve ficar como mostrado abaixo:

```php
$this->call('migrate');
$this->call('db:seed');
```

Mas, antes de testar as alterações, vamos editar a classe _\database\seeders\DatabaseSeeder.php_ de forma que sejam criados usuários aleatórios para nossa aplicação. Precisamente, 10.

Esta modificação é bem simples e pode ser vista logo a seguir:

```php
public function run()
{
    \App\Models\User::factory(10)->create();
}

```

Salve as alterações e volte para o terminal, no diretório raiz da aplicação, para executarmos o comando que criamos:

```php
php artisan project:test
```
:point_down:

![Executing MyCommand class](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/44kj6csiscin2h3c85gn.jpg)

Interessante não?

---

### Interagindo com o terminal

E se for necessário reiniciar a migração?

Para isso basta que informemos opção 'refresh' logo após o comando para migrar. 

Porém este comportamento não deve ficar engessado na aplicação. Em outras palavras nem todos os projetos precisão ter sua migração reiniciada.

Neste caso vamos transferir para o desenvolvedor a decisão de quando reiniciar ou não a migração.

A classe `MyCommand `extende de _Illuminate\Console\Command.php_, o que significa que todos os métodos (públicos ou protegidos) da classe **pai** estarão disponíveis.

E para nos ajudar a resolver nessa decisão, faremos isso utilizando o método `confirm()`. Como o próprio nome sugere, será solicitada uma **confirmação** do desenvolvedor para a mensagem que será mostrada. O retorno deste método é um valor booleano.

Utilizando uma abordagem menos ortodoxa, vamos criar uma variável para armazenar o valor `:refresh` quando o desenvolvedor desejar reiniciar a migração e vazio para respostas negativas.

Uma sugestão de código para solucionar essa questão está logo abaixo:

```php
public function handle()
{
    $fresh_migration = ($this->confirm('Refresh migration?') ? ':refresh' : '');

    $this->call('migrate'.$fresh_migration);
    $this->call('db:seed');
    return 0;
}
```
:point_down:

---

Note que, por padrão, a opção selecionada será 'não'. Esta configuração pode ser modificada adicionando `true `como parâmetro, logo após a mensagem, ficando assim:

```php
$refresh_migration = ($this->confirm('Refresh migration?', true) ? ':refresh' : '');
```

---

### Utilizando outras classes dentro da aplicação

Esta abordagem é bem interessante e já facilita bastante a vida do desenvolvedor. :unamused: Mas surgiu a necessidade de criarmos um usuário específico. Como resolver?

Uma das maneiras de solucionar este problema é alterar a classe _\database\seeders\DatabaseSeeder.php_ e inserir o código para esse usuário. Esta solução fará com que o usuário tenha sempre a mesma senha, o que às vezes pode não ser uma boa estratégia.

Outra solução é perguntar ao desenvolvedor se ele deseja ou não criar um usuário.


Voltando ao editor de código, logo abaixo do comando `db:seed` vamos adicionar uma nova linha com o método `$this->confirm()`, abrindo um novo bloco de instruções em seguida:

```php
if ($this->confirm('Create a new user?')) {
//
}

```
Dentro desse bloco crie três variáveis conforme o exemplo abaixo:

```php
$name = null;
$email = null;
$password = null;
```

Em seguida, pedido ao desenvolvedor que informe um nome para o novo usuário. 

```php
while(!$name) {
    $name = $this->ask('Please give us a name');
}

```
Note que utilizo um laço do tipo `while()` que só será finalizado quando a variável `$name` possuir um valor.

Vamos repetir esta técnica para o e-mail e para a senha.

```php
while(!$email) {
    $email = $this->ask('Now, a valid email');
}
    
while(!$password) {
    $password = $this->ask('At last, a password');
}
```

Mas a senha deveria ficar oculta, certo?

Resolvemos essa dificuldade substituindo o método `$this->ask()` pelo método `$this->secret()`, ficando assim:

```php
while(!$password) {
    $password = $this->secret('At last, a password (don\t worry..no one can see it)');
}
```

---

Agora que obtemos o mínimo de informações para um novo usuário da aplicação, vamos criar o modelo desse usuário, persistindo-o no banco de dados em seguida.

:warning: Não se esqueça de importar o modelo **User** (`use App\Models\User;`).


```php
$new_user = new User;
$new_user->name = $name;
$new_user->email = $email;
$new_user->password = bcrypt($password);
    
$new_user->save();
```


E para ter certeza que o usuário foi realmente persistido, basta mostrar o id dele.

```php
$this->warn('New user created sucessfully with id:  "'.$new_user->id."'");
```

Por fim, mostramos uma mensagem informando que todas as tarefas foram realizadas com sucesso.

```php
return $this->info('All tasks completed');
```

:point_down::point_down::point_down:

{% embed https://youtu.be/F6JFQroh1Hs %}

---

### Conclusão

O framework Laravel é uma ferramenta poderosa em vários sentidos:
* acelera o desenvolvimento 
* facilita a automatização de atividades
* possui código aberto

A única limitação é a sua imaginação.

Obrigado pela leitura e até breve. :smiley: