在我提出问题之前,我想确保一些事情是清楚的:
1)我阅读了关于OOP的官方PHP手册(介绍,基础知识,继承,属性等)。老实说,我似乎没有得到任何东西。我现在已经上了好几个小时并在那里修了一些东西然后又出现了新的错误。
2)我读取错误消息缺少Main :: __ construct()的参数1和Undefined变量:array。这意味着我的$ start变量为NULL。
3)我确实对stackoverflow进行了一些搜索,要么它没有完全相关,要么我很难理解最新情况,因为示例代码非常复杂(对于启动程序来说不是最好的事情) )。
我的问题:为什么下面的代码不起作用?我真的很感激为什么它失败了,我需要考虑什么。
class Main {
protected $config;
protected $start;
function __construct($arr) {
if(!isset($this -> start)) {
if ($arr['secure']){
$this -> config = parse_ini_file('C:\xampp\htdocs\project\config.ini');
$this -> start = mysqli_connect($this -> config['host'], $this -> config['username'],
$this -> config['password'], $this -> config['database']);
}
else {
$this -> start = mysqli_connect($arr['host'], $arr['username'], $arr['password'], $arr['database']);
}
}
if($this -> start == false) {
return mysqli_connect_error();
}
}
}
$Main = new Main($array = ["host" => '', "username" => '', "password" => '', "database" => '',
"errors" => false, "secure" => true]);
class Test extends Main {
public function sample() {
$query = "SELECT id, user,
FROM users";
$result = mysqli_query($Main -> start , $query);
$row = mysqli_fetch_array($result);
echo $row['user'];
}
}
$x = new Test();
$x -> sample();
答案 0 :(得分:3)
所以这是运行时发生的事情:
$Main = new Main(...);
好的,如果填写了这些详细信息,您可能会在那里获得连接,但在确定您是否成功建立连接时存在问题。请参阅下面的详细信息,但$Main
暂时需要注意。
$x = new Test();
班级Test
扩展了您的班级Main
。
因此,您的类Test
会继承类Main
的构造函数,这需要一个参数。该论点未提供,因此会生成警告。
为了解决这个问题,如果你并不总是要传递$arr
,请选择function __construct($arr = array())
:
isset
然后在索引上使用if(isset($arr['secure'])) // ...
检查它是否存在:
$arr
快进,因为您还没有提供mysqli_connect
,您将无法成功连接到您的数据库。根据{{3}},$this -> start = mysqli_connect( ... )
// ...
if ($this -> start == false) {
是别名,它将尝试返回一个对象("表示与MySQL服务器的连接。")。
现在,看看以下几行:
mysqli_connect
感谢下面的评论,您还应该检查错误的分配,因为已知$x -> sample();
会生成警告并返回false,即使它没有显示在PHP文档中。
让我们继续。
Test::sample
mysqli_query
使用$Main->start
,它希望数据库连接成为它的第一个参数。您可以通过传递$Main
来尝试此操作。
不幸的是,$this->start
不在You must check against the return's connect_error
attribute (or mysqli_connect_error()
) to verify if the connection worked or not.中,并且无法从该方法内部访问。您需要参考的是$Main
。
事实上,如果这是您实例化new Test()
的唯一原因,那么此时您就不需要了。相反,请将连接详细信息数组传递给$x = new Test();
。
以下是两个解决方案:
Main
然后,实例将按预期连接到数据库,并且能够运行查询。 从类Main中分离类Test,并通过类Test构造函数传递类Main的实例。
可能是更好的选择。如果您的测试是针对您的查询而不是扩展new Main(..)
,请创建数据库连接对象(new Test($Main)
),然后将其传递到 public function __construct(Main $main)
{
$this->db = $main;
}
。在Test类中,创建一个构造函数,该构造函数接受Main类作为参数:
$main
通过制作$start
public
属性getter
或创建getConnection()
功能(例如$result = mysqli_query($this->db->getConnection(), $query);
}来允许访问您的连接对象),然后使用比你的查询:
xmls
您可以采用多种方式来实现您的方案,这取决于您。 答案已经解决了最初的问题,但我想我也可能会提供一些实施建议。
答案 1 :(得分:0)
$result = mysqli_query($Main -> start , $query);
到
$result = mysqli_query($this -> start , $query);
至少删除了语法错误。 $this
是一个内省变量,它总是指当前的实例范围。
答案 2 :(得分:0)
您正在使用两个不同的实例。
// This is one instance
$Main = new Main([...]);
// This is a different instance.
$test = new Test();
扩展类并不意味着它从类的现有实例中获取值。它只表示它获得相同的方法(和默认属性)。
因此,您的类Test获取与Main相同的构造函数,这意味着您需要将数组发送到Test以便能够使用它实例化它。在您的示例中,没有理由直接实例化Main。
答案 3 :(得分:0)
查看以下评论
//I suggest to make this class abstract to make sure
//php doesn't let you to instantiate it directly as you did before
abstract class Main {
protected $config;
protected $start;
function __construct($arr) {
if(!isset($this -> start)) {
if ($arr['secure']){
$this -> config = parse_ini_file('C:\xampp\htdocs\project\config.ini');
$this -> start = mysqli_connect($this -> config['host'], $this -> config['username'],
$this -> config['password'], $this -> config['database']);
}
else {
$this -> start = mysqli_connect($arr['host'], $arr['username'], $arr['password'], $arr['database']);
}
}
if($this -> start == false) {
return mysqli_connect_error();
}
}
}
class Test extends Main {
public function sample() {
$query = "SELECT id, user,
FROM users";
//Here you should use $this instead of $Main as you can access protected
//properties of the parent from the child class.
$result = mysqli_query($this -> start , $query);
$row = mysqli_fetch_array($result);
echo $row['user'];
}
}
//Instantiate Test class instead of Main as it inherits Main anyway
//Your code also had a typo in the constructor argument.
$x = new Test(array("host" => '', "username" => '', "password" => '', "database" => '', "errors" => false, "secure" => true));
$x -> sample();
请注意,我没有检查代码的mysql部分 - 只是一个OOP结构