mysqli prepare statement error "MySQL server has gone away" - php

I'm struggling to make the jump form Procedural to Object Orientated style so if my code is untidy or flawed please be nice - here I'm passing a couple of posts via jQuery to a class to update a record when the user checks a checkbox:
Here is the database connection
class db {
private $host ;
private $username;
private $password;
private $dbname;
protected function conn()
{
$this->host = "localhost";
$this->username = "root";
$this->password = "";
$this->dbname = "mytest";
$db = new mysqli($this->host, $this->username, $this->password, $this->dbname);
if($db->connect_errno > 0){
die('Unable to connect to database [' . $db->connect_error . ']');
}
return $db;
}
}
Here is the update class
class updOrders extends db {
public $pid;
public $proc;
public function __construct()
{
$this->pid = isset($_POST['pid']) ? $_POST['pid'] : 0;
$this->proc = isset($_POST['proc']) ? $_POST['proc'] : 1;
// $stmt = $this->conn()->query("UPDATE tblorderhdr SET completed = ".$this->proc." WHERE orderid = ".$this->pid);
$stmt = $this->conn()->prepare("UPDATE tblorderhdr SET completed = ? WHERE orderid = ?");
$stmt->bind_param('ii', $this->proc, $this->pid);
$stmt->execute();
if($stmt->error)
{
$err = $stmt->error ;
} else {
$err = 'ok';
}
/* close statement */
$stmt->close();
echo json_encode($err);
}
}
$test = new updOrders;
When I comment out the prepare statement and run the query directly (commented out) it updates, when I try and run it as a prepare statement it returns an error "MySQL server has gone away".

I have looked at your code and I found this.
$stmt = $this->conn()->prepare("UPDATE tblorderhdr SET completed = ? WHERE orderid = ?");
I wrote nearly the same. But I saw you separated the connection from the prepare function.
$db = $this->conn();
$stmt = $db->prepare("UPDATE tblorderhdr SET completed = ? WHERE orderid = ?");
I don't know either why, but it works now.

It would appear that the problem lies within the connection to the database. Here is the (relevant bit of the) updated code:
$db = $this->conn();
$stmt = $db->prepare("UPDATE tblorderhdr SET completed = ? WHERE orderid = ?");
$stmt->bind_param('ii', $this->proc, $this->pid);
$stmt->execute();

When you call $this->conn(), you are creating a new connection object of class mysqli. When no more variables point to the object, PHP will trigger its destructor. The destructor for mysqli will close the connection. This means that if you do not save the return value of this method into a variable, there will be no more references pointing to the object and the connection will be closed.
To fix this, simply save the object and reuse it. Don't connect each time.
$conn = $this->conn();
$stmt = $conn->prepare("UPDATE tblorderhdr SET completed = ? WHERE orderid = ?");
On a side note, creating a class like the one you have db is absolutely pointless. This class doesn't do anything useful. You haven't added any extra functionality to mysqli. You never need to save the credentials in properties. The whole class can be replaced with this code:
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$mysqli = new mysqli('localhost', 'user', 'password', 'test');
$mysqli->set_charset('utf8mb4'); // always set the charset
Then your classes will expect the mysqli object as a dependency.
class updOrders {
public $pid;
public $proc;
public function __construct(mysqli $conn) {
}

Related

Error SQL Syntax

hi im rather new to SQL and im currently trying to save some data into a Sql database using a website. But everytime i run it i get some Syntax error and now after many hours of looking i was hoping somebody in here knew an answer, or could lead me in the right direction :)
this is the error i get when i hit my submit button :
0You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '[Campus one],[101],[2016-12-08],[test])' at line 1
this is the insert part of the script, connection part seems to be running fine
$sql = "INSERT INTO `formel`(`Område`, `Værelse`, `Dato`, `TV Fjernsyn Forlænger`) VALUES ([$area],[$filnavn],[$dato],[$Fjernsyn]) ";
SQL information:
Your values need to be changed from:
[$area],[$filnavn],[$dato],[$Fjernsyn]
to:
'{$area}','{$filnavn}','{$dato}','{$Fjernsyn}'
You should really be binding your params though. I assume you're using mysql_ which you shouldn't be using anymore therefore I also suggest you look into mysqli_ or PDO.
Edit:
You should move over to PDO in fairness, I did and I love it!
I work with classes a lot as it's a neater way to work so I'll give you my input:
Make yourself a dbConfig.php file:
class Database
{
private $host = "localhost";
private $db_name = "dbName";
private $username = "username";
private $password = "password";
public $conn;
public function dbConnection()
{
$this->conn = null;
try
{
$this->conn = new PDO("mysql:host=" . $this->host . ";dbname=" . $this->db_name, $this->username, $this->password);
$this->conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}
catch(PDOException $exception)
{
echo "Connection error: " . $exception->getMessage();
}
return $this->conn;
}
}
So because i am half lazy and why type code over and over?
Create yourself a dbCommon.php file.
class DBCommon
{
private $conn;
/** #var Common */
public $common;
public function __construct()
{
$database = new Database();
$db = $database->dbConnection();
$this->conn = $db;
}
public function runQuery($sql)
{
$stmt = $this->conn->prepare($sql);
return $stmt;
}
}
Then you need a class file for your PDO to go into such as:
class.update.php:
require_once('dbCommon.php');
class Update extends DBCommon
{
function __construct()
{
parent::__construct();
}
public function updateCode($area, $filnavn, $dato, $Fjernsyn)
{
$stmt = $this->runQuery("INSERT INTO `formel` (`Område`, `Værelse`, `Dato`, `TV Fjernsyn Forlænger`) VALUES (:area, :filnavn, :dato, :Fjernsyn)");
$stmt->bindParam(array(':area' => $area, ':filnavn' => $filnavn, ':dato' => $dato, ':Fjernsyn' => $Fjernsyn));
$stmt->execute();
echo "Your insert command has been completed!";
}
}
Then within your file.php where you would be calling the class you need to do:
require_once ('class.update.php');
$update = new Update();
if (isset($_POST['send']))
{
$update->updateCode($_POST['area'], $_POST['filnavn'], $_POST['dato'], $_POST['Fjernsyn']);
}
Note: Because you didn't post your $_POST['name']'s in I have given you a base example.
Binding your params is best practice as this prevents SQL Injection.
With binding params you dont have to run $stmt->bindParam(); You can simply run $stmt->execute(array(':paramshere' => $paramVar));
It totally depends on your preference but I always prefer binding before executing (personal preference). I hope this gives you some input and insight on how to move into PDO instead but it really is the way forward.
In order to prevent SQL injection, you should really use Prepared Statements, or correctly escape your strings. Please look at MySQLi or PDO.
Here's a basic tutorial using PDO and Prepared Statements inside of PHP:
// Connect to the database:
$db = new PDO( 'mysql:dbname=DB_NAME;host=localhost', 'DB_USER', 'DB_PASS' );
// Prepare the statement:
$ins = $db->prepare( 'INSERT INTO `formel` (`Område`, `Værelse`, `Dato`, `TV Fjernsyn Forlænger`) VALUES (:area, :filnavn, :dato, :Fjernsyn' );
// Execute with bindings:
$ins->execute(array(
':area' => $area,
':filnavn' => $filnavn,
':dato' => $dato,
':Fjernsyn' => $Fjernsyn
));
Try This,
$sql = "INSERT INTO `formel`(`Område`, `Værelse`, `Dato`, `TV Fjernsyn Forlænger`) VALUES ('$area','$filnavn','$dato','$Fjernsyn') ";
I think it should work.
Change your query to this
$sql = "INSERT INTO formel(Område, Værelse, Dato, TV Fjernsyn Forlænger) VALUES ('$area','$filnavn', '$dato', '$Fjernsyn') ";
But I would suggest you use prepared statement for security purposes

How to fix Fatal error: Call to a member function prepare() on null in

Fatal error: Call to a member function prepare() on null in C:\xampp\htdocs\af\functions\indexdatasummary.php on line 6
dbconnect.php
global $dbh;
//Server Variables========-------------->
$af_host="localhost";
$af_root="root";
$af_password="";
//Database Variables========------------>
$af_cbms_database="af_cbms";
try
{
$dbh = new PDO("mysql:host=$af_host", $af_root, $af_password);
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);
$af_cbms_database = "`" . str_replace("`", "``", $af_cbms_database) . "`";
$dbh->query("CREATE DATABASE IF NOT EXISTS $af_database");
$dbh->query("SET CHARACTER SET utf8");
$dbh->query("USE $af_database");
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);
}
catch(PDOException $e)
{
echo $e->getMessage();
}
the above code I use is working for almost all of my pages but in this page it's having an error. the way I call this is just the same way for the other file and this is the only page that returns with error.
indexsummary.php
global $dbh;
require_once '../functions/dbconnect.php';
$stmt = $dbh->prepare("SELECT * FROM `city_tbl`");
$stmt->execute();
and soon.....
what do you think is causing this error? any help!
1) Your problem with creating connection and creating database.
Cuz You define:
$af_cbms_database="af_cbms";
and then You call:
$dbh->query("CREATE DATABASE IF NOT EXISTS $af_database");
so where in Your code You've defined $af_database variable?
2) it's too unprofessional to make this (seems like You're new to programming):
$af_cbms_database = "`" . str_replace("`", "``", $af_cbms_database) . "`";
You've already defined Your variable and then replacing it, funny, like You don't trust Yourself that You've defined variable? (:
or You cannot do it like this? :
$dbh->query("CREATE DATABASE IF NOT EXISTS `".$af_cbms_database."`");
$dbh->query("USE `".$af_cbms_database."`");
3) Don't complicate Your code wit too much of variables like $af_, be simple as in this fixed code of dbconnect.php:
<?php
global $dbh;
$host = "localhost";
$user = "root";
$password = "";
$db_name = "af_cbms";
try {
$dbh = new PDO("mysql:host=$host", $user, $password);
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$dbh->query("CREATE DATABASE IF NOT EXISTS ".$db_name);
$dbh->query("SET CHARACTER SET utf8");
$dbh->query("USE ".$db_name);
}
catch(PDOException $e) {
die($e->getMessage());
}
4) BONUS: Don't use global $dbh, because may happen that some process, some code can replace $dbh variable. Also using global vars is not in fashion (:
so have some Object that will keep shared stuff :
class Objs {
private $data = [];
final public static function set($key, $instance, $preventReset = false) {
if($preventReset === true AND isset(self::$data[$key])) {
return self::$data[$key];
}
return self::$data[$key] = $instance;
}
final public static function get($key, $instance) {
return self::$data[$key];
}
}
and in Your db connection file:
require_once('classes/Objs.php');
Objs::set('db', $dbh, true);
and in Your another files:
$stmt = Objs::get('db')->prepare('SELECT * FROM city_tbl');
I got this problem too. The error is I call the function before the function is declared. So I changed the sequence so that I call the function after it is declared.

Storing mysqli connection in object

I am trying to contain my mysqli object within a class, that other objects/scripts can use. I initialize it like so:
$this->host = $Host;
$this->username = $UName;
$this->password = $PWord;
$this->database = $DBName;
$this->debugEmail = $debugEmail;
// Create sql handler
$this->conn = new mysqli($this->host, $this->username, $this->password, $this->database);
// Check connection
if ($this->conn->connect_error) {
die("Connection Failed: " . $this->conn->connect_error());
}
The problem is when I use this object elsewhere, it seems to think that the conn object is null.
For example:
$sqlObj = new sqlObject();
$sqlObj->init();
// run query
$sql = "SELECT * FROM table";
$result = $sqlObj->getConn()->query($sql);
It returns:
Call to a member function query() on a non-object
Certainly $sqlObj->getConn() is returning null or false (or another object) that isn't the desired type.
I recommend you to throw a new error in getConn() and wrap with a try/catch block. In this throw, return the error coming from getConn and you'll be able to understand it better. BTW, Are the connection params ok ? It seems to be something related to this.

Cant pass mysqli connection to class

I am trying to pass an mysqli database connection to a php class. The code I have so far (cut down for simplicity) is as follows:
db.php
$db_host = 'localhost';
$db_name = 'dbname';
$db_user = 'username';
$db_password = 'password';
$db = array('db_host'=>$db_host,
'db_name'=>$db_name,
'db_user'=>$db_user,
'db_password'=>$db_password);
$dbCon = new mysqli( $db['db_host'],
$db['db_user'],
$db['db_password'],
$db['db_name']);
if (mysqli_connect_errno())
{
die(mysqli_connect_error()); //There was an error. Print it out and die
}
index.php
<?php
require_once($_SERVER["DOCUMENT_ROOT"] . "/db.php");
$sql = "SELECT id FROM usr_clients";
$stmt = $dbCon->prepare( $sql );
if ($stmt)
{
$stmt->execute();
$stmt->bind_result($id);
while($stmt->fetch())
{
$cl = new Client($id, $dbCon);
$cl->doIt();
}
$stmt->close();
}
?>
client.php
<?php
Class Client
{
private $con;
public static $clientCount = 0;
public function __construct( $id, $con )
{
$this->con = $con;
$sql = "SELECT id FROM usr_clients WHERE id = $id";
$stmt = $this->con->prepare( $sql );
if ($stmt)
{
echo "it worked!";
}
else
{
echo "it failed";
}
}
}
?>
Now the index.php page successfully recognises the database connection declared in db.php, and returns a list of all clients. It then loops through each client, and creates a "client" object, passing it the database connection.
It is here that the problem seems to start. In the client class, the database connection is not recognised. I get multiple errors on the page saying "it failed". In the logs, there is a line about calling prepare() on a non object.
Can anyone explain why the connection works in index.php, but not in the client class?
Thanks
Your main problem is assumptions.
You are assuming that there is no connection passed, judging by indirect consequence.
But a programmer should be always logically correct in their reasoning.
Talking of connection? Verify the very connection. var_dump($con) in the constructor. var_dump($this->con) in the method. If it fails - only now you can blame connection and start for the solution.
If not - there is no reason in looking for another connection passing method. Yet it's time to find the real problem.
If your query fails, you have to ask mysql, what's going on, using $this->con->error, as this function will provide you with a lot more useful information than simple "it fails". The right usage I've explained here: https://stackoverflow.com/a/15447204/285587

php pdo connection scope

Hey guys I have a connection class I found for pdo. I am calling the connection method on the page that the file is included on. The problem is that within functions the $conn variable is not defined even though I stated the method was public, and I was wondering if anyone had an elegant solution other then using global in every function. Any suggestions are greatly appreciated.
CONNECTION
class PDOConnectionFactory{
// receives the connection
public $con = null;
// swich database?
public $dbType = "mysql";
// connection parameters
// when it will not be necessary leaves blank only with the double quotations marks ""
public $host = "localhost";
public $user = "user";
public $senha = "password";
public $db = "database";
// arrow the persistence of the connection
public $persistent = false;
// new PDOConnectionFactory( true ) <--- persistent connection
// new PDOConnectionFactory() <--- no persistent connection
public function PDOConnectionFactory( $persistent=false ){
// it verifies the persistence of the connection
if( $persistent != false){ $this->persistent = true; }
}
public function getConnection(){
try{
// it carries through the connection
$this->con = new PDO($this->dbType.":host=".$this->host.";dbname=".$this->db, $this->user, $this->senha,
array( PDO::ATTR_PERSISTENT => $this->persistent ) );
// carried through successfully, it returns connected
return $this->con;
// in case that an error occurs, it returns the error;
}catch ( PDOException $ex ){ echo "We are currently experiencing technical difficulties. We have a bunch of monkies working really hard to fix the problem. Check back soon: ".$ex->getMessage(); }
}
// close connection
public function Close(){
if( $this->con != null )
$this->con = null;
}
}
PAGE USED ON
include("includes/connection.php");
$db = new PDOConnectionFactory();
$conn = $db->getConnection();
function test(){
try{
$sql = 'SELECT * FROM topic';
$stmt = $conn->prepare($sql);
$result=$stmt->execute();
}
catch(PDOException $e){ echo $e->getMessage(); }
}
test();
You can declarate database class where you carrying conn pdo class, then you don't must duplicates instaces of this. And all database operations you can doing by this class. I mean my answer is what you searching.
But i see, you using only PDO hadle class in Product Factory pattern. You can use normal full database support class under PDO (includes queryies execution from one function) and without this design pattern when you don't want to use many database connectors engines.

Categories