cgm225 Posted May 17, 2008 Share Posted May 17, 2008 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; } } ?> Quote Link to comment Share on other sites More sharing options...
cgm225 Posted May 19, 2008 Author Share Posted May 19, 2008 bump Quote Link to comment Share on other sites More sharing options...
448191 Posted May 21, 2008 Share Posted May 21, 2008 You've got at least three options: 1) Pass the mysqli object around 2) Use a (Singleton) Registry 3) Wrap a Singleton around the mysqli object Quote Link to comment Share on other sites More sharing options...
cgm225 Posted May 22, 2008 Author Share Posted May 22, 2008 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! Quote Link to comment Share on other sites More sharing options...
448191 Posted May 22, 2008 Share Posted May 22, 2008 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. Quote Link to comment Share on other sites More sharing options...
cgm225 Posted May 22, 2008 Author Share Posted May 22, 2008 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! Quote Link to comment Share on other sites More sharing options...
448191 Posted May 23, 2008 Share Posted May 23, 2008 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. Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.