mysqli :: prepare()和bind_param()的问题 [英] Issues with mysqli::prepare() and bind_param()
问题描述
我的应用程序中包含以下类:
I have the following classes in my application:
<?php
class Connection extends Mysqli{
public function __construct($mysqli_host,$mysqli_user,$mysqli_pass, $mysqli_db) {
parent::__construct($mysqli_host,$mysqli_user,$mysqli_pass,$mysqli_db);
$this->throwConnectionExceptionOnConnectionError();
}
private function throwConnectionExceptionOnConnectionError(){
if(!$this->connect_error){
echo "Database connection established<br/>";
}else{
//$message = sprintf('(%s) %s', $this->connect_errno, $this->connect_error);
echo "Error connecting to the database.";
throw new DatabaseException($message);
}
}
}
class DatabaseException extends Exception
{
}
class Page extends Mysqli{
private $con;
public function __construct(Connection $con) {
$this->con = $con;
if(isset($_GET['id'])){
$id = $_GET['id'];
}else{
$id = 1;
}
$this->get_headers($id);
$this->get_content($id);
$this->get_footer($id);
}
private function get_headers($pageId){
$retrieveHead = $this->con->prepare("SELECT headers FROM pages WHERE page_id=?");
$retrieveHead->bind_param('i',$pageId);
$retrieveHead->execute();
$retrieveHead->bind_result($header);
$retrieveHead->fetch();
$retrieveHead->close();
echo $header;
}
private function get_footer($pageId){
$retrieveFooter = $this->con->prepare("SELECT footer FROM pages WHERE page_id=?");
$retrieveFooter->bind_param('i',$pageId);
$retrieveFooter->execute();
$retrieveFooter->bind_result($footer);
$retrieveFooter->fetch();
$retrieveFooter->close();
echo $footer;
}
private function get_content($pageId){
$retreiveContent = $this->con->prepare("SELECT template_id, section_title, i1, i2 FROM content WHERE page_id=? ORDER BY sequence DESC");
$retreiveContent->bind_param('i',$pageId);
$retreiveContent->execute();
$retreiveContent->bind_result($template_id, $section_title, $i1, $i2);
while ($retreiveContent->fetch()) {
//Variables will be populated for this row.
//Update the tags in the template.
$template = $this->get_template($template_id);
$template = str_replace('[i1]',$i1,$template);
$template = str_replace('[i2]',$i2,$template);
//$theTemplate is populated with content. Probably want to echo here
echo $template;
}
}
private function get_template($template_id){
$retreiveTemplate = $this->con->prepare("SELECT code FROM templates WHERE template_id=?");
$retreiveTemplate->bind_param('i',$template_id);
$retreiveTemplate->execute();
$retreiveTemplate->bind_result($template);
$retreiveTemplate->fetch();
$retreiveTemplate->close();
return $template;
}
}
?>
小型应用程序基本上应该从url中获取page变量,并使用它来拉出页面的页眉,内容项和页脚,并使用也从数据库检索到的模板来呈现内容项.运行包含以下代码的索引文件时:
The small application should basically get the page variable from the url and use it to pull out the header, content items and footer of the page with the content items being rendered using a template which is also retreived from the database. When running my index file which contains the following code:
require ("/req/db_connection.php");
require ("/req/connection.php");
$dbConnection = new Connection($mysqli_host,$mysqli_user,$mysqli_pass, $mysqli_db);
$page = new Page();
我得到以下输出:
Database connection established
Warning: mysqli::prepare(): Couldn't fetch Page in C:\xampp\htdocs\forum\req\connection.php on line 39
Fatal error: Call to a member function bind_param() on a non-object in C:\xampp\htdocs\forum\req\connection.php on line 40
有人能指出我为什么会遇到这些错误的正确方向吗?
Could anyone point in the right direction as to why I am experiencing these errors?
第39行是以下语句:
$retrieveHead = $this->prepare("SELECT headers FROM pages WHERE page_id=?");
第40行当然是:
$retrieveHead->bind_param('i',$pageId);
任何帮助将不胜感激.
上面的代码现在已经根据下面的答案进行了更正,但是我仍然在第80行遇到以下错误:
N.B. The code above has now been corrected based on the answers below however I am still experiencing the following error at line 80:
Call to a member function bind_param() on a non-object in C:\xampp\htdocs\forum\req\connection.php on line 80
这是哪一行:
$retreiveTemplate->bind_param('i',$template_id);
有什么建议吗?
推荐答案
class Page extends Mysqli{
public function __construct() {
if(isset($_GET['id'])){
$id = $_GET['id'];
}else{
$id = 1;
}
$this->get_headers($id);
$this->get_content($id);
$this->get_footer($id);
}
上面的代码看起来像是问题(在其他问题中).您扩展了mysqli,覆盖了构造函数,并且不调用父构造函数.结果,没有一个基本的mysqli构造函数例程被调用,并且您没有任何连接.考虑重新设计对象,并将其传递给Connection
对象,而不是将mysqli扩展到任何地方.我还将尝试避免在构造函数中完成所有这些工作.例如,您的页面类可能类似于:
This code above looks like the problem (amongst others). You extend mysqli, override the constructor and do not call the parent constructor. As a result none of the base mysqli constructor routines are invoked and you are left with no connection. Consider redesigning your objects and pass them your Connection
object as opposed to extending mysqli everywhere. I'd also try to avoid doing all that work in the constructor. For example your page class could look something like:
class Page{
private $con;
public function __construct(Connection $con) {
$this->con = $con;
}
public function get_headers($pageId){
$retrieveHead = $this->conn->prepare("SELECT headers FROM pages WHERE page_id=?");
//...
}
}
当我在上面打上其他"时(我不劝阻)时,我暗示-尽管错误的真正原因是构造函数-您的类和OOP概念的设计似乎有些混乱一般来说.
When I quipped "amongst others" (no discouragement intended) above I was hinting that -- while the actual cause of your error was the constructor -- there looks to be some confusion in the design of your classes and of OOP concepts in general.
class Connection extends Mysqli{
public function __construct($mysqli_host,$mysqli_user,$mysqli_pass, $mysqli_db) {
parent::__construct($mysqli_host,$mysqli_user,$mysqli_pass,$mysqli_db);
$this->throwConnectionExceptionOnConnectionError();
}
}
在这里,您已使用Connection
类扩展了mysqli
,并正确调用了父构造函数,并传递了所有必需的参数以建立连接.如果实例化此类型$myConnection = new Connection(...)
的对象,则它可以充当数据库的网关.
Here you have extended mysqli
with your Connection
class, and correctly called the parent constructor and passed all the required parameters to establish a connection. If you instantiate an object of this type $myConnection = new Connection(...)
it can act as your gateway to the database.
其他类(例如Page
)可能需要对数据库执行操作,并且它们可以通过Connection
来实现,而不需要扩展mysqli
本身.您可以在Page
构造函数中传递Connection
的实例以实现此目的.所以您的代码行在这里:
Other classes like Page
may need to perform operations on the database and they can do it via Connection
not by extending mysqli
itself. You can pass an instance of Connection
in the Page
constructor to achieve this. So your lines of code here:
$dbConnection = new Connection($mysqli_host,$mysqli_user,$mysqli_pass, $mysqli_db);
$page = new Page();
将变为(经过对如上所示的Page类进行一些修改之后):
Would become (after some modification to Page class like shown above):
$dbConnection = new Connection($mysqli_host,$mysqli_user,$mysqli_pass, $mysqli_db);
$page = new Page($dbConnection);
这篇关于mysqli :: prepare()和bind_param()的问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!