Что-то не так с классом Singleton, не знаю, что

Я раньше не делал ни одного класса Singleton, и теперь я понял, что для этого подключения к базе данных будет хорошей идеей сделать это, но я не знаю, почему он не работает. Я действительно был бы признателен, если бы кто-то помог мне с этим, так как я хочу узнать, как работает ООП.

В любом случае, я исправил его, просто обновив свой PHP до последней версии, теперь $DBH = new static(); отлично работает, спасибо людям.

Я попытался использовать $DBH = new static(); isntead $DBH = new self();, но тогда у меня есть эта ошибка:

Ошибка анализа: синтаксическая ошибка, неожиданный T_STATIC, ожидая T_STRING или T_VARIABLE или '$' в mSingleton.php on строка 14

Ошибка:

Неустранимая ошибка: невозможно создать экземпляр абстрактный класс Singleton в mSingleton.php в строке 14

Файлы: (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");

Ответы

Ответ 2

Мое обходное решение для PHP 5 < 5.3 для абстрактных классов Singleton.

Взято из: 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();
    }
}

В принципе, после отключения всех потребностей phpRaise:

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();
    }
}

Ответ 3

self указывает на абстрактный класс, и вы не можете создать экземпляр абстрактного класса, вы должны использовать new static(), если хотите сохранить эту организацию.

Ответ 4

$DBH = new self(); совпадает с $DBH = new Singleton();, который был помечен как абстрактный, чтобы предотвратить создание экземпляра.

Вы должны использовать Late Static Binding, чтобы инициировать новый обход дочернего класса, попробуйте использовать new static().

Ответ 5

Я скажу заранее, что не владею PHP, но есть несколько вещей, которые выделяются мне.

  • $DBH переопределяется в DBAccess, где сначала объявляется в Singleton.
  • $DBH в Singleton не объявляется статическим, так как может работать $DBH = new static()? Если последнее связывание со статическими преобразует $DBH в статическую область хранения.
  • Если вы конвертируете $DBH в Singleton в статическую переменную, у вас будут проблемы, если что-то еще происходит от Singleton.

Если кто-то не мудрее приходит и может сделать класс Singleton, который может быть использован для любого подкласса, вам лучше всего поставить логику непосредственно в ваш класс DBAccess. Если кто-то может исправить семантические и синтаксические ошибки, я бы это оценил.

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;
    }
}