1

These are three files

config.php
functions.php
index.php

I got an error "Fatal error: Uncaught Error: Call to a member function prepare() on null". I am new to PHP oop. Please help me.

I have code in config.php

class DatabaseConnection {
   public function __construct() {
      try {
         $pdo = new PDO('mysqli:host=xxx;dbname=xxx', 'root', '');
      } catch(PDOException $e) {
          exit('Database error');
      }
   }
}

functions.php code see below

require "config.php";

class LoginRegistration {
function __constructor() {
  $database = new DatabaseConnection();
}

public function registerUser($username, $password, $name, $email, $website) {
  global $pdo;
  $query = $pdo->prepare("SELECT id FROM users WHERE username = ? AND email = ?");
  exit();
  $query->execute(array($username, $email));
  $num = $query->rowCount();

  if($num == 0) {
    $query = $pdo -> prepare("INSERT INTO users (username, password, name, email, website) VALUES (?, ?, ?, ?, ?)");
    $query -> execute(array($username, $password, $name, $email, $website));
    return true;
  } else {
    print "Username and email already used.";
  }
}
}

And index.php code you can find below.

  require_once "functions.php";
  $user = new LoginRegistration();
    if($_SERVER['REQUEST_METHOD'] == 'POST') {
    $username = $_POST['username'];
    $password = $_POST['password'];
    $name = $_POST['name'];
    $email = $_POST['email'];
    $website = $_POST['website'];

    $password = md5($password);
    $register = $user->registerUser($username, $password, $name, $email, $website);
    if($register) {
  echo "<div class='alert alert-success'>Register done <a href='login.php'>Click her</a> for login</div>";
} else {
  echo "<div class='alert alert-danger'>Username or Email already exists.</div>";
}
}
Ankit Parmar
  • 670
  • 10
  • 24
  • **WARNING**: Writing your own access control layer is not easy and there are many opportunities to get it severely wrong. Please, do not write your own authentication system when any modern [development framework](http://codegeekz.com/best-php-frameworks-for-developers/) like [Laravel](http://laravel.com/) comes with a robust [authentication system](https://laravel.com/docs/master/authentication) built-in. At the absolute least follow [recommended security best practices](http://www.phptherightway.com/#security) and **never store passwords with a weak, high-speed hash like SHA1 or MD5**. – tadman Dec 01 '17 at 19:15
  • 1
    : "It looks like you're writing your own ORM. Have you considered using one that's already written, tested, and widely supported like [Doctrine](http://www.doctrine-project.org/), [Propel](http://propelorm.org/) or [Eloquent](https://laravel.com/docs/master/eloquent)?" – tadman Dec 01 '17 at 19:15
  • 1
    Well, you define `$pdo` in `DatabaseConnection`, but it only exists within that class. So using `global $pdo` within `LoginRegistration` does nothing. – aynber Dec 01 '17 at 19:19
  • **You shouldn't use [MD5 password hashes](http://security.stackexchange.com/questions/19906/is-md5-considered-insecure)**. Please use **PHP's [built-in functions](http://jayblanchard.net/proper_password_hashing_with_PHP.html)** (`password_hash()` and `password_verify()`) to handle password security. If you're using a PHP version less than 5.5 you can use the `password_hash()` [compatibility pack](https://github.com/ircmaxell/password_compat). **It is not necessary** to [escape passwords](http://stackoverflow.com/q/36628418/1011527) or use any other cleansing mechanism on them before hashing. – GrumpyCrouton Dec 01 '17 at 19:33
  • `__constructor()` that isn't the right syntax here. – Funk Forty Niner Dec 01 '17 at 19:34
  • Nice to see how you're just ignoring the heck out of perfectly valid / important comments. – Funk Forty Niner Dec 01 '17 at 19:35
  • I am not ignoring your comments. I read it but I don't get the expected answer. – Ankit Parmar Dec 01 '17 at 19:37

1 Answers1

1

You will not get the $pdo variable in DatabaseConnection class from global scope. So, your $pdo variable is basically null. You can change you code as below:

config.php:

class DatabaseConnection {
   public function __construct() {
      try {
         return new PDO('mysqli:host=xxx;dbname=xxx', 'root', '');            
      } catch(PDOException $e) {
          exit('Database error');
      }
   }
}

Then:

class LoginRegistration {
    private $database

    function __construct() {
        $this->database = new DatabaseConnection();
    }

    public function registerUser($username, $password, $name, $email, $website) {

      $query = $this->database->prepare("SELECT id FROM users WHERE username = ? AND email = ?");
      $query->execute(array($username, $email));
      $num = $query->rowCount();

      ...

However, I would rather extend the DatabaseConnection class rather instantiating it within the LoginRegistration class. That is:

config.php:

class DatabaseConnection {
   protected $pdo;
   public function __construct() {
      try {
         $this->pdo = new PDO('mysqli:host=xxx;dbname=xxx', 'root', '');            
      } catch(PDOException $e) {
          exit('Database error');
      }
   }
}

Then extend DatabaseConnection from LoginRegistration class:

class LoginRegistration extends DatabaseConnection {
    // constructor is not needed anymore
    public function registerUser($username, $password, $name, $email, $website) {

      $query = $this->pdo->prepare("SELECT id FROM users WHERE username = ? AND email = ?");
      $query->execute(array($username, $email));
      $num = $query->rowCount();

      ...
Kamrul Khan
  • 3,260
  • 4
  • 32
  • 59