对不起这个愚蠢的问题我是一个新手来在php中oop ...我有一个问题,一个mysqli类,它返回一个连接处理程序,使我能够在其他类/方法中的连接处理程序。我运行一个小程序博客,想要转换为oop。 这是我工作的代码示例。请在必要时为我重构。提前谢谢。
$db_link = mysqli_connect(DB,HOST,DB_USER,DB,PASS,DB_NAME) or die(mysql_error());
class myDB extends mysqli
{
public function getConfig($id, $db_link) // thanks cbuckley
{
$db_link = $this->db_link;
$res = mysqli_query($this->db_link,"SELECT * from config where id='1'");
$row = mysqli_fetch_array($res);
return $row['option'];
}
}
我已经定义了常量并且连接成功但是select不起作用。在索引页面上,这是
include('inc/dbc.php');
$db = new MyDB();
echo $db->getConfig(1, $db_link);
感谢任何帮助
答案 0 :(得分:6)
你的问题不是很具体,我觉得你并不知道你的具体问题是什么。您已经接受了一个答案,它会为您提供一些代码,但会使您处于错误的方向,因为它无法解决您的潜在问题并浪费代码。
如果你想利用PHP的mysqli扩展的面向对象接口,你应该知道的第一件事是,Mysqli
类代表数据库连接(因为它被命名为“链接”)程序方法):
require('inc/dbc.php');
$dbConnection = new Mysqli(DB_HOST, DB_USER, DB_PASS, DB_NAME);
已经是这样了。当然你可能想在这里使用一些错误处理:
if ($dbConnection->connect_error)
{
throw new Exception(
sprintf('(#%d) %s', $dbConnection->connect_errorno,
$dbConnection->connect_error)
);
}
抛出异常而不是让我们说die('message')
已完成,因为您可以轻松创建异常处理程序,以便您可以在中心位置向用户显示更有用的响应,而不是处理每个异常错误情况它出现的地方(实际上在die
所在的地方。)
您还可以记录和邮寄回溯,以便更轻松地修复问题。当然,您不需要使用异常,但经验法则是仅在您扔掉的脚本中使用die
,比如说一周,并且它不适用于面向对象的设计。
因为在需要数据库连接的所有地方,无论如何都需要此代码,您可以创建自己的连接对象,将这些部分放在一起,因为它们属于一起:
class DatabaseException extends Exception
{
}
class DatabaseConnection extends Mysqli
{
public function __construct($host, $user, $password, $database = "", $port = NULL, $socket = NULL) {
parent::__construct($host, $user, $password, $database, $port, $socket);
$this->throwConnectionExceptionOnConnectionError();
}
private function throwConnectionExceptionOnConnectionError() {
if (!$this->connect_error) return;
$message = sprintf('(%s) %s', $this->connect_errno, $this->connect_error);
throw new DatabaseException($message);
}
}
用法实际上非常简单,非常相同,只有类的名称有所不同,需要加载它的定义:
require('inc/dbc.php');
require('inc/database.php');
$dbConnection = new DatabaseConnection(DB_HOST, DB_USER, DB_PASS, DB_NAME);
如上所述,连接对象已经表示您的数据库连接。因此,应用程序中需要它的每个部分都必须要求它。让我们回顾一下您的示例函数:
function getOption($id, $db_link)
{
// $db_link = $this->db_link;
$res = mysqli_query($this->db_link,"SELECT * from config where id='1'");
$row = mysqli_fetch_array($res);
return $row['option'];
}
我重命名了这个功能,我评论了第一行,即使这可能是你想要的。实际上,如果该函数将成为DatabaseConnection
对象的一部分,它可以这样工作:
class DatabaseConnection extends Mysqli
{
...
public function getOption($id) {
$statement = $this->prepare('SELECT `option` FROM config WHERE id=?');
$statement->bind_param('i', $id);
$statement->execute();
$statement->bind_result($option);
$statement->fetch();
$statement->close();
return $option;
}
如本例所示,数据库连接已经存在。但是,这是不可取的。想象一下,你不仅有选择,还有这个和那个等等,而不是更多。您将在一个类中创建另一个函数。对于一个可能正常工作的小应用程序,但想象越来越多。你会得到一个非常大的课程,负责很多事情。因此,即使您已经使用$this
来准备语句,这样做也会很糟糕。
另请注意,您应准备陈述。这已经在这里得到了很多次回答,如果你不习惯它,阅读它,它是值得的。有一些更好的方法可以在进入面向对象时不重复代码(DRY:不要重复自己)(你甚至应该已经通过程序执行此操作)。
因此,将这一切都放在一个类中会是一个问题,而是将它放在它自己的类中:
class DatabaseModelBase
{
protected $connection;
public function __construct(Connection $connection) {
$this->connection = $connection;
}
protected function prepare($query) {
$connection = $this->connection;
$statement = $connection->prepare($query);
if (!$statement) {
throw new DatabaseException(
sprintf('(%s) %s', $connection->error, $connection->errno)
);
}
return $statement;
}
}
class Option extends DatabaseModelBase
{
public function find($id) {
$statement = $this->prepare('SELECT `option` FROM config WHERE id=?');
$statement->bind_param('i', $id);
$statement->execute();
$statement->bind_result($option);
$statement->fetch();
$statement->close();
return $option;
}
}
这又有一些扩展错误处理,因为大多数错误都是在SQL查询中产生的。正如您所看到的,获取某些特定数据的单个函数被放置在它自己的类中。您可以使用此类对特定数据类型的提取和更新进行分组。
完整使用:
$dbConnection = new Connection(DB_HOST, DB_USER, DB_PASS, DB_NAME);
$option = new Option($dbConnection);
$optionValue = $option->find(1);
echo $optionValue; # value for option with ID1
Option
对象的名称可能不太好,我试图保持示例轻量级但也提供一些分离。对于其他风格,您可能希望更喜欢某种不同类型如何访问数据库连接,因为它通过它的构造函数注入Option
,Option
不再处理数据库连接的详细信息。被创造。
例如,您可以使数据库连接对象更加智能,只有在第一次准备或查询实际使用时才连接到数据库。因此,对您的网站的不需要数据库连接的请求不会不必要地连接到数据库。
您可以在其他问题中找到更多示例,您可能希望了解依赖注入。此外,你总是希望彼此分开,所以你有一些只是轻微相互连接的物体。
答案 1 :(得分:3)
我建议将连接移动到类中的数据库:
class myDB extends mysqli
{
private $link;
public function Connect()
{
$this->link = mysqli_connect(DB,HOST,DB_USER,DB,PASS,DB_NAME) or die(mysql_error());
}
public function getConfig($id) // thanks cbuckley
{
$res = mysqli_query($this->link,"SELECT * from config where id='$id'");
$row = mysqli_fetch_array($res);
return $row['option'];
}
}
并像这样使用它:
include('inc/dbc.php');
$db = new MyDB();
$db->Connect();
echo $db->getConfig(1);
答案 2 :(得分:2)
我建议你将mysqli类包装在一个新类中,而不是扩展它: 对于那些需要配置的类,只需包含带依赖注入的配置。这为您带来了好处,您需要配置的代码,不需要了解方式,配置获取其值。 如果您以后决定从iniFile解析Configuration,您只需更改Configuration-Class甚至更好,编写一个实现ConfigurationInterface的新类并注入新的ConfigurationClass。
class Configuration implements ConfigurationInterface{
private $mysqli;
public function construct(mysqli $mysqli) {
$this->mysqli = $mysqli;
}
public function get($key)
{
// You should escape this query to prevent SQL-injection
$res = $this->mysqli->query("SELECT * from config where id='$key'");
$row = $res>fetch_array();
return $row['option'];
}
}
interface ConfigurationInterface {
public get($key);
}
像这样使用:
$mysqli = new mysqli('localhost', 'root', 'pw', 'my_db');
$config = new Configuration($mysqli);
var_dump($config->get(0));