0

I am having a go at creating a small framework. I am currently busy with my dispatcher object and I am having trouble to logically work out the best practice as to how the dispatcher should tie in the controller and requested view/action.

So far everything works, I am able to create the page controller with an action and doing a echo "test123"; returns perfectly, I am just a little confused as to how to build in the views and to also give the views access to variables assigned in the controller. I have added some comments where I feel I might take the wrong approach.

Some items which bugs me: - I dont quite think I am taking the correct approach regarding require_once() and creating the object instances within the dispatch() method, but I am not sure which other option will work. - I attempt to ensure that the user gets some sort of output either with the requested url, or the referred url or lastly the default controller/action so that I can show a simplified error message within the template of the site, but I also feel I may be duplicating work, any ideas? - I cannot see how I will tie in the views controller (which will output the HTML). Where would I assign variables or values generated in the controller?

Points to note:

  • The dispatcher does not extend any other classes.
  • The selected page controller will extend the master controller, which in return extends to the core controller. I figured the core controller would be the one which will tie up all other classes I want to share between the application like a database class etc, but I am not sure if that even makes sense.

Any ideas on how to improve my dispatcher would greatly be appreciated!

 public function dispatch($user_request) {
    // Receive the user requested controller/action in an array:
    $this->requested_array = $user_request;
    $request_validated = false;
    // Ensure the master controller is available or break gracefully:
    if(!include(CONTROLLERS_DIR."master".CONTROLLER_SUFFIX.".php")) {
        output_message("Unable to load the master controller.", true);
        return false;
    }

    // Verify if the requested controller is available and that it is indeed a class:
    if(file_exists(CONTROLLERS_DIR.$this->requested_array['controller'].CONTROLLER_SUFFIX.".php")) {
        require_once(CONTROLLERS_DIR.$this->requested_array['controller'].CONTROLLER_SUFFIX.".php");
        if(class_exists($this->requested_array['controller'])) {
            // Create object of requested controller:
            $requested_controller_object = new $this->requested_array['controller']();
            // Verify that the requested action/method exists in the controller:
            if(method_exists($requested_controller_object, $this->requested_array['action'])) {
                $request_validated = true;
            }
        }

    } else {
        $this->dispatcher_errors[] = "Unable to locate the requested controller.";
    }

    if($request_validated != true) {
        // Rollback will check if the page has a successful referrer (same application) and assign the previous pages controller/action properties to this request:
        if($this->rollback() != true) {
            // Check if the default controller exists and if it is a class:
            if(file_exists(CONTROLLERS_DIR.$this->default_request_array['controller'].CONTROLLER_SUFFIX.".php")) {
                require_once(CONTROLLERS_DIR.$this->default_request_array['controller'].CONTROLLER_SUFFIX.".php");
                if(class_exists($this->default_request_array['controller'])) {
                    $requested_controller_object = new $this->default_request_array['controller']();
                    if(!method_exists($requested_controller_object, $this->default_request_array['action'])) {
                        // Verify if the default action exists in the default controller:
                        output_message("Unable to load the default action.", true);
                        return false;
                    }
                }
            } else {
                output_message("Unable to load the default controller.", true);
                return false;
            }
        } else {
            require_once(CONTROLLERS_DIR.$this->requested_array['controller'].CONTROLLER_SUFFIX.".php");
            $requested_controller_object = new $this->requested_array['controller']();
        }   
    // All systems go, create session variables to save this as the referring url:
    $this->process_referring_url();
    $requested_controller_object->{$this->requested_array['action']}();
    /*
     *  Layout happens here, but how? Should I extend my views class with dispatcher or do I create a views object? 
     * If so, how do I make sure my views will be able to get access to assigned variables from my controllers? 
     * Also, a method like $this->assign("variable_name",$value), in which class do I need to add this method as
     * it feels out of place in the dispatcher and the controller does not have access to the views object.
     */

    }
    return true;
}
mauzilla
  • 3,574
  • 10
  • 50
  • 86

1 Answers1

0

I started building a small php framework for my own educational purposes a little while back. It ended up being pretty heavily influenced by the zend framework. Maybe take a look at some of the established frameworks for ideas. My 2c on what you posted:

I dont quite think I am taking the correct approach regarding require_once() and creating the object instances within the dispatch() method

You could register an autoload function with spl_autoload_register to autoload your classes and avoid explicit calls to require in the dispatcher. I think instantiating your objects in the dispatcher is fine.

I cannot see how I will tie in the views controller (which will output the HTML). Where would I assign variables or values generated in the controller?

The constructor of my controllers accepted a request object that held all the http request variables, a response object for the action to fill with a response (be it HTML, Json, etc) and a session object that held session info and any other config data. If you have a separate view controller or need to have multiple controllers you can queue the controllers and dispatch in a loop, passing them each the common request object with all the required variables. I kept mine simple though with a single controller per request.

Any ideas on how to improve my dispatcher would greatly be appreciated!

You could maybe consider using a controller/action whitelist and blacklist that is checked before dispatching to give you more control over what requests get fulfilled.