Search code examples
php.htaccessdirectory-structure

Clean url in php mvc


In first .htaccess,I send url to public/index.php:

RewriteEngine On
RewriteCond %{REQUEST_FILENAME} -s [OR]
RewriteCond %{REQUEST_FILENAME} -l [OR]
RewriteCond %{REQUEST_FILENAME} -d

RewriteRule ^.*$ - [NC,L]
RewriteRule ^.*$ public/index.php [NC,L]

And my public/index.php:

<?php
// define root path of the site
if(!defined('ROOT_PATH')){
define('ROOT_PATH','../');
}

require_once ROOT_PATH.'function/my_autoloader.php';

use application\controllers as controllers;

 $uri=strtolower($_SERVER['REQUEST_URI']);
 $actionName='';
 $uriData=array();
 $uriData=preg_split('/[\/\\\]/',$uri );

 $actionName = (!empty($uriData[3])) ? preg_split('/[?].*/', $uriData[3] ): '' ;
 $actionName =$actionName[0];
 $controllerName = (!empty($uriData[2])) ? $uriData[2] : '' ;

 switch ($controllerName) {
case 'manage':
    $controller = new Controllers\manageController($controllerName,$actionName);
    break;
default:
    die('ERROR WE DON\'T HAVE THIS ACTION!');
    exit;
    break;
  }

// function dispatch send url to controller layer 
$controller->dispatch();
?>

I have this directory :

  • application
    • controller
    • models
    • view
  • public
    • css
    • java script
    • index.php
  • .htaccess

I want to have clean URL for example localhost/lib/manage/id/1 instead of localhost/lib/manage?id=1,what should I do ?


Solution

  • Using your current rewrite rules, everything is already redirected to your index.php file. And, as you are already doing, you should parse the URL to find all these URL parameters. This is called routing, and most PHP frameworks do it this way. With some simple parsing, you can transform localhost/lib/manage/id/1 to an array:

    array(
        'controller' => 'manage',
        'id' => 1
    )
    

    We can simply do this, by first splitting the URL on a '/', and then looping over it to find the values:

    $output = array();
    $url = split('/', $_SERVER['REQUEST_URI']);
    // the first part is the controller
    $output['controller'] = array_shift($url);
    
    while (count($url) >= 2) {
        // take the next two elements from the array, and put them in the output
        $key = array_shift($url);
        $value = array_shift($url);
        $output[$key] = $value;
    }
    

    Now the $output array contains a key => value pair like you want to. Though note that the code probably isn't very safe. It is just to show the concept, not really production-ready code.