我的数据库类中有一个PDO连接,最近我一直使用它作为其他类的扩展,即class Users extends Database
这使我可以始终保持数据库连接,而无需在我的Users类中有一个函数
然而有人指出我不应该这样做是不好的做法,为什么这是不好的做法?如何在不扩展的情况下连接到我的用户类中的数据库类?
目前我在viewall()
函数中调用了数据库,我试图将其放在__construct()
函数中但是它坚持使用参数
我已尝试过以下代码但是我收到如下错误消息:
Fatal error: Call to undefined method Database::prepare() in E:\xampp\htdocs\attendance\class.Register.php on line 13
关于如何调用我的数据库的任何想法?
这是我的代码:
class.Connect.php
<?php
// Database connection PDO
class Database {
public function __construct() {
// Connection information
$host = 'localhost';
$dbname = 'attendance';
$user = 'root';
$pass = '';
// Attempt DB connection
try
{
$this->pdo = new PDO("mysql:host=$host;dbname=$dbname", $user, $pass);
$this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
//echo 'Successfully connected to the database!';
}
catch(PDOException $e)
{
echo $e->getMessage();
}
}
public function __destruct()
{
// Disconnect from DB
$this->pdo = null;
//echo 'Successfully disconnected from the database!';
}
}
?>
class.Register.php
<?php
require 'class.Connect.php';
class Register {
public function viewall() {
$pdo = new Database();
$stmt = $pdo->prepare('SELECT * FROM users');
$stmt->execute();
$stmt->fetch();
}
}
$run = new Register();
$run->viewall();
?>
答案 0 :(得分:8)
简单的经验法则:如果一个类extends
是另一个,那么该类是那个父类(只是稍微改变或扩展)。您可以传递此子类而不是父类。例如:
class Foo { }
class Bar extends Foo { }
function baz(Foo $foo) { }
baz(new Bar);
这有效,baz()
需要Foo
,但也接受Bar
,因为Bar
是Foo
。< / p>
现在, 您的Users
a Database
?不。您的用户不是数据库。您的用户使用数据库。如果有的话,你应该使用组合:
class User {
protected $database;
public function __construct(Database $database) {
$this->database = $database;
}
}
一个类 用户管理类的职责是管理用户数据。其中一部分可能涉及与数据库通信,但这并不意味着用户管理类 是一个数据库。如果User extends Database
,这意味着它可以执行Database
类可以执行的所有操作(以及更多)。这意味着您可以在处使用User
类而不是 Database
类,这没有任何意义。将责任分开。
现在,这是否是正确的结构仍然存在争议,但它正朝着正确的方向发展。但是你可能真的想要一个User
类,它代表一个用户。然后,您有UserManager
或UserORM
或UserStorage
或其他任何内容,这与在数据库中检索和存储User
个对象有关。该类依次使用 Database
来做到这一点。这使责任明确和分离。 User
类表示用户数据,Database
类与数据库交互,中间的UserORM/Manager/whatever
在两者之间协商。
答案 1 :(得分:1)
扩展课程是否良好实践?
嗯,是的,如果你做对了正确的原因。
面向对象编程中的继承(类扩展)的概念就像在现实世界中拥有这些对象一样。
在现实世界中,当您使用世界汽车时,按照惯例,您通常意味着所有汽车并且您考虑其中的常见属性,例如车轮,发动机,转向,油门,制动器等。 但也有一些汽车具有这些属性和一些额外的,例如消防车汽车也有一些额外的属性,如附加梯子,一些投掷水管等。 对于某些物体的“行为”也可以考虑相同的情况,例如,汽车可以移动,并且我们的意思是你在道路上有车轮旋转以便移动(通过汽车移动方法建模)。 此外,救火车可能具有延长的行为,例如可以在其具有的梯子上下移动。这可以通过在FireTruckCar类中使用moveLadder()方法来建模。
如果您想在PHP类(OOP)中表示这些概念,您可以这样做:
class Car {
protected $wheels;
protected $engine;
//Rest attributes of Car.
public function __construct($wheels, $engine) {
$this->wheels = $wheels;
$this->engine = $engine;
//Initialize more attributes.
}
function move(){
$this->wheels->rotate();
}
//.....
}
类FireTruckCar扩展了汽车{
//Additional Attributes.
//The attributes of Car class belong to this
//one too and are accessible as private.
protected $ladder;
protected $tubes;
public function __construct($wheels, $engine, $ladder, $tubes) {
//Call the parent constructor, to initialize parent attributes
parent::__construct($wheels, $engine);
$this->ladder = $ladder;
$this->tubes = $tubes;
}
function moveLadder($direction){
$this->ladder->move($direction);
}
//...
}
当然,继承中还有许多其他概念,一般是OOP,例如方法重载/覆盖,抽象类等,但我不是在这里解释它们,因为这一点将被遗漏。我建议你搜索面向对象的编程原理虽然并且很好地了解它们。
答案 2 :(得分:0)
可能有多种方法可以连接到数据库,以便在应用程序中的任何位置都有连接。对于一个好的做法,您可以通过使用另一个可以处理数据库操作的类来轻松地完成此操作,并扩展需要该类操作的所有类。
首先更改一下Database类,并传递数据库连接的参数,如下所示:
<?php
// Database connection PDO
class Database {
public function __construct($host, $dbname, $user, $pass) {
// Connection information
// Attempt DB connection
try
{
$this->pdo = new PDO("mysql:host=$host;dbname=$dbname", $user, $pass);
$this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
//echo 'Successfully connected to the database!';
}
catch(PDOException $e)
{
echo $e->getMessage();
}
}
public function __destruct()
{
// Disconnect from DB
$this->pdo = null;
//echo 'Successfully disconnected from the database!';
}
}
?>
现在创建另一个类,让我们将其称为ObjectModel,如下所示
class ObjectModel
{
protected $db
public function __construct()
{
$this->db = new Database($host, $dbname, $user, $pass) //ofcourse you can get the db connections details and database name from a config file
}
// you can have more db operations functions like insert, update, delete etc
}
因此,ObjectModel类将处理所有CRUD和其他数据库操作以及运行查询。现在,如果要使用$ db对象,可以直接在ObjectModel类中使用它,也可以在OBjectModel的子类中使用它,如下所示:
class Users extends ObjectModel
{
public function getUsers()
{
//$this->db-> whatever operation you want to do you can do it using this db object
}
}
请记住,ObjectModel有一个名为$ db的Database类的对象,所以如果你的Database类使用的是PDO,那么你的ObjectModel $ db对象将拥有所有这些操作,即使用PDO。
我希望这对你也有帮助,因为我正在为我的类使用这样的ObjectModel类,它为我节省了大量时间来反复编写代码:)。
快乐编码;)