Manage URL routes in own php framework

2019-03-12 22:52发布

I'm creating a PHP Framework and I have some doubts...

The framework takes the url in this way: http:/web.com/site/index

It takes the first parameter to load controller (site) and then loads the specific action (index).

If you've installed the framework in a base URL works ok, but if you install it in a subfolder like this: http://web.com/mysubfolder/controller/action

My script parses it as controller = mysubfolder and action = controller.

If you have more subfolders the results will be worst.

This is my Route code:

Class Route
{
    private $_htaccess = TRUE;
    private $_suffix = ".jsp";

    public function params()
    {
        $url='';

        //nombre del directorio actual del script ejecutandose.
        //basename(dirname($_SERVER['SCRIPT_FILENAME']));

        if($this->_htaccess !== FALSE):
            //no está funcionando bien si está en un subdirectorio web, por ej stynat.dyndns.org/subdir/
            // muestra el "subdir" como primer parámetro
            $url = $_SERVER['REQUEST_URI'];
            if(isset($_SERVER['QUERY_STRING']) && !empty($_SERVER['QUERY_STRING'])):
                $url = str_replace("?" . $_SERVER['QUERY_STRING'], '',$url);
            endif;
        else:
            if(isset($_SERVER['PATH_INFO'])):
                $url = $_SERVER['PATH_INFO'];
            endif;
        endif;

        $url = explode('/',preg_replace('/^(\/)/','',$url));
        var_dump($url);

        var_dump($_GET);

    }
}

Thanks for any help you can give.

12条回答
Emotional °昔
2楼-- · 2019-03-12 23:37

basically grab the url string after your first slash, and then explode it into an array (i use '/' as a delimiter).

then carefully array_shift off your elements and store them as variables

item 0: controller
item 1: the action / method in that controller
item 2 thru n: the remaining array is your params
查看更多
手持菜刀,她持情操
3楼-- · 2019-03-12 23:40

This is how i implemented loader.php

   <?php
/*@author arun ak
auto load controller class and function from url*/
class loader
{
    private $request;
    private $className;
    private $funcName;

    function __construct($folder    = array())
    {   
        $parse_res  = parse_url($this->createUrl());
        if(!empty($folder) && trim($folder['path'],DIRECTORY_SEPARATOR)!='')
         {
            $temp_path  = explode(DIRECTORY_SEPARATOR,trim($parse_res['path'],DIRECTORY_SEPARATOR));
            $folder_path    = explode(DIRECTORY_SEPARATOR,trim($folder['path'],DIRECTORY_SEPARATOR));
            $temp_path      = array_diff($temp_path,$folder_path);

                if(empty($temp_path))
                {
                    $temp_path =    '';
                }
         }else
         {
            if(trim($parse_res['path'],DIRECTORY_SEPARATOR)!='')
            {
             $temp_path = explode(DIRECTORY_SEPARATOR,trim($parse_res['path'],DIRECTORY_SEPARATOR));
            }
                 else
             $temp_path ='';
         }
        if(is_array($temp_path))
        {   
            if(count($temp_path) ==1)
            {
                array_push($temp_path,'index');
            }
            foreach($temp_path as $pathname)
            {   
                $this->request .= $pathname.':';
            }
        }
        else $this->request = 'index'.':'.'index';

    }

 private function createUrl()
 {  
    $pageURL  = (@$_SERVER["HTTPS"] == "on") ? "https://" : "http://";
    $pageURL .= $_SERVER["SERVER_NAME"].$_SERVER["REQUEST_URI"];
    return $pageURL;
 }
 public function autolLoad()
 {
    if($this->request) 
    {   
        $parsedPath = explode(':',rtrim($this->request,':'));
        if(is_file(APPLICATION_PATH.DIRECTORY_SEPARATOR.'controllers'.DIRECTORY_SEPARATOR.$parsedPath[0].'_controller'.'.php'))
        {
            include_once(APPLICATION_PATH.DIRECTORY_SEPARATOR.'controllers'.DIRECTORY_SEPARATOR.$parsedPath[0].'_controller'.'.php');
            if(class_exists($parsedPath[0].'_controller'))
            {
                $class  = $parsedPath[0].'_controller';
                $obj    = new $class();
                //$config       = new config('localhost','Winkstore','nCdyQyEdqDbBFpay','mawinkcms');
                //$connect  =  connectdb::getinstance();
                //$connect->setConfig($config);
                //$connection_obj = $connect->connect();
                //$db               = $connect->getconnection();//mysql link object
                //$obj->setDb($db);
                $method = $parsedPath[1];
                if(method_exists ($obj ,$parsedPath[1] ))
                {
                    $obj->$method();
                }else die('class method '.$method.' not defined');

            }else die('class '.$parsedPath[0]. ' has not been defined' );

        } else die('controller not found plz define one b4 u proceed'.APPLICATION_PATH.DIRECTORY_SEPARATOR.'controllers'.DIRECTORY_SEPARATOR.$parsedPath[0].'.php');

     }else{ die('oops request not set,i know tis is not the correct way to error :)'); }
 }

}

Now in my index file

//include_once('config.php');
include_once('connectdb.php');
require_once('../../../includes/db_connect.php');
include_once('view.php');
include_once('abstractController.php');
include_once('controller.php');
include_once('loader.php');
$loader = new loader(array('path'=>DIRECTORY_SEPARATOR.'magsonwink'.DIRECTORY_SEPARATOR.'modules'.DIRECTORY_SEPARATOR.'admin'.DIRECTORY_SEPARATOR.'atom'.DIRECTORY_SEPARATOR));
$loader->autolLoad();

I haven't used the concept of modules.only controller action and view are rendered.

查看更多
可以哭但决不认输i
4楼-- · 2019-03-12 23:44

If I am understanding what you are after correctly, then one solution may be to carry on doing what you are doing, but also get the path of the main routing script (using realpath() for example).

If the last folder (or folder before that etc) matches the beginning URL item (or another section), you ignore it and go for the next one.

Just my 2 cents :-).

查看更多
别忘想泡老子
5楼-- · 2019-03-12 23:45

Forget about "reinventing the wheel is wrong" claims. They don't have to use our wheels. I walked on the same road a while ago and i'm totally grateful what i get... i hope you will too

When it comes to the answer to your specific problem -which if faced too- there is a very easy solution. it's a new line in .htaccess at root folder...

Just add line below to your root .htaccess file ; (if your subfoler is "subfolder" )

RewriteRule subfolder/ - [L]

This will leave apart this folder from rewriting directives

By using this way you can install as many instances of your framework as you wish. But if you want this to be framework driven then you have to create/change .htaccess within your framework.

查看更多
唯我独甜
6楼-- · 2019-03-12 23:46

Even if you are creating your own framework, there is no reason not to reuse robust, well tested and documented components, like this Routing component.

Just use Composer, which has become the standard for dependency management in PHP, and you'll be fine. Add as many components as you want to your stack.

And here you have a must read guide on how to make your own framework.

查看更多
三岁会撩人
7楼-- · 2019-03-12 23:46

Within the application configuration script place a variable which will be set to the path the application runs at.

An alternative is to dynamically set that path.

Before the part

$url = explode('/',preg_replace('/^(\/)/','',$url));

strip the location (sub-folder) path out of the $url string using the predefined application path.

查看更多
登录 后发表回答