Multiple Class Initialization and Bootstrap Process

I am trying to create an MVC framework for teaching purposes only.

At this point, I created a class Application

that I believe bootstrap should do, such as setting error reporting based on configuration and also setting an instance of $ db.

I have a common folded structure like models, controllers, views, libraries and core.

In my core, I will have classes for database, session, evaluation, etc.

I don't understand how to pass all these instances to the appropriate class containing the protected $ instance property so that inherited models and controllers can access them.

For example, in my initialization process, I did

<?php
use Core\Config;

class Application
{
    public function __construct()
    {
        // Load runtime configuration
        require_once 'config/config.php';
        $this->errorHandler();

    }

    private function setDbConnection()
    {
        switch (Config::$config['database']['dbdriver'])
        {
            case 'MySQLi':
                $db = new mysqli(Config::$config['database']['dbhost'], Config::$config['database']['dbuser'], Config::$config['database']['dbpass'], Config::$config['database']['dbname']);
                break;

            case 'PDO':
                $dsn = 'mysql:host='.Config::$config['database']['dbhost'].';dbname='.Config::$config['database']['dbname'];
                $db =  new PDO($dsn, Config::$config['database']['dbuser'], Config::$config['database']['dbpass']);
                break;

            default:

                break;
        }
    }


}

$application = new Application;

      

How can I pass this dbConnection to my core /Database.php so that my models will extend Database.php and have $ db to do requests etc.

Also this is a good idea or I am doing it wrong in terms of performance.

+3


source to share


1 answer


Hope I'm not too late, but you can try to use a single color context object, this will allow global access to your objects and avoid static classes.

All you have to do is create the objects you need in the method Application::bootstrap

and assign them to the context.

For models that I would not inherit directly from the database, I would use composition as shown in the model class below.

EDIT : I'm a little rusty with PHP, but last time I checked PDO and Mysqli had very different implementations, so I added a common database interface and two half implementations, it will allow switching from an extension to another without polluting the code with useless conditions.

Context.php

<?php
namespace Core;

/**
 *  Context singleton class.
 *  Contains 'global instances' reusable by your application
 */
class Context {
    private static $instance = null;
    private $config;
    private $db;

    public static function getInstance() {
        if (null == $instance) {
            $instance = new Context();
        }
        return $instance;
    }

    private function __construct() {
    }

    public function getConfig() {
        return $this->config;
    }

    public function setConfig(Config $config) {
        $this->config = $config;
    }

    public function getDatabase() {
        return $this->db;
    }

    public function setDatabase(Database $db) {
        $this->db = $db;
    }
}
?>

      

config.php

<?php
namespace Core;

/**
 *  Config class, Since you didn't post the implementation
 *  I took the liberty to implement it as ArrayObject
 */
class Config extends ArrayObject {

    public function __construct(array $configurationArray) {
        parent::__construct($configurationArray, self::ARRAY_AS_PROPS);
    }
}
?>

      

database.php

<?php
namespace Core;

/**
 * Database interface.
 *
 * Provides a common interface for different PHP extensions
 */
interface Database {

    public function connect();

    public function diconnect();

    public function getConnection();

    public function query($sql);

    public function countRows();

    public function fetchRows();

    // Add other useful wrapper methods here...
}
?>

      

MysqliAdapter.php

<?php
namespace Core;

use \mysqli;

/**
 * Mysqli Database Adapter
 *
 * Wraps Mysqli extension
 */
class MysqliAdapter implements Database {
    private $connection;

    public function connect() {
        $config = Context::getInstance()->getConfig();

        $this->connection = new mysqli($config['database']['dbhost'], $config['database']['dbuser'], $config['database']['dbpass'], $config['database']['dbname']);
    }

    public function diconnect() {
        // Implement mysqli disconnection here
    }

    public function getConnection() {
        return $this->connection;
    }

    public function query($sql) {
        // Implement mysqli query here
    }

    public function countRows() {
        // Implement mysqli count rows here
    }

    public function fetchRows() {
        // Implement mysqli fetch rows here
    }
}
?>

      



PDOAdapter.php

<?php
namespace Core;

use \PDO;

/**
 * PDO Database Adapter
 *
 * Wraps PDO extension
 */
class PDOAdapter implements Database {
    private $connection;

    public function connect() {
        $config = Context::getInstance()->getConfig();

        $dsn = 'mysql:host='. $config['database']['dbhost'].';dbname='.$config['database']['dbname'];
        $this->connection =  new PDO($dsn, $config['database']['dbuser'], $config['database']['dbpass']);
    }

    public function diconnect() {
        // Implement PDO disconnection here
    }

    public function getConnection() {
        return $this->connection;
    }

    public function query($sql) {
        // Implement PDO query here
    }

    public function countRows() {
        // Implement PDO count rows here
    }

    public function fetchRows() {
        // Implement PDO fetch rows here
    }
}
?>

      

Model.php

<?php
namespace Core;

/**
 * Abstract model, holds a database instance, it not necessary since you can access it
 * from the Context but this way it will be inherited by subclasses
 */
abstract class Model {
    protected $db;

    public function __construct() {
        // Assign Database object from the context
        $this->db = Context::getInstance()->getDatabase();
    }

    // Model methods if any....
}
?>

      

application.php

<?php
namespace Core;

/**
 *  Application class.
 */
class Application {

    public static function bootstrap(array $configurationArray) {

        // Initialize and put configuration object into the Context
        $config = new Config($configurationArray);
        Context::getInstance()->setConfig( $config );

        // Connect to the database using the right adapter.
        // Remember to set the 'dbdriver' setting or $db will be undefined
        switch ($config['database']['dbdriver']) {

            case 'MySQLi':
                $db = new MysqliAdapter();
                break;

            case 'PDO':
                $db = new PDOAdapter();
                break;      
        }

        $db->connect();
        Context::getInstance()->setDatabase( $db );
    }
}
?>

      

config.php

<?php
/**
 * Configuration array
 */
return array(
    'database' => array(
        'dbdriver' => '...',
        'dbhost'   => '...',
        'dbuser'   => '...',
        'dbpass'   => '...',
        'dbname'   => '...'
    )
);
?>

      

index.php

<?php
use Core\Application;

// Not a very good way, but it should serve you 
// well enough during development
$configurationArray = require_once 'config.php';

// Start application
Application::bootstrap( $configurationArray );
?>

      

I haven't tested the code but should be enough to give you an idea

Greetings

0


source







All Articles