how to make a htaccess rule from id to name

I have a list of unique data:

Suppose I have the following data:

id    name
1     Jhon
2     Peter 
3     Mark
4     Scotty
5     Marry

I make a .htaccess rule for id :

RewriteRule brandlisting/(.*)/ site/brandlisting?id=$1 [L]
RewriteRule brandlisting/(.*) site/brandlisting?id=$1 [L]

my URL is:

http://localhost/mate/admin/site/brandlisting/3

this works for id.

Now I need a .htaccess rule for name, so I make a rule for it:

RewriteRule brandlisting/(.*)/ site/brandlisting?name=$1 [L]
RewriteRule brandlisting/(.*) site/brandlisting?name=$1 [L]

http://localhost/mate/admin/site/brandlisting/Mark

When I used the above URL I was faced with following error in the console:

"NetworkError: 400 Bad Request - http://localhost/mate/admin/site/brandlisting/Mark"

and in browser it shows:

Error 400 Your request is invalid.

My current .htaccess file

RewriteEngine on

RewriteCond %{HTTP_HOST} ^localhost/mate/admin$ [NC,OR]
RewriteCond %{HTTP_HOST} ^localhost/mate/admin$

RewriteCond %{REQUEST_URI} !wordpress/
RewriteRule (.*) /wordpress/$1 [L]

Options +FollowSymLinks -MultiViews
RewriteEngine On

RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule .* index.php/$0 [PT,L]

#RewriteRule brandlisting/(.*)/ site/brandlisting?id=$1 [L]
#RewriteRule brandlisting/(.*) site/brandlisting?id=$1 [L]

RewriteRule brandlisting/(.*)/ site/brandlisting?name=$1 [L] 
RewriteRule brandlisting/(.*) site/brandlisting?name=$1 [L] 

.htaccess rules rely on order. If you anticipate using a lot of routes, keep your htaccess rules simple and put your routes into PHP instead, using one of the several already written routing frameworks.

Here's an explanation as to why your .htaccess file isn't working, line-by-line:

RewriteEngine on

This turned the RewriteEngine on. No problems so far.

RewriteCond %{HTTP_HOST} ^localhost/mate/admin$ [NC,OR]
RewriteCond %{HTTP_HOST} ^localhost/mate/admin$    
RewriteCond %{REQUEST_URI} !wordpress/

Only match RewriteRule is it's WordPress. This seems to be working, so let's ignore this block of rules.

RewriteRule (.*) /wordpress/$1 [L]

Options +FollowSymLinks -MultiViews

RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d

Only match below if the requested filename is not a file or a directory.

RewriteRule .* index.php/$0 [PT,L]

Rewrite any path PATH to index.php/ PATH . Stop processing if it matched (note the L as last ). That means nothing below will be activated.

#RewriteRule brandlisting/(.*)/ site/brandlisting?id=$1 [L]
#RewriteRule brandlisting/(.*) site/brandlisting?id=$1 [L]

RewriteRule brandlisting/(.*)/ site/brandlisting?name=$1 [L] 
RewriteRule brandlisting/(.*) site/brandlisting?name=$1 [L] 

Assuming that it doesn't match .* (aka, never), check path for other patterns. Note also that the two lines you have commented, and the two lines you don't, both match the same pattern. If one worked, the other would not.

-- Pro Tip: Regex has a shorthand for including a rule with a trailing slash and without one: /? is equivalent to, either with one slash, or with no slashes. Another way to write this is /{0,1} .

How to Fix

.htaccess redirect rules are a pain. My rule of thumb is to make them as easy as possible to write, which makes them easy to read and to maintain. How to do this? Push the redirect logic to your PHP program, rather than forcing Apache to rely on it.

Solution 1

The htaccess -only approach here would be to ensure you understand what Apache rewrite flags are telling your server to do, and adjust accordingly. You can do this here one of two ways:

  • Make your more specific rules show up first. ie, move /site/brandlisting?name=$1 rules to before .* rules.

  • Add a separate rewrite conditions for any followup processing. As per the Apache2 documentation linked above:

  • The [L] flag causes mod_rewrite to stop processing the rule set. In most contexts, this means that if the rule matches, no further rules will be processed. This corresponds to the last command in Perl, or the break command in C. Use this flag to indicate that the current rule should be applied immediately without considering further rules.

    The key point here is that it is within each rule set . Building a new rule set will continue processing.

    Example that should work (not tested):

    RewriteEngine on
    
    RewriteCond %{HTTP_HOST} ^localhost/mate/admin$ [NC,OR]
    RewriteCond %{HTTP_HOST} ^localhost/mate/admin$
    
    RewriteCond %{REQUEST_URI} !wordpress/
    RewriteRule (.*) /wordpress/$1 [L]
    
    Options +FollowSymLinks -MultiViews
    RewriteEngine On
    
    RewriteEngine on
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule .* index.php/$0 [PT,L]
    
    #New Rule Set
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    
    # Note that /? is the same as writing two separate rules,
    # one with a slash at the end, and one without.
    RewriteRule brandlisting/(.*)/? site/brandlisting?name=$1 [L] 
    

    There are some great pre-built routers out there, like Silex and Slim. If you don't want to use them, you can still use your own internal logic that parses various pieces. From my experience, the more that I can pull out of my .htaccess file, the happier you'll be. It winds up being far easier to debug issues, and it's easier to iterate changes without introducing unintended consequences.

    Solution 2

    You can use PHP routers in conjunction with the .htaccess file I provided above, like so:

    // Slim example
    $app = new SlimSlim();
    $app->get('/brandlisting/:key', function ($key) {
        if (is_numeric($key)) {
            $id = $key;
            // call/run $id logic
        } else {
            $name = $key;
            // call/run $name logic
        }
    });
    // ...
    $app->run();
    

    If you do this, you can remove any of your brandlisting logic from .htaccess and instead put it into your index.php .

    Conclusion

    If you can help it, experience tells me that it's better to not write your app logic into .htaccess rules. Instead, make your .htaccess rules simple and use a routing library. If you want to use .htaccess , make sure you understand the Apache rewrite flags you're using, and that Apache reads everything from top to bottom. For example, if the [L] flag is used, Apache stops reading all other rules in the rule set . That means, you have to create a new rule set with additional rules that need to be processed, or put your more specific rules first. Keep in mind that, if those rules have an [L] flag, they will also stop execution of any subsequent rules.


    I am starting with your current .htaccess you have crunch all the available rule which meets your needs in one single .htaccess for example rule for wordpress it should be in directory where your wordpress is installed.

    Your rule as per your requirement should be like this if you are trying in root directory,

    RewriteEngine on
    
    RewriteBase /mate/admin/
    
    RewriteRule site/brandlisting/([d]+)/?$ site/brandlisting.php?id=$1 [L]
    RewriteRule site/brandlisting/([a-zA-Z]+)/?$ site/brandlisting.php?name=$1 [L]
    

    And for wordpress you directory you can create seperate .htaccess where you can put your rule index.php.


    You can use redirect here.

    Assuming you have the following folders:

    <server root>/mate/admin
    

    place in .htaccess in mate/admin

    RewriteBase /mate/admin/
    RewriteRule "site/brandlisting/([^]+)/" "site/brandlisting?id=$1" [R,L]
    RewriteRule "site/brandlisting/([^]+)" "site/brandlisting?id=$1" [R,L]
    
    链接地址: http://www.djcxy.com/p/94756.html

    上一篇: 将导航抽屉添加到现有活动

    下一篇: 如何制作从id到名称的htaccess规则