Request
Além de ser possível informar dados para o controller por meio de parâmetros de rota, é possível utilizar a classe Request
para acessar variáveis informadas via GET ou POST, por exemplo. A classe Request
pertence ao Symfony, pacote requerido pelo Silex, e está disponível em Symfony\Component\HttpFoundation\Request
. Algumas das principais propriedades são:
$attributes
: retorna parâmetros personalizados$request
: retorna parâmetros de requisições POST (objeto$_POST
do PHP)$query
: retorna parâmetros de URL (objeto$_GET
do PHP)$server
: retorna informações do servidor web (objeto$_SERVER
do PHP)$files
: retorna arquivos enviados via upload (objeto$_FILES
do PHP)$cookies
: retorna variáveis armazenadas em cookies (objeto$_COOKIE
do PHP)$headers
: retorna cabeçalhos da requisição (extraídos de$_SERVER
)
As propriedades $attributes
, $request
, $query
e $cookies
são do tipo ParameterBag
, cujos principais métodos são apresentados a seguir.
Tipo de retorno | Método | Descrição |
---|---|---|
array |
all() |
Retorna os parâmetros (como array ) |
array |
keys() |
Retorna as chaves (nomes dos parâmetros) |
misto | get($chave, $default, $deep) |
Retorna um parâmetro pelo nome (chave) com valor padrão igual a $default (padrão é null ) |
bool |
has($chave) |
Retorna true se o parâmetro estiver definido |
int |
count() |
Retorna a quantidade de parâmetros |
Além destes, há outros métodos que retornam valores convertendo-os para tipos específicos:
getInt()
: retorna o parâmetro com valor convertido para inteirogetBoolean()
: retorna o parâmetro com valor convertido para booleano
As seções a seguir apresentam a utilização destas propriedades.
Parâmetros de URL
Parâmetros de URL estão presentes na URL, seguindo o formato: nome=valor
(separardos por &
, no caso de mais de um parâmetro). Por exemplo, a URL http://localhost/pessoas/?s=Jose&i=1&o=nome
possui os seguintes parâmetros:
s
com valorJose
i
com valor1
o
com valornome
Para ter acesso a estes parâmetros de URL deve ser utilizada a propriedade $query
, como mostra o exemplo:
require_once 'vendor/autoload.php';
use Silex\Application;
use Symfony\Component\HttpFoundation\Request;
$app = new Silex\Application();
$app->get('/', function(Application $app, Request $request) {
return $request->query->get('id');
});
$app->run();
Para usar as classes Silex\Application
e Symfony\component\HttpFoundation\Request
, é necessário incluí-las no código. isso é feito por meio da instrução use
, utilizada nas linhas 3 e 4.
No controller, estão sendo injetados dois objetos: $app
(do tipo Application
) e $request
(do tipo Request
). Para acessar o parâmetro de URL id
é utilizada a propriedade $query
e o método get()
.
Para acessar o aplicativo, deve ser utilizada a URL http://localhost/?id=1
. Assim, o controller acessa o parâmetro id
, com valor 1
.
Integração com Angular
O capítulo sobre Angular demonstrou que o serviço $http
está disponível e permite realizar requisições HTTP. A primeira forma de integração entre o aplicativo Angular e o Silex é por meio da utilização de parâmetros de URL. Para isso, o aplicativo precisa do frontend e do backend.
Backend
Do lado do backend, o aplicativo contém um controller que trata a rota /
. Este controller espera por dois números via dois parâmetros de URL: numero1
e numero2
:
$app->get('/', function(Application $app, Request $request) {
$numero1 = $request->query->get('numero1', 0);
$numero2 = $request->query->get('numero2', 0);
return ($numero1 + $numero2);
});
Como os dados serão transmitidos via GET, a rota /
é tratada via este protocolo. O código acessa os parâmetros de URL por meio de $request->query->get()
, calcula a soma e retorna o resultado.
Frontend
Do lado do frontend, o código de exemplo desta seção está nos arquivos index.html
e app.js
. No arquivo index.html
há o trecho:
<body ng-controller="Home">
<p>Número A: <input type="text" ng-model="numero1"></p>
<p>Número B: <input type="text" ng-model="numero2"></p>
<p><button ng-click="somar()">Somar</button>
<p>Resultado da soma: {{resultado}}</p>
</body>
O trecho de código refere-se à view do controller Home
.
O código a seguir apresenta o arquivo app.js
:
angular.module('silex-request-get', [])
.controller('Home', function($scope, $http){
$scope.somar = function() {
$http.get('/livro-web-codigo-fonte/backend/request-angular-get/', {
params: {numero1 : $scope.numero1, numero2 : $scope.numero2}
}).then(function(response){
$scope.resultado = response.data;
});
};
});
No controller Home
o serviço $http
está sendo utilizado para criar uma requisição GET para a URL /livro-web-codigo-fonte/backend/request-angular-get/
e informa os parâmetros que representam os dois números a serem enviados para o backend por meio do segundo parâmetro: um objeto que possui o atributo params
que, efetivamente, define quais são os parâmetros enviados para o backend. Aqui, perceba que o valor de params
é um objeto com dois atributos numero1
e numero2
. Não por acaso, os nomes destes atributos referem-se aos nomes dos parâmetros de URL esperados no backend. Os valores dos atributos estão vinculados ao model correspondente.
Uma vez que a requisição GET tenha ocorrido com sucesso, a variável $scope.resultado
recebe o valor de response.data
. O objeto response
, neste caso, parâmetro da função anônima que trata o sucesso da requisição GET, contém informações sobre a resposta enviada pelo backend. O atributo data
contém o conteúdo da resposta.
Requisições POST
O que se pode perceber com as requisições GET é que os dados (variáveis ou parâmetros de URL) ficam visíveis na URL. Entretanto, pode ser que isso não seja a maneira mais adequada. Uma vez que estes dados ficam visíveis inclusive em logs de acesso, dados com requisitos de segurança não podem ser transmitidos desta forma. Assim, a segunda forma, requisições POST, fornece uma maneira de enviar dados diretamente no cabeçalho da requisição HTTP.
Para ter acesso aos dados via deve ser utilizada a propriedade $request
(do objeto $request
), como mostra o exemplo:
require_once 'vendor/autoload.php';
use Silex\Application;
use Symfony\Component\HttpFoundation\Request;
$app = new Silex\Application();
$app->post('/', function(Application $app, Request $request) {
return $request->request->get('id');
});
$app->run();
Enquanto os parâmetros de URL estão presentes na URL da requisição, isso não acontece com os dados enviados via POST. Assim, não é possível (ou não tão fácil) criar requisições POST diretamente no navegador. Por isso, esta seção apresenta duas formas de fazer isso. A primeira delas, apresentada a seguir, usa o mesmo formato de requisição integrada com o Angular. A segunda, utiliza uma extensão para o Google Chrome, que pode ser usada para qualquer tipo de requisição, inclusive, GET ou POST.
Integração com Angular
Backend
A integração com o Angular, no caso de requisições POST, implica em um pequeno problema: o formato como os dados estão codificados no cabeçalho da requisição HTTP. Por padrão, o Silex espera que as requisições estejam codificadas com application/x-www-form-urlencoded
, mas o Angular as codifica com application/json
(uma vez que os dados são sempre tratados em formato JSON). Por causa disso, é necessário tratar a requisição, convertendo os dados para o formato adequado do Silex.
Para facilitar este trabalho, uma classe chamada AngularPostRequestServiceProvider
é utilizada como um serviço do aplicativo Silex, de modo a fazer as conversões necessárias entre o formato do Angular e o formato do Silex.
O código do backend é o seguinte:
require_once 'vendor/autoload.php';
use Silex\Application;
use Symfony\Component\HttpFoundation\Request;
use Lpweb\AngularPostRequestServiceProvider;
$app = new Silex\Application();
$app['debug'] = true;
$app->register(new AngularPostRequestServiceProvider());
$app->post('/', function(Application $app, Request $request) {
$data = $request->request->get('data');
$numero1 = $data['numero1'];
$numero2 = $data['numero2'];
return ($numero1 + $numero2);
});
$app->run();
Perceba que é utilizada a coleção $request
(do objeto $request
) e o nome da chave é data
. Esta é a chave utilizada pelo Angular para enviar os dados para o backend. Assim, a primeira linha do controller acessa a chave data
e as linhas seguintes acessam os valores numero1
e numero2
já como elementos do vetor data
. O restante do código não muda em relação ao backend para as requisições GET.
Frontend
O Frontend muda pouco em relação às requisições GET: ao invés de utilizar a função get()
do serviço $http
, é usada a função post()
; ao invés de utilizar o atributo params
do objeto de configuração, usa-se o atributo data
:
angular.module('silex-request-get', [])
.controller('Home', function($scope, $http){
$scope.somar = function() {
$http.post('/livro-web-codigo-fonte/backend/request-angular-post/', {
data: {numero1 : $scope.numero1, numero2 : $scope.numero2}
}).then(function(response){
$scope.resultado = response.data;
});
};
});
Aplicativo Advanced REST Client
O aplicativo Advanced REST Client para o Google Chrome (https://chrome.google.com/webstore/detail/advanced-rest-client/hgmloofddffdnphfgcellkdfbfbjeloo) é outra forma de gerar requisições via navegador e testar a comunicação com o backend.
Após instalar o aplicativo realize os seguintes passos:
- Informe a URL (não se esqueça de indicar
/
ao final, pois representa a rota) - Escolha "POST" como o tipo da requisição
- Na seção Payload, na aba Raw, informe o conteúdo da requisição (em formato JSON)
- Escolha "application/json" como codificação da requisição
- Clique no botão "Send"
Sobre o conteúdo da requisição, deve ser informado da mesma forma com o Angular o faria (já que o backend está esperando este formato). Assim, o conteúdo deve ser JSON, como o exemplo:
{"data":{"numero1":1,"numero2":3}}
A figura a seguir ilustra este processo (animação GIF disponível apenas na versão online deste livro).
Assim, o aplicativo Advanced REST Client para o Google Chrome pode ser usado como alternativa para criar clientes de backends construídos com Silex e outros frameworks para o PHP ou outras plataformas de programação.