1

Below is my code to connect which works fine without configuration file (.ini file). But if I use configuration file, I'm getting error:

Fatal error: Constant expression contains invalid operations in singletonDB.php on line 13.

But as you can see, the variables $dsn, $user and $pass are not static variables. I'm not understanding why I'm getting static variable related error for non-static variable.

My final goal is to use configuration file as well as keeping only singleton connection to DB.

<?php
$config = parse_ini_file("config.ini");
var_dump($config);
// Singleton to connect db.
class ConnectDb
{

    // Hold the class instance.
    private static $instance = null;

    private $pdo;

    private $dsn = $config['dsn_config'];

    private $user = $config['user_config'];

    private $pass = $config['password_config'];

    // The db connection is established in the private constructor.
    private function __construct()
    {
        echo nl2br("Inside constructor"); 
        $this->pdo = new PDO($this->dsn, $this->user, $this->pass);
        $this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    }

    public static function getInstance()
    {
        if (! self::$instance) {
            self::$instance = new ConnectDb();
        }

        return self::$instance;
    }

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

And this is my configuration file

;Local
dsn_config = 'mysql:host=127.0.0.1;port=3306;dbname=db_name;';
user_config = 'root';
password_config = 'root';

Thank you.

2 Answers 2

1

The issue is not with $dsn, $user, or $pass, it will be with $config. You can not assign $config that way. If you change those to strings or other values (int, array, bool), you will find the error goes away:

private $dsn  = false;  # All of these are 
private $user = [];     # are valid
private $pass = 1234;   # assignments

The problem then is how do you assign the ini args? A common method is to just inject into the construct of the class when it's instantiated:

class ConnectDb
{
    private static $instance = null;

    private $pdo;    
    private $dsn = '';
    private $user = '';
    private $pass = '';

    private function __construct($dsn, $user, $pass)
    {
        $this->dns = $dns;
        $this->user = $user;
        $this->pass = $pass;

        echo nl2br("Inside constructor"); 
        $this->pdo = new PDO($this->dsn, $this->user, $this->pass);
        $this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    }
    ...etc.

To use:

<?php
$config = parse_ini_file("config.ini");
# Inject into the construct here
$Db = new ConnectDb($config['dsn_config'], $config['user_config'], $config['password_config']);

Another method could be using defines (constants):

<?php
$config = parse_ini_file("config.ini");
# Create some defines
define('DB_DSN', $config['dsn_config']);
define('DB_USER', $config['user_config']);
define('DB_PASS', $config['password_config']);

The class then would look like:

class ConnectDb
{
    private static $instance = null;

    private $pdo;
    private $dsn = '';
    private $user = '';
    private $pass = '';

    private function __construct()
    {
        # Assign the constants here ALTHOUGH...
        # I don't know that there is a good reason to make these class 
        # variables. I would just put the constants into the construct of
        # the PDO below. I don't know that you are going to need to reference
        # these variables after you have created the PDO connection.
        $this->dns = DB_DSN;
        $this->user = DB_USER;
        $this->pass = DB_PASS;

        echo nl2br("Inside constructor"); 
        $this->pdo = new PDO($this->dsn, $this->user, $this->pass);
        $this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    }
    ...etc.
Sign up to request clarification or add additional context in comments.

2 Comments

Thank you for the detailed explanation Rasclatt. However I didn't wanted to create the object elsewhere in my program. Hence, based on your explanation, I moved the configuration file reading code inside the constructor only. Don't know whether that is a good way of approach.
Yeah that works too. There are benefits for doing a method like that. It’s similar to using defines in that you can create the connect anytime without having to first parse the ini and inject the array
0

I didn't want to create object elsewhere in my program, Hence based on the explanation from @Rasclatt, I moved the configuration reading code inside the constructor and it's working fine now. Below is the updated code.

File name "singletonDB.php"

<?php

// Singleton to connect db.
class ConnectDB
{

    // Hold the class instance.
    private static $instance = null;

    private $pdo;

    private $dsn = '';

    private $user = '';

    private $pass = '';

    // The db connection is established in the private constructor.
    private function __construct()
    {
//         $pdo = new PDO($dsn, $user, $password);
        $config = parse_ini_file("../config.ini");
        echo nl2br("var_dump ing config");
        var_dump($config);

        $this->dsn = $config['dsn_config'];
        $this->user = $config['user_config'];
        $this->pass = $config['password_config'];

        echo nl2br("Inside constructor"); 
        $this->pdo = new PDO($this->dsn, $this->user, $this->pass);
        $this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    }

    public static function getInstance()
    {
        if (! self::$instance) {
            self::$instance = new ConnectDB();
        }

        return self::$instance;
    }

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

Later you can get the connection form DB as

require_once 'singletonDB.php';
$instance = ConnectDB::getInstance();
$conn = $instance->getConnection();
var_dump($conn);

However I'm not sure whether it's a good way of programming.

Comments

Your Answer

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.