6
\$\begingroup\$

My bootstrap file contained procedural code, but after stumbling upon this answer I tried to make my bootstrap object oriented.

This is my attempt so far, and I have a feeling that I'm failing at it. I also know that some parts are not really working, because usually with procedural code the changes are made globally and not within a class' scope. I don't know how I can achieve that. Also the methods would have to be performed in order.

Could someone review my bootstrap code and how I can better the logic / usability?

I'm sorry if my code is a little bit overwhelming, but any help is highly appreciated!

Old procedural bootstrap (index.php)

# report all php errors
error_reporting(E_ALL);
# OS independent directory separator
define('DS', DIRECTORY_SEPARATOR);
# define site root path
define('ABSPATH', dirname(__FILE__) . DS);
# auto include entire config array
foreach (glob(ABSPATH . 'config' . DS . '*.php') as $configFile) {
 require $configFile;
}
# auto include all functions
foreach (glob(ABSPATH . 'functions' . DS . '*.php') as $functionFile) {
 require $functionFile;
}
# set include paths to be used for class auto loading
set_include_path(
 ABSPATH . 'core' . PATH_SEPARATOR .
 ABSPATH . 'controllers' . PATH_SEPARATOR .
 ABSPATH . 'models' . PATH_SEPARATOR .
 ABSPATH . 'libraries' . PATH_SEPARATOR .
 ABSPATH . 'helpers'
);
# enable auto loading of classes with the include paths above
spl_autoload_register(
 function ($classname)
 {
 $classname = ltrim($classname, '\\');
 preg_match('/^(.+)?([^\\\\]+)$/U', $classname, $match);
 $classname = str_replace('\\', '/', $match[1]) . str_replace(['\\', '_'], '/', $match[2]) . '.php';
 require_once $classname;
 }
);
# create config object for global scope
$config = new Config($config);
# load session ini settings
foreach ($config->get('session') as $setting => $value) {
 ini_set($setting, $value);
}
session_name('sid');
session_start();
# load router
$request = new Request($_FILES, $_GET, $_POST, $_SERVER);
$router = new Router($request);

OO index.php

require_once dirname(__FILE__) . DIRECTORY_SEPARATOR . 'core' . DIRECTORY_SEPARATOR . 'bootstrap.php';
# bootstrap the framework
$bootstrap = new Bootstrap();
# report all php errors
$bootstrap->errorReporting(E_ALL);
# OS independent directory separator
$bootstrap->directorySeparator('DS');
# define site root path
$bootstrap->rootPath('ABSPATH');
# auto include entire config array
$bootstrap->configArray('configs');
# auto include all functions
$bootstrap->functions('functions');
# set include paths to be used for class auto loading
$bootstrap->includePaths(
 array(
 'core',
 'controllers',
 'models',
 'libraries',
 'helpers'
 )
);
# enable auto loading of classes with the include paths above
$bootstrap->autoload();
# create global config object
$bootstrap->config($config);
# load session ini settings
$bootstrap->session();
# load router
$bootstrap->router();

OO Bootstrap

class Bootstrap
{
 private $ds;
 private $abspath;
 public function errorReporting($level)
 {
 error_reporting($level);
 }
 public function directorySeparator($name)
 {
 define($name, DIRECTORY_SEPARATOR);
 $this->ds = constant($name);
 }
 public function rootPath($name)
 {
 define($name, dirname(__FILE__) . '/../' . $this->ds);
 $this->abspath = constant($name);
 }
 public function configArray($directory)
 {
 foreach (glob($this->abspath . $directory . $this->ds . '*.php') as $config) {
 require $config;
 } 
 }
 public function functions($directory)
 {
 foreach (glob($this->abspath . $directory . $this->ds . '*.php') as $function) {
 require $function;
 }
 }
 public function includePaths(Array $directories)
 {
 $i = 0;
 $numItems = count($directories);
 $paths = '';
 foreach ($directories as $directory) {
 if(++$i !== $numItems) {
 $paths .= $this->abspath . $directory . PATH_SEPARATOR;
 } else {
 $paths .= $this->abspath . $directory;
 }
 }
 set_include_path($paths);
 }
 public function autoload()
 {
 spl_autoload_register(
 function ($classname)
 {
 $classname = ltrim($classname, '\\');
 preg_match('/^(.+)?([^\\\\]+)$/U', $classname, $match);
 $classname = str_replace('\\', '/', $match[1]) . str_replace(['\\', '_'], '/', $match[2]) . '.php';
 require_once $classname;
 }
 );
 }
 public function config()
 {
 $config = new Config([]);
 }
 public function session()
 {
 session_name('sid');
 session_start();
 foreach ($config->get('session') as $setting => $value) {
 ini_set($setting, $value);
 }
 }
 public function router()
 {
 $request = new Request($_FILES, $_GET, $_POST, $_SERVER);
 $router = new Router($request);
 }
}
asked Jun 5, 2014 at 19:54
\$\endgroup\$

2 Answers 2

8
+50
\$\begingroup\$

First off, let me say this: There's no need for your bootstrap to be OO. Your Bootstrap class will become a utility class with no real purpose, which does everything. That is also known as a God Object .

From what I see, you're better off using the procedural one.


Review for OO:

  • Naming convention: Setters should be prefixed with set: setDirectorySeparator, setRootPath, etc. It's not clear what directorySeparator does at a glance.
  • Don't use Globals: The entire point of moving an application to OOP is to better manage the dependencies and move away from global variables.
  • Don't use Service Locators: Your $config variable is a service locator. You will inject it (or worse, global include it) everywhere, it contains all of the configurations and all you need is one or two entries. Don't do that. Give each function/method exactly what it needs.
  • Application bootstrapping should not be OO. See above explanation.

Review for Procedural

  • Use a class for Autoloading: It makes things a whole lot simpler, and it looks nicer too. I see you're using PSR-0, there are easy and simple solutions out there available.
  • Arbitrarily requiring files and adding ini entries is not safe: If you don't sanitize user input properly in any part of your application, this may cause you some severe breakage on the server. Beware!

Here's an example for a good bootstrap file for an MVC application: How should a Model be structured in MVC?

answered Jun 10, 2014 at 8:40
\$\endgroup\$
1
  • \$\begingroup\$ The session ini settings are predefined, and not based on users input. \$\endgroup\$ Commented Jun 11, 2014 at 5:46
3
\$\begingroup\$

configArray() and functions() do the same thing, create just includeDir().

If files in configs directory create arrays, they are not global, so are discarded once out of scope.

Redefine config() as config(&$config), but it should not be global anyway, quite usual name and it might be overwritten by some external legacy library.

syb0rg
21.9k10 gold badges113 silver badges192 bronze badges
answered Jun 6, 2014 at 12:07
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

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.