Url friendly to MVC

Asked

Viewed 1,281 times

-1

I am trying to create a . htaccess to make the site urls friendly, the page display will always be on index because I am using MVC. I am following a pattern with the ato parameter in the url to indicate which class and method to run. Example

site/index.php? ato=account'fazerlogin

Account is part of the name of my class that calls Controllerconta and fazerlogin is a method of the same.

other examples are:

site/index.php? ato=conta'editarusuario&id=2

Here I call the method to edit the user and pass the user id.

I wanted it to stay that way:

website/account/fazerlogin

site/account/editarusuario/1

I tried in some ways but I will not even put the attempts because they did not work, gave Bad Internet error.

  • I couldn’t understand the url site/index.php?ato=conta'editarusuario&id=2, could correct?

  • Here’s what you need: http://answall.com/search?q=url+friendly

  • @I believe he’s using the ' as a separator

  • @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?

  • @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

  • 2

    MVC has nothing to do with URL friendly.

  • And great chance to be duplicate of some of the 2103467463 questions about htaccess.

  • @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.

  • @Guilhermenascimento In PATH_INFO, which takes only what comes after . php

  • I was afraid to answer, but I went to the mat and posted.. rsrsr

  • 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.

Show 6 more comments

3 answers

1

One of the solutions I use is:

No . htaccess

RewriteEngine On
RewriteBase /

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php/$1 [L]

#Options -Indexes

No index.php

  <?php
  //EXPLODE A URL PASSADA
  $URI = urldecode($_SERVER['REQUEST_URI']);
  $url = explode ("/", $URI);

  var_dump($url); //veja como fica a saída
  ?>

$url becomes an array that contains the path passed in the url.

Example: http://site/page/action

In the $url[0] will have the value: page and in the $url[1] will have the value action

With this you can make the desired Includs and catch the last action.

  • shows the error: Internal Server Error

  • Check whether the Rewritebase is set to the folder that is your index.php. Example: if on my server the example folder is muddy, Rewritebase must be Rewritebase /urlamigaval/

0


In my case what worked was:

<IfModule mod_rewrite.c>

    RewriteEngine On

    RewriteRule ^([a-z]+)/?$ index.php?ato=$1 [NC]
    RewriteRule ^([a-z]+)/([a-z]+)/?$ index.php?objeto=$1&ato=$2 [NC]
    RewriteRule ^([a-z]+)/([a-z]+)/([0-9]+)/?$ index.php?objeto=$1&ato=$2&id=$3 [NC,L]
</IfModule>

0

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.

  • shows the error: Internal Server Error

  • it is expected that mod_rewrite is already properly activated

  • Actually it was not active, some configurations of a software ended up changing, but still did not give.. However I managed to edit the . htaccess and only with it

  • I can’t do anything with information this vague.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.