在null OOP上调用成员函数prepare()

时间:2016-03-14 07:29:47

标签: php oop

无法理解类和继承:

core.php中:

$servername = "****";
$database = "****";
$username = "****";
$password = "****";

try {
    $pdo = new PDO("mysql:host=$servername;dbname=$database", $username, $password);
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch(PDOException $e) {
    echo "Connection failed: " . $e->getMessage();
}

class Database {

  protected $pdo;

  public function __construct($pdo) {
    $this->pdo = $pdo;
  }
}

class User extends Database {

  private $ip;
  private $sessionId;

  public function __construct($ip, $sessionId) {
    $this->ip = $ip;
    $this->sessionId = $sessionId;
  }
  public function getSessionInfo () {
    $stmt = $this->pdo->prepare(".."); <-- error here
    ....
  }
}

致电:

require_once 'api/core.php';
$database = new Database($pdo);
$user = new User($_SERVER['REMOTE_ADDR'], $_SESSION['info']['id']);

2 个答案:

答案 0 :(得分:3)

在本次竞赛中,$ database和$ user变量彼此无关:

require_once 'api/core.php';
$database = new Database($pdo);
$user = new User($_SERVER['REMOTE_ADDR'], $_SESSION['info']['id']);

因此,在$ user上调用prepare()将不起作用。

您需要一种机制,至少像这样,虽然不是将数据库分配给用户的好方法:

$user->setDatabase($database);

而是创建一个静态数据库对象,在用户启动之前启动它,并在User对象或任何其他对象中静态调用它,使其可用于所有对象。

快速修复看起来像这样,用户不会扩展数据库,因为它是错误的。 用户不是数据库

$database = new Database();
$user = new User();
$user->setDatabase($database); //sets $db variable inside User

//User.php
namespace MyApp;

class User{
    private Database $db;

    public function setDatabase($db){
        $this->db = $db;
    }

    public function doSomething(){
         $this->db->getPdo()->prepare('..');
    }
}

//Database.php
namespace MyApp;

class Database{

    private $pdo; //returns PDO object

    function __construct(){

         //create pdo connection
         $this->pdo = ..
    }

    function getPdo(){
         return $this->pdo;
    }

}

数据库应注入对象或由对象使用,您不应仅仅为了拥有它而扩展数据库。如果你想以面向对象的方式正确地做到这一点。

记住PHP不允许通过扩展进行多次继承。明天,您可能希望拥有一个每个用户都会扩展的Person类,但由于您在开始时做错了,并且在数据库上浪费了宝贵的extend,因此无法实现。如果无法控制已创建的数据库实例数,则会遇到问题。您需要确定一个数据库只有一个连接对象,如果当然相反是必须的 - 在您的情况下我怀疑。

当然,如果您有多个数据库要求和更复杂的应用程序结构,这将会改变。

答案 1 :(得分:0)

您收到此错误,因为用户实例已将pdo设为空。试试这段代码

$servername = "****";
$database = "****";
$username = "****";
$password = "****";

try {
    $pdo = new PDO("mysql:host=$servername;dbname=$database", $username, $password);
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch(PDOException $e) {
    echo "Connection failed: " . $e->getMessage();
}

class Database {

  protected $pdo;

  public function __construct($pdo) {
    $this->pdo = $pdo;
  }
}

class User extends Database {

  private $ip;
  private $sessionId;

  public function __construct($pdo, $ip, $sessionId) {\
    parent::__construct($pdo)
    $this->ip = $ip;
    $this->sessionId = $sessionId;
  }
  public function getSessionInfo () {
    $stmt = $this->pdo->prepare("..");
    ....
  }
}

然后

require_once 'api/core.php';
$user = new User($pdo, $_SERVER['REMOTE_ADDR'], $_SESSION['info']['id']);
希望它有所帮助。

相关问题