Skip to content
Advertisement

Call to undefined method but it is defined and it works in index.php?

I have a small php project with OOP. I have 3 Klasse that represent the Objects User.php Transaction.php and BankAccount.php. They work fine if I’m in the index.php but as soon i go to an other site it states:

Fatal error: Uncaught Error: Call to undefined method database::connect() in /app/public/models/Transaction.php on line 83

The project structure is like this app/public models Database.php User.php Transaction.php BankAccount.php sites account.php index.php

it works in index.php but when i loggin and redirect to sites/account.php suddenly the Database::connect() is undefined.

Thanks in advance

Github: https://github.com/OSZII/eBanking_APP

index.php:

<?php
session_start();
require_once("./sites/validate.php");
require_once("./models/User.php");
require_once("./models/BankAccount.php");
require_once("./models/Transaction.php");

// redirect if logged in
if (isset($_SESSION['username'])) {
  if ($_SESSION['role'] == "admin" | $_SESSION['role'] == "worker") {
    echo "<script>window.location.href='sites/adminAccount.php'</script>";
    // header("Location: ./sites/adminAccount.php");
    die();
  } else {
    echo "<script>window.location.href='sites/account.php'</script>";
    // header("Location: ./sites/account.php");
    die();
  }
}

if(isset($_POST['username']) & isset($_POST['password'])){
  $username = $_POST['username'];
  $password = $_POST['password'];

  $user = User::getByName($username);
  $bankaccount = BankAccount::getByUserId($user->getId());

  if($user){
    if(password_verify($password, $user->getPassword())){
      $_SESSION['id'] = $user->getId();
      $_SESSION['username'] = $username;
      $_SESSION['role'] = $user->getRole();
      $_SESSION['IBAN'] = $bankaccount->getIBAN();
      echo "<script>window.location.href='index.php'</script>";
      die();
    }else $errors['password'] = "Password falsch!";
  }else $errors['username'] = "Benutzer existiert nicht!";


}

?>

Database.php:

<?php

class Database
{  
    private static $dbName = 'ebanking';
    private static $dbHost = 'mysql';
    private static $dbUsername = 'root';
    private static $dbUserPassword = 'password';

    private static $conn = null;

    public function __construct()
    {
        exit('Init function is not allowed');
    }

    public static function connect()
    {
        // One connection through whole application
        if (null == self::$conn) {
            try {
                self::$conn = new PDO("mysql:host=" . self::$dbHost . ";" . "dbname=" . self::$dbName, self::$dbUsername, self::$dbUserPassword);
            } catch (PDOException $e) {
                die($e->getMessage());
            }
        }
        self::$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
        return self::$conn;
    }

    public static function disconnect()
    {
        self::$conn = null;
    }
}

?>

User.php:

<?php

require_once("Database.php");
require_once("DatabaseObject.php");

class User implements DatabaseObject{

    private $id;
    private $username;
    private $password;
    private $role;

    public function save(){
        if($this->validate()){
            if($this->id != null && $this->id > 0){
                $this->update();
            } else $this->id = $this->create();

            return true;
        }
        return false;
    }

    public function create()
    {
        $db = Database::connect();
        $sql = "INSERT INTO users (username, password, role) values (?, ?, ?);";
        $stmt = $db->prepare($sql);
        $stmt->execute();
        Database::disconnect();
    }

    public function update(){
        $db = Database::connect();
        $sql = "UPDATE users SET username = ?, password = ?, role = ? WHERE id = ?;";
        $stmt = $db->prepare($sql);
        $stmt->executer(array($this->username, $this->password, $this->role, $this->id));
        Database::disconnect();
    }

    public static function get($id){
        $db = Database::connect();
        $sql = "SELECT * FROM users WHERE id = ?;";
        $stmt = $db->prepare($sql);
        $stmt->execute(array($id));
        $user = $stmt->fetchObject("User");
        Database::disconnect();

        return $user;
    }

    public static function getByName($username){
        $db = Database::connect();
        $sql = "SELECT * FROM users WHERE username = ?;";
        $stmt = $db->prepare($sql);
        $stmt->execute(array($username));
        $user = $stmt->fetchObject("User");
        Database::disconnect();
        return $user;
    }

    public static function getByIBAN($IBAN){
        $db = Database::connect();
        $sql = "SELECT * FROM users WHERE IBAN = ?;";
        $stmt = $db->prepare($sql);
        $stmt->execute(array($IBAN));
        $user = $stmt->fetchObject("User");
        Database::disconnect();
        return $user;
    }

    public static function getAll()
    {
        $db = Database::connect();
        $sql = "SELECT * FROM users;";
        $stmt = $db->prepare($sql);
        $stmt->execute();
        $users = $stmt->fetchAll(PDO::FETCH_CLASS, "User");
        Database::disconnect();

        return $users;
    }

    public static function delete($id){
        $db = Database::connect();
        $sql = "DELETE FROM users WHERE id = ?;";
        $stmt = $db->prepare($sql);
        $stmt->execute(array($id));
        Database::disconnect();

    }

    private function validate(){
        return $this->validateHelper($this->username) &
            $this->validateHelper($this->password) &
            $this->validateHelper($this->role);
    }

    private function validateHelper($value){
        return strlen($value) > 0 ? true : false;
    }

    //getter & setter cut out to reduce length off this class for stackoverflow

}

account.php:

<?php
session_start();
require_once("../models/Transaction.php");
require_once("../models/BankAccount.php");
require_once("../models/User.php");

// wenn kein username gesetzt ist, dann soll man direkt wieder auf die loginseite zurück geschickt werden
if(!isset($_SESSION['username']) | isset($_GET['logout']) ){
    session_destroy();
    echo "<script>window.location.href='../index.php'</script>";
    // header("Location: ../index.php");
    die();
}

echo User::get(1)->getUsername();

if(isset($_POST['transaction'])){
    
    $bankaccount = BankAccount::getByIBAN($_SESSION['IBAN']);
    $senderIBAN = $bankaccount->getIBAN();
    $senderBIC = $bankaccount->getBIC();
    $receiverIBAN = isset($_POST['receiverIBAN'])? $_POST['receiverIBAN'] : "";
    $receiverBIC = BankAccount::getByIBAN($receiverIBAN);
    $paymentReference = isset($_POST['paymentReference'])? $_POST['paymentReference'] : "";
    $purposeOfUse = isset($_POST['purposeOfUse'])? $_POST['purposeOfUse'] : "";
    $amount = isset($_POST['betrag'])? $_POST['betrag'] : "";
    

    if($bankaccount->getBalance() >= $amount){
        $transaction = new Transaction();
        $transaction->setSenderIBAN($senderIBAN);
        $transaction->setReceiverIBAN($receiverIBAN);
        $transaction->setSenderBIC($senderBIC);
        $transaction->setReceiverBIC($receiverBIC);
        $transaction->setPaymentReference($paymentReference);
        $transaction->setPurposeOfUse($purposeOfUse);
        $transaction->setAmount($amount);
        $transaction->setDate(date('Y-m-d'));
        $transaction->setTime(date('H:i:s'));
        $transaction->save();
        echo "<script>window.location.href = 'account.php'</script>";
        // header("Location: account.php");
        die();
    }else $transaktionFehlgeschlagen = true;
    
}
?>

Advertisement

Answer

In public/sites/account.php l. 3 you have : require_once("./database.php");

‘./’ refers to the current directory (public/sites), so this statement includes the file public/sites/database.php.

This file define a class named database (not the same than the Database class defined in app/public/models).

This database class do not have a method connect(), this is why PHP tells you Call to undefined method database::connect() (please note the lowercase d)

Addition, to avoid this kind of problem, you could :

  • rename your classes to clarify their role (example here : DatabaseConnection / DatabaseQueries, would be easier to understand and debug than Database / database)
  • use an autoloader, it will be easier than handle the require statement by yourself.
User contributions licensed under: CC BY-SA
10 People found this is helpful
Advertisement