Jump to content

Making MySQLi connection avaliable to all MVC modules...


cgm225

Recommended Posts

I have MVC classes I coded myself (see below) which I instantiate in my index.php5 file.  Also, at the beginning of my index file, I open a MySQLi connection, and then close it at the end of the index file.  My question is this, how can I make that MySQLi object/connection available to all the MVC modules.  Restated, I don't want to have to constantly open up new connections for each module.

 

Any other feedback is appreciated as well.  Thanks again!

 

My index.php5 file

<?php

//Setting full error reporting
error_reporting(E_ALL);

//Initializing session
session_start();

//General includes
require_once 'configurations.php5';               //General configurations
require_once MVC_ROOT . '/MysqliSetConnect.php5'; //MySQLi Settings & Connection
require_once MVC_ROOT . '/Authentication.php5';   //User authentication

//Including MVC classes and instatiating front controller
require_once MVC_ROOT . '/ModelViewController.php5';
$controller = FrontController::getInstance();
$controller->setPageDir(MVC_ROOT);
$controller->dispatch(false);

//Closing MySQLi object created in MysqliSetConnect.php5 (included above)
$mysqli->close();

?>

 

My MysqliSetConnect.php5 file

<?php

//Setting constant database connection settings
define("MYSQL_SERVER", 'mysql.internal');
define("MYSQL_SERVER_USERNAME", 'example_user');
define("MYSQL_SERVER_PASSWORD", 'example_password');

/* Establishing general MySQLi connection for all modules with NO database
* selected
*/
$mysqli = new mysqli(MYSQL_SERVER, MYSQL_SERVER_USERNAME, MYSQL_SERVER_PASSWORD);

?>

 

My ModelViewController.php5 file

<?php

class FrontController extends ActionController {

    //Declaring variable(s)
    private static $instance;
    protected $controller;

    public function __construct(){}

    //Starting new instance of this class with a singleton pattern
    public static function getInstance() {
        if(!self::$instance) {
            self::$instance = new self();
        }
        return self::$instance;
    }

    public function dispatch($throwExceptions = false) {

        /*  
            Checking for the GET variables $module and $action, and, if present,
            will strip them down with a regular expression function with a white
            list of allowed characters, removing anything that is not a letter,
            number, underscore or hyphen.
        */
        $regex  = '/[^-_A-z0-9]++/';
        $module = isset($_GET['module']) ? preg_replace($regex, '', $_GET['module']) : 'home';
        $action = isset($_GET['action']) ? preg_replace($regex, '', $_GET['action']) : 'frontpage';

        /*
            Generating Actions class filename (example: HomeActions) and path to
            that class (example: home/HomeActions.php5), checking if $file is a
            valid file, and then, if so, requiring that file.
        */
        $class = ucfirst($module) . 'Actions';
        $file  = $this->pageDir . '/' . $module . '/' . $class . '.php5';

        if (!is_file($file)) {
            throw new FrontControllerException('Page not found!');
        }

        require_once $file;

        /*  
            Creating a new instance of the Actions class (example: $controller
            = new HomeActions(), and passing page directory variable to the
            ActionController class.
        */
        $controller = new $class();
        $controller->setPageDir($this->pageDir);

        try {
            //Using the setModule method in the ActionController class
            $controller->setModule($module);

            /*
                The ActionController dispatchAction method Checks if the method
                exists, then runs the displayView function in the
                ActionController class.
            */    
            $controller->dispatchAction($action);
        }
        catch(Exception $error) {

            /*
                An exception has occurred, and will be displayed if
                $throwExceptions is set to true.
            */
            if($throwExceptions) {
                echo $error->errorMessage($error); //Full exception echoed
            } else {
                echo $error->errorMessage(null); //Simple error messaged echoed
            }
        }
    }
}

abstract class ActionController {

    //Declaring variable(s)
    protected $pageDir;
    protected $module;
    protected $viewData = array();
    
    public function __construct(){
        
        /*
            Setting variables for objects external to the MVC that are used in
            multiple modules.  These objects add NO functionality to the actual
            MVC classes, but are used by multiple modules.
         */
        $this->auth = MysqliAuthentication::getInstance(); //User authentication
    }
    
    public function setPageDir($pageDir){
        $this->pageDir = $pageDir;
    }

    public function setModule($module) {
        $this->module = $module;
    }

    public function getModule() {
        return $this->module;
    }

    //Placing a value in the $viewData array at the key position
    public function setVar($key, $value) {
        $this->viewData[$key] = $value;
    }

    //Returns a value from the $viewData array located at the key position
    public function getVar($key) {
        if (array_key_exists($key, $this->viewData)) {
            return $this->viewData[$key];
        }
    }

    public function getViewData($viewData) {
        $this->viewData = $viewData;
    }

    /*
        Checking for actionMethod in the Actions class (example: doFrontpage()
        within home/HomeActions.php5) with the method_exists function and, if
        present, the actionMethod and displayView functions are executed.
    */  
    public function dispatchAction($action) {
        $actionMethod = 'do' . ucfirst($action);
        if (!method_exists($this, $actionMethod)) {
            throw new FrontControllerException('Page not found!');
        }
        $this->$actionMethod();
        $this->displayView($action);
    }

    public function displayView($action) {
        if (!is_file($this->pageDir . '/' . $this->getModule() . '/' . $action . 'View.php5')) {
            throw new FrontControllerException('Page not found!');
        }

        //Setting $this->actionView to the path of the action View file
        $this->actionView = $this->pageDir . '/' . $this->getModule() . '/' . $action . 'View.php5';

        /*
            Creating a new instance of the View class and passing the $pageDir,
            $viewData, and actionView variables
        */  
        $view = new View();
        $view->setPageDir($this->pageDir);
        $view->getViewData($this->viewData);
        $view->setVar('actionView',$this->actionView);
        $view->render();
    }
}

class View extends ActionController {

    public function render() {

        //Including default template settings
        require_once $this->pageDir . '/defaultTplSettings.php5';

        /*
            Merging the default template variables with variables provided in
            the $this->viewData array, taken from the Actions class, giving
            priority to those provided by the action class, then extracting the
            array with the extract() function, which creates a variable for
            every array value, and the name of the value (the variable name) is
            the key's value.
        */
        $templateSettings = array_merge($defaultTemplateSettings, $this->viewData);
        extract($templateSettings, EXTR_OVERWRITE);

        //Including template file within which the action View file is included
        require_once $this->pageDir . '/default.tpl';
    }
}

class FrontControllerException extends Exception {
    public function errorMessage($error) {
        
        /*
            If and throwExceptions is true, then the full exception will be
            returned.
        */
        $errorMessage = isset($error) ? $error : $this->getMessage();
        return $errorMessage;
    }
}

?>

Link to comment
Share on other sites

How does this look?  I used a registry. Do you have any feedback for things I can improve?

 

Index.php5

<?php

//Initializing session
session_start();

//General includes
require_once 'configurations.php5';                 //General configurations
require_once MVC_ROOT . '/MysqliSetConnect.php5';   //MySQLi settings|connection
require_once MVC_ROOT . '/Authentication.php5';     //User authentication
require_once MVC_ROOT . '/RegistryItems.inc.php5';  //Default registry items
require_once MVC_ROOT . '/ModelViewController.php5';//MVC with registry class

//Instantiating registry
$registry = new Registry($registryItems);

//Instatiating front controller
$controller = FrontController::getInstance();
$controller->setRegistry($registry);              
$controller->dispatch(false);

//Closing MySQLi object created in MysqliSetConnect.php5 (included above)
$mysqli->close();

?>

 

My MVC WITH a registry class

<?php

class FrontController extends ActionController {

    //Declaring variable(s)
    private static $instance;
    protected $controller;

    //Class construct method
    public function __construct() {}

    //Starts new instance of this class with a singleton pattern
    public static function getInstance() {
        if(!self::$instance) {
            self::$instance = new self();
        }
        return self::$instance;
    }

    public function dispatch($throwExceptions = false) {
        
        /* Checks for the GET variables $module and $action, and, if present,
         * strips them down with a regular expression function with a white
         * list of allowed characters, removing anything that is not a letter,
         * number, underscore or hyphen.
         */
        $regex  = '/[^-_A-z0-9]++/';
        $module = isset($_GET['module']) ? preg_replace($regex, '', $_GET['module']) : 'home';
        $action = isset($_GET['action']) ? preg_replace($regex, '', $_GET['action']) : 'frontpage';

        /* Generates Actions class filename (example: HomeActions) and path to
         * that class (example: home/HomeActions.php5), checks if $file is a
         * valid file, and then, if so, requires that file.
         */
        $class = ucfirst($module) . 'Actions';
        $file  = $this->pageDir . '/' . $module . '/' . $class . '.php5';

        if (!is_file($file)) {
            throw new FrontControllerException('Page not found!');
        }

        require_once $file;

        /* Creates a new instance of the Actions class (example: $controller
         * = new HomeActions(), and passes the registry variable to the
         * ActionController class.
         */
        $controller = new $class();
        $controller->setRegistry($this->registry);

        try {
            //Trys the setModule method in the ActionController class
            $controller->setModule($module);

            /* The ActionController dispatchAction method checks if the method
             * exists, then runs the displayView function in the
             * ActionController class.
             */    
            $controller->dispatchAction($action);
        }
        catch(Exception $error) {

            /* An exception has occurred, and will be displayed if
             * $throwExceptions is set to true.
             */
            if($throwExceptions) {
                echo $error->errorMessage($error); //Full exception echoed
            } else {
                echo $error->errorMessage(null); //Simple error messaged echoed
            }
        }
    }
}

abstract class ActionController {

    //Declaring variable(s)
    protected $registry;
    protected $module;
    protected $registryItems = array();
    
    //Class construct method
    public function __construct(){}
    
    public function setRegistry($registry) {
      
        //Sets the registry object
        $this->registry = $registry;
        
        /* Once the registry is loaded, the MVC root directory path is set from
         * the registry.  This path is needed for the MVC classes to work
         * properly.
         */
        $this->setPageDir();
    }
    
    //Sets the MVC root directory from the value stored in the registry
    public function setPageDir() {
        $this->pageDir = $this->registry->get('pageDir');
    }

    //Sets the module
    public function setModule($module) {
        $this->module = $module;
    }

    //Gets the module
    public function getModule() {
        return $this->module;
    }

    /* Checks for actionMethod in the Actions class (example: doFrontpage()
     * within home/HomeActions.php5) with the method_exists function and, if
     * present, the actionMethod and displayView functions are executed.
     */  
    public function dispatchAction($action) {
        $actionMethod = 'do' . ucfirst($action);
        if (!method_exists($this, $actionMethod)) {
            throw new FrontControllerException('Page not found!');
        }
        $this->$actionMethod();
        $this->displayView($action);
    }

    public function displayView($action) {
        if (!is_file($this->pageDir . '/' . $this->getModule() . '/' . $action . 'View.php5')) {
            throw new FrontControllerException('Page not found!');
        }

        //Sets $this->actionView to the path of the action View file
        $this->actionView = $this->pageDir . '/' . $this->getModule() . '/' . $action . 'View.php5';

        //Sets path of the action View file into the registry
        $this->registry->set('actionView', $this->actionView);

        //Includes template file within which the action View file is included
        require_once $this->pageDir . '/default.tpl';
    }
}

class Registry {
    
    //Declaring variables
    private $store;

    //Class constructor
    public function __construct($store = array()) {
        $this->store = $store;
    }
    
    //Sets registry variable
    public function set($label, $object) {
        $this->store[$label] = $object;
    }
   
    //Gets registry variable    
    public function get($label) {
        if(isset($this->store[$label])) {
            return $this->store[$label];
        }
        return false;
    }
    
    public function getRegistryArray() {
        return $this->store;
    }
}

class FrontControllerException extends Exception {
    public function errorMessage($error) {
        
        //If and throwExceptions is true, then the full exception is returned.
        $errorMessage = isset($error) ? $error : $this->getMessage();
        return $errorMessage;
    }
}

?>

 

RegistryItems.inc.php5

<?php

$registryItems = array();

$registryItems['pageDir'] = MVC_ROOT; //MVC root path **required by MVC classes
$registryItems['mysqli']  = $mysqli;  //MySQLi connection object
$registryItems['auth']    = $auth;    //MysqliAuthentication class object

?>

 

Thanks again!

Link to comment
Share on other sites

Could be worse. One thing though (very common oversight). When you pass an array to an object to be used as an internal stack/queue/hashtable, don't set it directly on the internal reference, unless you have a valid reason to do so. In your case this means passing the $registryItems.

 

Instead, use the class' accessors. Enforce the entry points of the internal data. This is good practice that allows you to easily manage any  restrictions on setting data (not that you have any currently, but as I said: good practice). This also applies to using magic methods: never let them operate directly on internal data.

 

You may feel a bit silly doing a foreach loop when you could simply copy the reference, but in the end it is for the best.

 

Some general stuff...

 

//Closing MySQLi object created in MysqliSetConnect.php5 (included above)
$mysqli->close();

 

a) Why is this in your bootstap?

b) Why do you bother calling it?

 

//Setting constant database connection settings
define("MYSQL_SERVER", 'mysql.internal');
define("MYSQL_SERVER_USERNAME", 'example_user');
define("MYSQL_SERVER_PASSWORD", 'example_password');

 

Constants?

 

Something else, this is a topic that should be App Design.

 

 

Link to comment
Share on other sites

Thanks again for all your help.

 

Could you explain a little more about the class's accessors, and using a foreach loop?  I am not sure what you mean, and what I am supposed to be doing.

 

Also, I have the $mysqli->close in the index.php5 so I do not have to redundantly close it in each module.  No good?  What should I be doing?

 

Finally, what is wrong with using those constants?  Should I just be directly inserting those values into the mysqli statement?

 

 

Thanks!

Link to comment
Share on other sites

You directly set internal data on your registry. Try to make it a habit to use your accessors (get() and set()).

 

Try to avoid constants. For a quick and flexible alternative, use an INI file.

 

It's not useful to close a database connection, especially at the bottom of your script. The connection will terminate after execution is complete anyway. Also, you might want to save connecting to the database until you need to. You can make a simple wrapper around mysqli for this purpose.

Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.