Oop php front controller issue

后端 未结 2 1038
Happy的楠姐
Happy的楠姐 2021-01-28 11:01

I have a problem building a front controller for a project I have at school. Here is the thing, i created several controllers per entities i.e. One to select, another one to del

相关标签:
2条回答
  • 2021-01-28 11:28

    You will want to build a basic router, what it does.

    A router will parse the path and take parts of it and locate a controller file. And then run a method in that file with arguments. We will use this format for urls

      www.yoursite.com/index.php/{controller}/{method}/{args}
    

    So for this example our url will be

      www.yoursite.com/index.php/home/index/hello/world
    

    the index.php can be hidden using some basic .htaccess ( Mod Rewrite )

    So lets define some things, first we will have folders

    -public_html
      index.php
      --app
        ---controller
           home.php
    

    So the main folder is public_html with the index.php and a folder named app. Inside app is a folder named controller and inside that is our home.php contoller

    Now for the Code ( yea )

    index.php (basic router )

    <?php
    //GET URI segment from server, everything after index.php ( defaults to home )
    $path_info = isset( $_SERVER['PATH_INFO'] ) ? $_SERVER['PATH_INFO'] : '/home';
    //explode into an array - array_filter removes empty items such as this would cause  '/home//index/'  leading /, trailing / and // double slashes.
    $args = array_filter( explode('/', $path_info) );
    
    $controller_class = array_shift($args); //remove first item ( contoller )
    $method = count( $args ) > 0 ? array_shift($args) : 'index'; //remove second item or default to index ( method )
    
    $basepath = __DIR__.'/app/controller/'; //base path to controllers
    
    if(!file_exists($basepath.$controller_class.".php") ){
        echo "SHOW 404";
        exit();
    }
    
    //instantiate controller class
    require_once $basepath.$controller_class.".php";
    $Controller = new $controller_class;
    
    //check if method exists in controller
    if(!method_exists( $Controller, $method ) ){
        echo "Method not found in controller / or 404";
        exit(); 
    }
    
    //call methods with any remaining args
    call_user_func_array( [$Controller, $method], $args);
    

    home.php ( controller )

    <?php
    
    class home{
    
        public function index( $arg1="", $arg2=""){
            echo "Arg1: ".$arg1 . "\n";
            echo "Arg2: ".$arg2 . "\n";
        }
    
        public function test( $arg1 = "" ){
            echo "Arg1: ".$arg1 . "\n";         
        }   
    }
    

    Now if you put in any of these urls

      www.yoursite.com/index.php
      www.yoursite.com/index.php/home
      www.yoursite.com/index.php/home/index
    

    It should print ( defaults )

      Arg1: 
      Arg2: 
    

    If you do this url

      www.yoursite.com/index.php/home/index/hello/world
    

    It should print

     Arg1: hello
     Arg2: world
    

    And if you do this one

      www.yoursite.com/index.php/home/test/hello_world
    

    it would print

      Arg1: hello_world
    

    The last one, running in the second method test ( no echo arg2 ), this way you can see how we can add more controllers and methods with only having to code them into a controller.

    This method still allows you to use the $_GET part of the url, as well as the URI part to pass info into the controller. So this is still valid

      www.yoursite.com/index.php/home/test/hello_world?a=1
    

    and you could ( in home::test() ) output the contents of $_GET with no issues, this is useful for search forms etc. Some pretty url methods prevent this which is just ... well ... crap.

    In .htaccess with mod rewrite you would do this to remove index.php from the urls

    <IfModule mod_rewrite.c>
      RewriteEngine On
      RewriteCond %{REQUEST_FILENAME} !-f
      RewriteCond %{REQUEST_FILENAME} !-d
      RewriteRule ^(.*)$ index.php?/$1 [L]
    </IfModule>
    

    Then you can use urls without the index.php such as this

      www.yoursite.com/home/index/hello/world
    

    This is the simplest Router I could come up with on such short notice, yes I just created it. But this is a very similar ( although simplified ) implementation used in many MVC frameworks

    PS. please understand how this is all done, so you actually learn something...

    Many improvements could be made, such as allowing these urls

       www.yoursite.com/hello/world
    
       www.yoursite.com/home/hello/world
    
       www.yoursite.com/index/hello/world
    

    Which would all fall back to the a default of home controller and index method, but that would take some additional checks (for not found files and methods ) I cant be bothered with right now...

    0 讨论(0)
  • 2021-01-28 11:50

    Here's a simple demo process (won't work, just an example).

    index.php

    //Say you called /index.php/do/some/stuff
    $route = $_SERVER["PATH_INFO"]; //This will contain /do/some/stuff
    
    $router = new Router();
    $router->handle($route);
    

    router.php

    class Router {
         private static $routeTable = [
             "do/some/stuff" => [ "DoingSomeController" => "stuff" ]
         ];
    
         public function handle($route) {
              if (isset(self::$routeTable[trim($route,"/"])) {
                  $controller = new self::$routeTable[trim($route,"/"][0];
                  call_user_func([$controller,self::$routeTable[trim($route,"/"][1]]);
    
              }
         }
    }
    

    Basic demo, what some frameworks do.

    0 讨论(0)
提交回复
热议问题