Private function __construct() get Access level to Database::__construct() must be pu

Fatal error: Access level to Database::__construct() must be public (as in class PDO) in C:\xampp\htdocs\VT\Learnable\OOP-PHP\spbooks-PHPPRO1-ae9bb56\spbooks-PHPPRO1-ae9bb56\chapter_04\Ping\Singleton.php on line 30

getting this when in Singleton Design Pattern (1st DP in Lorna book (SITEPOINT) ch.4-DP “PHP Master: Write Cutting-edge Code”)
I HAVE BELOW - NOT GETTING but SUCCESS RUN WHEN public function __construct()
(book says private)


private function __construct()
  {
    // Call the PDO constructor
    parent::__construct(APP_DB_DSN, APP_DB_USER, APP_DB_PASSWORD);
  }

included code from ch.2-db in this example


<?php

require("Singleton.php");

try {
  $db_conn = Database::getInstance();
} catch (PDOException $e) {
  echo "Could not connect to database";
  exit;
}

/*
try {
  $db_conn = new PDO('mysql:host=localhost;dbname=recipes', 'root', '');
} catch (PDOException $e) {
  echo "Could not connect to database";
  exit;
}
*/

try {
  // start the transaction
  $db_conn->beginTransaction();

  $db_conn->exec('UPDATE categories SET id=99 WHERE name = "Pudding"');
  $db_conn->exec('UPDATE recipes SET category_id=99 WHERE category_id=19');

  // we made it!
  $db_conn->commit();
  echo "done";

} catch (PDOException $e) {
  $db_conn->rollBack();
  echo "Something went wrong: " . $e->getMessage();
} catch (Exception $e) {
  $db_conn->rollBack();
  echo "Something went wrong: " . $e->getMessage();
}
?>


Same to Trait DP - Book say private but only public work… the private function __construct()

The constructor must be public in PHP. I am not sure about older versions of PHP, but in PHP 5.4 it is required to be public.

sitepoint i think must note it in book errata

I don’t know where you got this but it’s not true. See http://3v4l.org/VveXS

The problem with the code here is that the PDO constructor is public, so any class extending PDO must also have it’s constructor public.
So there is no way you can extend PDO this way. The only thing you could do is instantiate a PDO instance in the constructor of your own class, like so


<?php

class MyClass
{
    private $pdo;
    private static $instance;

    private function __construct()
    {
        $this->pdo = new PDO(/* params here */);
    }

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

    /**
    * Just an example method to show
    * how to interact with the PDO instance
    */
    public function queryAndFetch($query)
    {
        $stmt = $this->pdo->query($query);
        return $stmt->fetchAll(PDO::FETCH_ASSOC);
    }
}

Of course you’d have to supply the correct parameters for PDO etc.

I think the OP’s problem is about private methods. Singletons usually use private constructors, but the assumption here is that you do not have an inheritance hierarchy. If inheritance is involved, you need to change your constructors into protected methods, so that your child class can call parent constructors. And of course there is absolutely NO requirement for constructors to be public, even in PHP 5.6.

Well, the book is 3 years old. Not much in human terms, but it might make a difference considering how fast technology is moving.

I’m almost assuredly missing something. but my take was that this is a problem relating to “statically calling” i.e.

$myClassObj = new ClassObj
$myClassObj->class_method
vs.
$ClassObj::class_method

I was wrong. A private constructor can be used when accessing methods using the scope resolution operator :: such as in the case with the singleton pattern. A private constructor will result in a fatal error when attempting to create an instance of the class using the new keyword. That may be desired behavior if you intend to use the DB class only as a singleton.

Fatal error: Access level to Database::__construct() must be public (as in class PDO) in C:\xampp\htdocs\VT\Learnable\OOP-PHP\spbooks-PHPPRO1-ae9bb56\spbooks-PHPPRO1-ae9bb56\chapter_04\Ping\Singleton\Singleton.php on line 31

private or protected give error
public - not Error


  const APP_DB_DSN = "mysql:host=localhost;dbname=recipes";
  const APP_DB_USER = "root";
  const APP_DB_PASSWORD = "";
  
  class Database extends PDO {
  // A static variable to hold our single instance
  private static $_instance = null;


  // Make the constructor private to ensure singleton   private protected - error
   public function __construct()  // not error getting with public
  {
    // Call the PDO constructor
    parent::__construct(APP_DB_DSN, APP_DB_USER, APP_DB_PASSWORD);
  }

  // A method to get our singleton instance
  public static function getInstance()
  {
    if (!(self::$_instance instanceof Database)) {
      self::$_instance = new Database();
    }
    
    return self::$_instance;
  }
}
?>


What happens when you try it this way with new Database() replaced with new self():

  public static function getInstance()
  {
    if (!(self::$_instance instanceof Database)) {
      self::$_instance = new self();
    }
    
    return self::$_instance;
  }
}

Same error, since that is not the problem. The problem is that PDO has a public constructor, so every class that extends it must also have a public constructor, like I already said in post #5 of this thread.

must be public (as in class PDO) from error

seems the correct is post #11

problem is that PDO has a public constructor, so every class that extends it must also have a public constructor,