Rewrite rules in . htacess
RewriteEngine on
RewriteBase /
# Redirect Trailing Slashes.
RewriteRule ^(.*)/$ $1 [L,R=301]
RewriteCond %{SCRIPT_FILENAME} !-f
RewriteCond %{SCRIPT_FILENAME} !-d
RewriteRule (.+) /
DirectoryIndex index.php
The rule is simple. Simply send the entire query to the file defined as directory index (Document root / directory index). In the above case, the index.php file
With this you can manipulate the URL query as you want, without creating new rules for each new parameter.
In index.php, just receive the query and make the appropriate treatments.
In this example below, I took parts of a particular framework that I have been developing for many years. The part that abstracts URI and GET and POST parameters, converted to a procedural style, no use of classes, Oop, etc. So that beginners understand and take advantage.
/*
Define a base da URL.
Caso queria executar num subfolder, basta especificar aqui.
Exemplo, http://localhost/pastateste/index.php
$href_base = '/pastateste/';
*/
$href_base = '/';
/*
Define o arquivo índice. Pode definir um arquivo diferente do definido em document root ou directory index seja u
Exemplo, http://localhost/pastateste/outro.php
$file_base = 'outro.php';
*/
$file_base = 'index.php';
$rs['path'] = null;
$rs['query'] = null;
$rs['post'] = null;
/*
Verifica em qual ambiente está sendo executado este script.
Tudo que começar com "cli", indica que está sob Command Line Interface.
*/
$cli_mode = ((substr(PHP_SAPI, 0, 3) == 'cli')? true : false);
$uri = (isset($_SERVER['REQUEST_URI'])? $_SERVER['REQUEST_URI'] : (isset($_SERVER['argv'][1])? $_SERVER['argv'][1] : ''));
$arr = parse_url($uri);
if (isset($arr['path']) && !empty($arr['path'])) {
$rs['path'] = $arr['path'];
unset($arr['path']);
/**
Checking for base path and remove it.
*/
if (strpos($rs['path'], $href_base) === 0) {
$rs['path'] = substr($rs['path'], strlen($href_base));
}
/**
Checking for file base path and remove it.
*/
if (strpos($rs['path'], $file_base) === 0) {
$rs['path'] = substr($rs['path'], strlen($file_base));
$rs['path'] = trim($rs['path'], '/');
}
/**
Convert the parameter to array.
*/
if (!empty($rs['path'])) {
$rs['path'] = explode('/', $rs['path']);
}
}
/**
Convert the URI query to array.
*/
if (isset($arr['query']) && !empty($arr['query'])) {
parse_str($arr['query'], $rs['query']);
}
/**
Get the POST array.
*/
if (isset($_POST) && !empty($_POST)) {
$rs['post'] = $_POST;
}
/*
Contém os dados extraídos da query uri
Exemplo: http://localhost/foo/bar
Retornará
array(0 => 'foo', 1 => 'bar')
*/
print_r($rs['path']);
/*
Contém os dados extraídos da variável global $_GET
Exemplo: http://localhost/?foo=1&bar=2
Retornará
array('foo' => 1, 'bar' => 2)
*/
print_r($rs['query']);
/*
Contém os dados extraídos da variável global $_GET
Exemplo:
<form action="http://localhost/" method="POST">
<input type="hidden" name="foo" value="1" />
<input type="hidden" name="bar" value="2" />
<input type="submit" value="send" />
</form>
Retornará
array('foo' => 1, 'bar' => 2)
*/
print_r($rs['post']);
In short, the interesting result will be inside the array $rs
. Just handle this array as you wish.
Invoking the rescued URI class and method
Taking the example of the question site/index.php?ato=conta'fazerlogin
.
I do not recommend doing this way using a single quote character as tab.
In the example I posted, it would be enough to do so
http://site/conta/fazerlogin
Then this query data would be rescued in $rs['path']
.
To call the class:
/*
Obviamente precisamos verificar se os parâmetros existem:
*/
if (
isset($rs['path'][0])
&& isset($rs['path'][1])
) {
$c = trim($rs['path'][0]);
$m = trim($rs['path'][1]);
} else {
/*
Isso aqui é para testes somente. Faça o tratamento adequado conforme o seu caso.
Recomendo que direcione para uma classe padrão.
*/
echo 'classe ou méotodo não informado'; exit;
}
if (
!empty($c)
&& !empty($m)
) {
if (class_exists($c)) {
/*
Aqui usamos o Reflection para poder instanciar um objeto caso não seja estático. Se for estático, será executado estaticamente.
*/
$reflection = new \ReflectionMethod($c, $m);
/*
Aqui também tomamos cuidado para checar se o método é publico.
O método deve ser definido como público para ser acessível.
*/
if ($reflection->isPublic()) {
if ($reflection->isStatic()) {
/*
Invoca de forma estática.
*/
$data = $c::$m();
} else {
/*
Invoca como instância.
*/
$c = new $c;
$data = $c->$m();
}
print_r($data);
} else {
/*
Isso aqui é para testes somente. Faça o tratamento adequado conforme o seu caso.
A decisão aqui depende de opinião pessoal. Avalie o que deseja fazer aqui pois pode-se aceitar um método inexistente ou negar a requisição. Isso dependerá do seu modelo de negócios.
Note que não foi necessário preocupar-se com method_exists(), pois a classe ReflectionMethod já faz esse trabalho.
*/
echo 'classe ou método vazios'; exit;
}
} else {
/*
Isso aqui é para testes somente. Faça o tratamento adequado conforme o seu caso.
Recomendo que direcione para uma classe que retorne um aviso de página inexistente ao usuário.
Aqui por exemplo, pode invocar uma classe que emita um http status 404 not found.
Claro que, se estiver trabalhando com design MVC, faça tudo dentro de sua respectiva camada.
*/
echo 'classe ou méotodo vazios'; exit;
}
} else {
/*
Isso aqui é para testes somente. Faça o tratamento adequado conforme o seu caso.
Recomendo que direcione para uma classe padrão.
*/
echo 'classe ou méotodo vazios'; exit;
}
class conta
{
public function fazerlogin()
{
return 'aqui retorna o for necessário';
}
}
Additional script resources that abstract the parameters of the URI query.
The script is compatible with command line executions (cli)
C:\pasta\onde\instalou\o\php\php.exe C:\www\site\index.php conta/fazerlogin
Fake URL Rewrite (fake url rewriting).
http://site/index.php/conta/fazerlogin
Normal URL. (This part is not demonstrated in the above scripts)
http://site/index.php/?p=conta/fazerlogin
Observing
The above examples are purely didactic.
I tried to demonstrate in a very brief way how to abstract the URI query in a "universal" way, where we can also take advantage of the same routines in different environments.
For a more complete example, the answer would become 2 or 3 times more extensive. However, with the examples above we can see how such a simple task is actually quite complex.
The ideal is to assemble this all in OOP so that it reuses the routines and optimize the executions.
To get a sense of how to further complicate, imagine business models where you need to attach specific parameters at the beginning or end of the query. An example in the real world is to add a parameter that identifies the language of the UI.
Example http://localhost/en/conta/fazerlogin
And at the same time also allow to ignore the language parameter
Example http://localhost/conta/fazerlogin
When not finding the parameter, the router would sign a default value and at the same time, it cannot conflict with the order of the other parameters.
I couldn’t understand the url
site/index.php?ato=conta'editarusuario&id=2
, could correct?– Guilherme Nascimento
Here’s what you need: http://answall.com/search?q=url+friendly
– Bacco
@I believe he’s using the
'
as a separator– Bacco
@Bacco if it is this is very confusing, Ivcs I know it will seem exaggerated my, but have you ever thought of using some route system ready, as framewroks like the Laravel, Lumen or cakephp?
– Guilherme Nascimento
@Guilhermenascimento or the old and good explodes :D - This technique is underused, but I find it much cleaner to pass thing by parameter. example.com/route.php/clothes/T-shirts
– Bacco
MVC has nothing to do with URL friendly.
– Daniel Omine
And great chance to be duplicate of some of the 2103467463 questions about htaccess.
– Bacco
@Guilhermenascimento seems so, but when I spoke of the explosion, I did not refer to the question, but to the example I gave. His is by parameter, so ' doesn’t help much. I think it’s totally cool without parameters.
– Bacco
@Guilhermenascimento In PATH_INFO, which takes only what comes after . php
– Bacco
I was afraid to answer, but I went to the mat and posted.. rsrsr
– Daniel Omine
The ' is a separator even, I’m using it because the rest of the team is beginner and could put invalid parameters, so it is more standardized. I had already searched here and elsewhere, I found some files, edited to frame the project but only gives the Bad Internet. About MVC, there really has to be nothing, but since the file structure is different, the examples I found stood out. About the frameworks I’ve never heard of, I’m not using framework, it was worth the tip.
– Leonardo