Laravel é um Framework PHP utilizado para o desenvolvimento web, que utiliza a arquitetura MVC e tem como principal característica ajudar a desenvolver aplicações seguras e performáticas de forma rápida, com código limpo e simples, já que ele incentiva o uso de boas práticas de programação e utiliza o padrão PSR-2 como guia para estilo de escrita do código.
No fim do ano passado, o Bugginho Developer entrevistou Diego Hernandes, um dos mais importantes movimentadores da comunidade Laravel no Brasil. Se você for um programador PHP e pensa em aprender a usar o Laravel, sugerimos que leia a entrevista para conhecer melhor este framework e sua comunidade no Brasil.
Algumas características proeminentes do Laravel são sua sintaxe simples e concisa, um sistema modular com gerenciador de dependencias dedicado, várias formas de acesso a banco de dados relacionais e vários utilitários indispensáveis no auxílio ao desenvolvimento e manutenção de sistemas.
Para ver o Laravel em ação, confira como a livecoder brasileira AGyrafa desenvolve um site com este framework:
Ao desenvolver aplicações, geralmente é comum ter a necessidade de criar caracteres aleatórios e, por isso, muitas linguagens de programação já têm mecanismos de geração aleatória embutidos. Algumas aplicações comuns incluem:
- Geração de código numérico aleatório para confirmação de e-mail ou serviço de verificação de número de telefone;
- Serviço de geração de senha que gera strings de senha alfanuméricas aleatórias;
- Geração de tokens ou strings aleatórios codificados em Base64 como chaves API.
Quando seu aplicativo precisa gerar muitas sequências de caracteres como as enumeradas acima, então o pacote Keygen é uma boa opção.
O que é o Keygen?
Keygen é um pacote PHP para gerar sequências de caracteres aleatórios simples de qualquer comprimento desejado e é fornecido com quatro geradores, numérico, alfanumérico, token e bytes. Ele tem uma interface muito simples e suporta encadeamento de métodos, tornando possível gerar chaves aleatórias simples com apenas uma linha de código. O pacote Keygen pode poupar seu tempo ao implementar um mecanismo de geração aleatória personalizado para seu aplicativo. Aqui estão alguns benefícios adicionais do Keygen:
- É muito fácil adicionar um prefixo ou sufixo à sequência gerada aleatoriamente;
- Você pode processar a sequência gerada aleatoriamente através de uma fila de callables antes de ser finalmente produzida;
- Você pode controlar manipulações e mutações de várias instâncias Keygen.
Vamos mostrar neste artigo como implementar o pacote Keygen e usá-lo em aplicações Laravel. Para obter uma documentação completa e guia de uso do pacote Keygen, consulte o documento README.
Começando
Neste tutorial, vamos criar um serviço simples de REST API. A API fornece endpoints para criar registros de usuário, mostrar o registro do usuário e gerar uma senha aleatória.
Este tutorial pressupõe que você já tem um aplicativo Laravel sendo executado e a ferramenta Composer já instalada em seu sistema e adicionada ao seu sistema PATH. Neste tutorial, vamos usar o Laravel 5.3. Você pode consultar o guia de instalação do Laravel se não tiver o Laravel instalado.
Em seguida, instalaremos o pacote Keygen como uma dependência para o nosso projeto usando composer. O pacote Keygen está disponível no repositório como gladcodes/keygen.
Se ele instalado corretamente, você verá uma tela como a seguinte imagem:
Criando um alias para o pacote do Keygen
A funcionalidade do pacote Keygen está encapsulada na classe KeygenKeygen. Por conveniência, registramos um alias para esta classe, para que possamos usá-lo facilmente em qualquer lugar em nossa aplicação. Para criar o alias, editamos o arquivo config/app.php e adicionamos um registro para nosso alias depois do último registro na array aliases, como mostrado a seguir.
1 2 3 4 5 6 |
// config/app.php 'aliases' => [ // ... other alias records 'Keygen' => KeygenKeygen::class, ], |
Agora podemos usar o pacote Keygen em qualquer lugar em nossa aplicação. Adicione a diretiva use Keygen no seu código para usar o pacote Keygen como mostrado no exemplo a seguir.
1 2 3 4 5 6 7 8 |
// usage example <?php use Keygen; $id = Keygen::numeric(10)->generate(); echo $id; //2542831057 |
Criando o Modelo do Usuário
Em seguida, vamos criar uma tabela de banco de dados chamada users para armazenar nossos registros de usuários. O esquema para a tabela é o seguinte:
- id INT(11) NOT NULL PRIMARY
- code CHAR(24) NOT NULL UNIQUE
- firstname VARCHAR(32) NOT NULL
- lastname VARCHAR(32) NOT NULL
- email VARCHAR(80) NOT NULL UNIQUE
- password_salt CHAR(64) NOT NULL
- password_hash CHAR(60) NOT NULL
Se criada corretamente, ele deve ser como mostrado na captura de tela a seguir:
Antes de prosseguir, verifique o arquivo config/database.php e o arquivo .env do seu aplicativo para garantir que você tenha a configuração correta para seu banco de dados.
Em seguida, criaremos um modelo para a tabela users usando a interface de linha de comando artisan do Laravel. O Laravel já vem com um modelo User interno e, por isso, temos que criar nosso modelo de usuário personalizado em um local diferente, a pasta app/Models, conforme mostrado no seguinte comando.
1 |
php artisan make:model Models/User |
Modificaremos a classe User criada no arquivo app/Models/User.php conforme mostrado no código a seguir para configurar nosso modelo conforme necessário.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
// app/Models/User.php <?php namespace AppModels; use IlluminateDatabaseEloquentModel; class User extends Model { protected $table = 'users'; public $timestamps = false; public $incrementing = false; public function setEmailAttribute($email) { // Ensure valid email if (!filter_var($email, FILTER_VALIDATE_EMAIL)) { throw new Exception("Invalid email address."); } // Ensure email does not exist elseif (static::whereEmail($email)->count() > 0) { throw new Exception("Email already exists."); } $this->attributes['email'] = $email; } } |
No código acima precedente, definimos a propriedade timestamps como false para desativar os recursos de timestamps do Laravel em nosso modelo. Também definimos a propriedade incrementing como false para desativar o incremento automático do campo da chave primária.
Finalmente, definimos um mutator para o atributo email do nosso modelo com verificação de validação de e-mail e verificação para evitar entradas de e-mail duplicadas.
Definindo rotas para a API
Em seguida, definiremos rotas para os endpoints da API. Existem basicamente quatro endpoints:
- GET /api/users
- POST /api/users
- GET /api/user/{id}
- GET /api/password
1 2 3 4 5 6 7 8 9 |
// routes/web.php // Add the following route definitions for API Route::group(['prefix' => 'api'], function() { Route::get('/users', 'ApiController@showAllUsers'); Route::post('/users', 'ApiController@createNewUser'); Route::get('/user/{id}', 'ApiController@showOneUser'); Route::get('/password', 'ApiController@showRandomPassword'); }); |
Em seguida, criamos o nosso ApiController usando a interface de linha de comando artisan do Laravel e adicionamos os métodos registrados nas rotas.
1 |
php artisan make:controller ApiController |
O comando acima cria um novo arquivo app/Http/Controllers/ApiController.php que contém a classe ApiController. Podemos ir em frente para editar a classe e adicionar os métodos registrados nas rotas.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
// app/Http/Controllers/ApiController.php <?php namespace AppHttpControllers; use IlluminateHttpRequest; class ApiController extends Controller { public function showAllUsers(Request $request) {} public function createNewUser(Request $request) {} public function showOneUser(Request $request, $id) {} public function showRandomPassword(Request $request) {} } |
O Laravel já vem com um middleware para verificação CSRF em todas as rotas web. Não exigiremos isso para a API, portanto, excluiremos nossas rotas api do serviço de verificação CSRF no arquivo app/Http/Middleware/VerifyCsrfToken.php.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
// app/Http/Middleware/VerifyCsrfToken.php <?php namespace AppHttpMiddleware; use IlluminateFoundationHttpMiddlewareVerifyCsrfToken as BaseVerifier; class VerifyCsrfToken extends BaseVerifier { /** * The URIs that should be excluded from CSRF verification. * * @var array */ protected $except = [ '/api/*', ]; } |
Gerando ID exclusivo para o usuário
O pacote Keygen será usado para gerar um ID inteiro de 8 dígitos para o usuário. Vamos implementar o mecanismo de geração de ID exclusivo em um novo método generateID(). Também adicionaremos diretivas de uso para classes Hash, Keygen e AppModelsUser em nosso controlador.
Primeiro, vamos adicionar um novo método generateNumericKey() para gerar chaves numéricas aleatórias de 8 dígitos de comprimento.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
// app/Http/Controllers/ApiController.php <?php namespace AppHttpControllers; use Hash; use Keygen; use AppModelsUser; use IlluminateHttpRequest; class ApiController extends Controller { // ... other methods protected function generateNumericKey() { return Keygen::numeric(8)->generate(); } } |
O pacote Keygen gera chaves numéricas chamando estaticamente o método numeric() da classe KeygenKeygen. É necessário um argumento length, que especifica o comprimento da chave numérica e assume como padrão 16 se omitido. No nosso caso, o comprimento da chave numérica gerada é 8. O método generate() deve ser chamado para retornar a chave gerada.
Geralmente, não é desejável ter números começando com zero armazenados no banco de dados, especialmente IDs. O snippet a seguir modifica o mecanismo de geração do método generateNumericKey() usando o método prefix() fornecido pelo pacote Keygen para adicionar um inteiro diferente de zero no início da chave numérica. Isso é conhecido como um afixo. O pacote Keygen também fornece um método suffix() para adicionar caracteres no final das chaves geradas.
1 2 3 4 5 6 7 8 |
// modified generateNumericKey() method // Ensures non-zero integer at beginning of key protected function generateNumericKey() { // prefixes the key with a random integer between 1 - 9 (inclusive) return Keygen::numeric(7)->prefix(mt_rand(1, 9))->generate(true); } |
No código anterior, observe como chamamos numeric() com o comprimento 7. Isso ocorre porque estamos adicionando um inteiro aleatório não-zero como um prefixo, fazendo com que o comprimento da chave numérica gerada final seja 8 como é necessário.
E, agora, vamos implementar o método generateID() para gerar IDs de usuário exclusivo.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
// generateID() method protected function generateID() { $id = $this->generateNumericKey(); // Ensure ID does not exist // Generate new one if ID already exists while (User::whereId($id)->count() > 0) { $id = $this->generateNumericKey(); } return $id; } |
Criando um novo usuário
Vamos escrever a implementação do método createNewUser() em nosso ApiController para criar um registro para o novo usuário.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
public function createNewUser() { $user = new User; // Generate unique ID $user->id = $this->generateID(); // Generate code for user $user->code = $this->generateCode(); // Collect data from request input $user->firstname = $request->input('firstname'); $user->lastname = $request->input('lastname'); $user->email = $request->input('email'); $password = $request->input('password'); // Generate random base64-encoded token for password salt $salt = Keygen::token(64)->generate(); $user->password_salt = $salt; // Create a password hash with user password and salt $user->password_hash = Hash::make($password . $salt . str_rot13($password)); // Save the user record in the database $user->save(); return $user; } |
No fragmento anterior, usamos Keygen::token() para gerar um token aleatório de 64 bits codificado para a nossa senha salt, com 64 caracteres. Também usamos a fachada Hash incorporada do Laravel para fazer um hash de senha bcrypt usando a senha do usuário e a senha salt.
Agora você pode criar um registro de usuário através da rota POST/api/users. Aqui, usamos Postman para testar os endpoints da API. Esta é a carga JSON do meu pedido POST:
1 2 3 4 5 6 |
{ "firstname": "Jack", "lastname": "Bauer", "password": "f1gHtTerr0rIsts" } |
Aqui, está uma imagem do Postman:
Implementando os métodos restantes
Vamos escrever a implementação dos métodos restantes em nosso controlador.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
// app/Http/Controllers/ApiController.php public function showAllUsers(Request $request) { // Return a collection of all user records return User::all(); } public function showOneUser(Request $request, $id) { // Return a single user record by ID return User::find($id); } public function showRandomPassword(Request $request) { // Set length to 12 if not specified in request $length = (int) $request->input('length', 12); // Generate a random alphanumeric combination $password = Keygen::alphanum($length)->generate(); return ['length' => $length, 'password' => $password]; } |
Na implementação do método showRandomPassword(), estamos usando o Keygen::alphanum() para criar uma combinação aleatória de caracteres alfanuméricos como a senha gerada. O comprimento da senha gerada é obtido a partir do parâmetro de consulta length da solicitação se for fornecido. Se não, o padrão é 12, como especificado.