2

I have never done any Singleton class before and now I figured that for this DB connection it will be a good idea to make one, but I have no clue why it is not working. I really would appreciate if someone would help me out with this one since I want to learn how OOP works...

Anyway, I fixed it with just updating my PHP to latest version, now $DBH = new static(); works fine, thanks people.

I tried to use $DBH = new static(); isntead of $DBH = new self(); but then I have this error:

Parse error: syntax error, unexpected T_STATIC, expecting T_STRING or T_VARIABLE or '$' in mSingleton.php on line 14

Error:

Fatal error: Cannot instantiate abstract class Singleton in mSingleton.php on line 14

Files: (mSingleton.php)

abstract class Singleton
{

    protected $DBH;

    public static function getInstance()
    {
        if ($DBH == null)
        {
            $DBH = new self();
        }

        return $DBH;
    }

}

(mDBAccess.php)

<?php
//mDBAccess.php
//Removed values ofc
$db_host = "";
$db_name = "";
$db_user = "";
$db_pass = "";

include "mSingleton.php";

class DBAccess extends Singleton
{
    protected $DBH;

    function __construct()
    {
        try
        {
        $this->DBH = new PDO("mysql:host=$db_host;dbname=$db_name", $db_user, $db_pass);
        $this->DBH->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);
        }
        catch (PDOException $e)
        {
            echo $e->getMessage();
        }
    }

    public static function getDBH()
    {
        return self::getInstance()->DBH;
    }
}

(mLog.php)

<?php
//mLog.php
include "mDBAccess.php";

class Log
{

    public static function Add($action)
    {
        try
        {
            $DBH = DBAccess::getDBH();

            //Getting user IP
            $ip = $_SERVER['REMOTE_ADDR'];

            //Getting time
            $time = date('Y-m-d');

            //Preparing our SQL Query
            $values = array($ip, $action, $time);
            $STH = $DBH->prepare("INSERT INTO log (ip, action, time)
                                  VALUES (?, ?, ?)");

            //Excecuting SQL Query
            $STH->execute($values);
        }
        catch (PDOException $e)
        {
            echo $e->getMessage();
        }
    }

}
//testing..
Log::Add("ddd");
1
  • 1
    "Something wrong with Singleton class, no idea what." Well, it's a design smell and has no purpose in PHP. That's what's wrong with it. Commented Feb 6, 2011 at 16:44

5 Answers 5

2

You need to write

$DBH = new static();

See: Late Static Binding

Sign up to request clarification or add additional context in comments.

2 Comments

Okey, but now I have this error:Parse error: syntax error, unexpected T_STATIC, expecting T_STRING or T_VARIABLE or '$' in mSingleton.php on line 14
@Qmail: Late Static Binding is available as of PHP 5.3. You will need to upgrade your PHP version or look for a different solution.
2

My workaround for PHP 5 < 5.3 for abstract Singleton classes.

Taken from: http://code.google.com/p/phpraise/source/browse/trunk/phpraise/core/RaiseSingleton.php

/**
 * RaiseSingleton abstract class
 * Defines a Singleton class
 *
 * @author Sam Yong
 * @license http://www.gnu.org/licenses/gpl.html GNU General Public License v3
 * @abstract
 * @package Raise.Core
 */
abstract class RaiseSingleton extends RaiseObject {

    /**
     * Prevent creation of a new instance
     * Constructor not set to final to allow overrides in subclass
     */
    protected function __construct() {}

    /**
     * Prevent cloning of the Singleton instance
     * @final
     */
    final private function __clone() {}

    /**
     * Return the Singleton instance
     * @return object
     * @staticvar static $__instance
     */
    public static function getInstance() {
        static $__instance;
        $class = get_called_class();
        return $__instance ? $__instance : $__instance = new $class();
    }
}

Basically, after tripping off all the phpRaise necessities:

abstract class Singleton {

    protected function __construct() {}

    final private function __clone() {}

    public static function getInstance() {
        static $__instance;
        $class = get_called_class();
        return $__instance ? $__instance : $__instance = new $class();
    }
}

1 Comment

Thanks man, well I updated my PHP to latest version and now it's all good! :)
0

self points there to the abstract class, and you can't instantiate an abstract class, you have to use new static() if you want to keep that organization.

Comments

0

$DBH = new self(); is the same as $DBH = new Singleton(); which has been marked as abstract to prevent instantiation.

You should be using Late Static Binding to initiate the new obhect of the child class, try using new static().

Comments

0

I will say upfront I am not proficient with PHP but there are a few things that stand out to me.

  • $DBH is redefined in DBAccess where it is first declared in Singleton.
  • $DBH in Singleton is not declared static, so how could $DBH = new static() work? Unless late binding with static converts $DBH into a static storage area.
  • If you convert $DBH in Singleton into a static variable, you'll have issues if anything else every derives from Singleton.

Unless someone wiser comes along and can make a Singleton class that can be utilized for any subclass of it your best bet is to put the logic directly into your DBAccess class. If someone can fix the semantic and syntax errors I'd appreciate it.

class DBAccess
{
    private static $_instance;

    protected $DBH;

    function __construct()
    {
        try
        {
            $this->DBH = new PDO("mysql:host=$db_host;dbname=$db_name", $db_user, $db_pass);
            $this->DBH->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);
        }
        catch (PDOException $e)
        {
            echo $e->getMessage();
        }
    }

    public static function getDBH()
    {
        if ($_instance == null)
            $_instance = new DBAccess();
        return $_instance->DBH;
    }
}

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.