How to use $_GET parameter to make seo friendly ur

2019-02-11 03:34发布

问题:

I am using a PHP CMS that I've made myself. It fetches the $_GET parameter url and turns it into www.website.com/{url}. This CMS uses the $_GET parameter to get the file. So, if the url is index, then the CMS searches for the file index and returns the contents of the file. But now, I'm expanding the CMS to have an addition parameter like profile/{username}. How can I expand on it? I want my URL to say www.website.com/profile/{username}. How would I go about doing this? This is my current htaccess:

RewriteEngine On  
RewriteRule ^(|/)$ index.php?url=$1  
RewriteRule ^([a-zA-Z0-9_-]+)(|/)$ index.php?url=$1a

Here is the TPL system.

public function addTpl() {     
    global $zip;

    if(!isset($_GET['url']) || empty($_GET['url'])) {
        $_GET['url'] = 'index';
    }

    if(file_exists('_zip/_templates/_front/'. $zip['Template']['Front'] . '/')) {
        if(file_exists('_zip/_templates/_front/'. $zip['Template']['Front'] . '/' . secure($_GET['url']) . '.php')) {
            ob_start();
            include('_zip/_templates/_front/'. $zip['Template']['Front'] . '/' . secure($_GET['url']) . '.php');
            $this->tpl .= ob_get_contents();
            ob_end_clean();
        } else {
            die(zipError('File Not Found', 'The file <b>' . secure($_GET['url']) . '</b> could not be found. Please re-check the URL; If you were directed here using a link, please report that link.'));
        }
    } else {
        die(zipError('Template Not Found', 'The template <b>' . $zip['Template']['Front'] . '</b> could not be found. Please check your configuration file for a mistake.'));
    }
}

Is there any other information I need to provide? I need to get this done ASAP, so any advice would be greatly appreciated.

回答1:

php_nub_qq's answer is cleaner: you would be better off in the long-run doing this by using $_SERVER['REQUEST_URI'] instead of adding more rewrite rules every time you want to add a new subdivision in your CMS. But I've answered below anyway assuming you don't want to change your existing code too much since you're under the gun.

Also you're going to large lengths to avoid setting any variables in addTpl(). This is for good reason, as php_nub_qq also already pointed out, which is to avoid any variables getting set in the child template that would violate encapsulation. But that is a cumbersome restraint now that you have to add more logic to that method, so you should probably factor out the template inclusion to a private method. Then you can do whatever complicated logic in addTpl() you want. To avoid setting any variables at all in the template file except for $this, you can set the path to the template file on the template object itself and use that when passing it to your template inclusion method.

So, you would add another rewrite rule:

RewriteRule ^profile/([a-zA-Z0-9_-]+)(|/)$ index.php?username=$1

Edit: I removed the extra slash at the start of the regex that broke this.

That will set the username key in $_GET, which you can use to switch the template to load. Then inside whatever class addTpl() is in do the following (This also assumes you change your config to add a $zip['Template']['Profile'] that works similar to $zip['Template']['Front'] to set the dir for profile templates:

class Template {
    public $tpl = '';
    private $_template_file;

    public function addTpl() {     
        global $zip;

        if(!isset($_GET['url']) || empty($_GET['url'])) {
            $_GET['url'] = 'index';
        }

        $top_dir = '_zip/_templates/';
        $type_dir = '_front/';
        $configured = $zip['Template']['Front'];
        $file = $_GET['url'];

        // Check username val and use custom template:
        if (!empty($_GET['username'])) {
            $type_dir = '_profile/';
            $configured = $zip['Template']['Profile']; // assuming you're configuring profile templates
            $file = $_GET['username'];
        }

        $full_dir = $top_dir . $type_dir . $configured . '/';
        if(file_exists($full_dir)) {
            $full_file = $full_dir . secure($file) . '.php';
            if(file_exists($full_file)) {
                $this->_template_file = $full_file;
                $this->tpl .= $this->loadTemplate();
            } else {
                die(zipError('File Not Found', 'The file <b>' . secure($file) . '</b> could not be found. Please re-check the URL; If you were directed here using a link, please report that link.'));
            }
        } else {
            die(zipError('Template Not Found', 'The template <b>' . $configured . '</b> could not be found. Please check your configuration file for a mistake.'));
        }
    }

    private function loadTemplate() {
        ob_start();
        include($this->_template_file);
        $result = ob_get_contents();
        ob_end_clean();
        return $result;
    }
}


回答2:

You can have the second parameter ( {username} ) be a local variable before you include the file, in which you can then access it as an ordinary variable. This is not a good thing to do if you're working with a team.

EDIT:

What you can do is the following

RewriteEngine On  
RewriteRule ^ index.php

Then in index.php you can have this

$url = str_replace('index.php','', $_SERVER['PHP_SELF']);
$url = str_replace($url,'',$_SERVER['REQUEST_URI']);
$url = explode('/',$url);
$page = array_shift($url);
foreach ($url as $val){
    $args[] = urldecode($val);
}

Now if you open the link www.website.com/profile/someuser/about you will have

$page = 'profile'
$args[0] = 'someuser'
$args[1] = 'about'

And so on you can have as much arguments as you like.