0

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 delete etc... and this for posts and comments. So i have 6 controllers and then I'm being asked to build front controller above these controllers but i keep on adding layers (route all to index.php then from there I instantiate the front controller which then will send the request to the related controller with header(location:...) and it gets messy and very complicated because for some of the request i need to pass some ids in the url for the db request... I can't use any framework so is there a cleaner way to build a front controller that can handle request with parameters in the url and some without? Do i have to route everything to a single page (with htaccess i created a simple rule to send everything to index.php)? And then from there again instantiate the front controller? If you need some code I'll share this with you but it's a mess :)

Thanks guys, i need advise I'm kind of lost at this point

2
  • So basically your front controller is more of a router than a controller? Don't redirect, just instantiate and call other controller methods from the "front controller" if it is more of a router. Commented Jun 30, 2017 at 7:45
  • Yes indeed it's more of a router than a controller as such! But then i need to build classes for the other controllers e.g. Using a constructor? because there role is to instantiate methods from specific classes(method to select, insert, hydrate etc...) Commented Jun 30, 2017 at 8:23

2 Answers 2

2

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...

Sign up to request clarification or add additional context in comments.

4 Comments

Sure, glad I could help. Just learn from it, more the method and reasoning, then the code...
PS, a URL is a real path to a physical address, a URI is an imaginary path to a physical address ( at least that's how I define the 2 )
But thanks because it's hard to find good materials on that to be really honest
I've written a few of these over the years, and I am currently building an event driven framework ( slowly building it ... lol ) when I have time outside of work, github.com/ArtisticPhoenix/Evo
1

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.