mysql table creation with PDO fails - php

I'm rewriting my php code for mysql database access (now using a class definitions). While I had the old code (using old style functions) working I struggle to get the code for creating tables right - I think the problem relates in particular to the right definition of the sql statement, pls see code below. The new aspect (for me) compared to the old code is that the sql table creation command now must include the name of a database different than the master_database for which the PDO connection is set up (within the class constructor).
I looked at http://dev.mysql.com/doc/refman/5.6/en/create-table.html (I use mysql v5.6) - the part starting with "The table name can be specified as db_name.tbl_name to ..." but I cant get the sql syntax right. If I'm right the sql syntax is wrong what should be the right syntax in the code below for $sql (using the construction with various variables)?
Thnx for your help in advance.
Simplified code:
<?php
define('DB_HOST', '***');
define('DB_NAME', 'MASTER_DATABASE'); //different name
define('DB_USER', 'root');
define('DB_PASS', '*****');
//class definitions
class Database {
private $_db = null; //databasehandler
public function __construct() {
try {
$this->_db = new PDO('mysql:host='.DB_HOST.';dbname='.DB_NAME, DB_USER, DB_PASS, array(
PDO::MYSQL_ATTR_USE_BUFFERED_QUERY => true
));
$this->_db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$this->_db->query('SET CHARACTER SET utf8');
} catch (PDOException $e) {
exit('Error while connecting to database.'.$e->getMessage());
}
}
private function printErrorMessage($message) {
echo $message;
}
public function createDBTable($dbname,$dbtable,$tablestructure) {
try {
$sql = "CREATE TABLE `".$dbname."'.'".$dbtable.$tablestructure; //NOT CORRECT YET
$success = $this->_db->exec($sql);
return ($success > 0) ? true:false;
}
catch(PDOException $e){
$this->printErrorMessage($e->getMessage());
}
}
}//class
//code using class defs
$dbname = 'Mydatabase'; //just an existing database
$dbtable = 'Persons';
$tablestructure = '(FirstName CHAR(30),LastName CHAR(30),Age INT)';
$mydb = new Database();
if($mydb->createDBTable($dbname,$dbtable,$tablestructure)){
echo 'table creation success';
}
else{
echo 'table creation failure';
}
?>

You can replace you create table line as:-
$sql = "CREATE TABLE ".$dbname.".".$dbtable."".$tablestructure; //NOT CORRECT YET
Also instead of:-
$success = $this->_db->exec($sql);
Use the below lines:-
$stmt = $this->_db->prepare($sql);
$success = $stmt->execute();
Without the above 2 lines, the $succes variable will have value of 0 and although the table can be created, it would echo table creation failed.
Hope this helps.

Related

How do I make $con available as a parameter of $Query?

I can get by with editing procedural PHP (just), but OOP is a different thing. So I'm not that experienced with what I'm doing here, but I'm trying my best...
I have a file called Quote.object.php containing the following:
$Query = new DbQuery( "INSERT", "quotes", $array );
$this->id = mysqli_insert_id();
mysqli_insert_id needs to be fed a DB connection parameter, but I'm not sure how to do it. There is another file called Mysql.handler.php containing the database connection variable - is there a way that I can make $con available as a parameter of $Query above?
class DbQuery extends DbConnectionInfo{
// file: includes/classes/MysqlQuery.php
// contains functions needed to perform queries on mysql database and functions for necessary data processing for application
// SELECT = new DbQuery("select", table,cols[$value] ,where[$col=$value],order[$value],limit);
// INSERT = new DbQuery("insert", table, data[$col=$value]);
// UPDATE = new DbQuery("update", table, data[$col=$value],where[$col=$value],limit);
// set testing as true for SQL reports in page
var $results;
var $sql;
function __construct($mode,$table = '',$var1 = '',$var2 = '',$var3 = '',$var4='')
//connects to database according to info in DbConnectInfo, runs query, closes connection
{
$temp = '';
$con = mysqli_connect($this->host, $this->user, $this->pass) or die ('There was a problem connecting to the database ' . (ENVIRONMENT == 'Development' ? mysqli_error() . "$this->user, $this->pass, $this->host" : ''));
mysqli_select_db($con,$this->db) or die ('There was a problem connecting to the database' . (ENVIRONMENT == 'Development' ? mysqli_error() : ''));
I'm trying to get $con from DbQuery so I can put it into mysqli_insert_id(). I assume that's what I need? Is there a way to get $con from DbQuery and put into mysqli_insert_id()? Or do you need more information to know this?
NB I've tried to be concise in trying to show just relevant information, apologies if I've missed other helpful info.
You're defining an object, so make $con a class variable, e.g.
function __construct() {
$this->con = mysqli_connect(...);
^^^^^^^----store in object
}
function foo() {
$result = mysqli_query($sql, $this->con);
^^^^^^^^---retrieve from object
}

PHP oops variable passing error

Guys this is a code i have written. I have two files.
File one.
$regname=$_POST['name']; -----> here the variable passed is john suppose..
$sponserid=$_POST['sname'];
$regemail=$_POST['email'];
$regmobile=$_POST['mobile'];
include 'dbcon.php';
$obj = new dbcon;
$obj->createUser($regname,$sponserid,$regemail,$regmobile);
echo $obj;
in the above code i am getting variables from a form a and storing them. Then I instantiate an object and pass all those to a method.
My class code id like this.
class dbcon
{
public function __construct() //This is the connection construct.
{
$server = "localhost";
$user = "eplu";
$pass = "123456"; //Change on hosting server
$db = "epl";
mysql_connect($server, $user, $pass) or die("Error connecting to sql server: ".mysql_error());
mysql_select_db($db);
}
public function createUser($regname,$sponserid,$regemail,$regmobile){
$sql = "INSERT INTO onlinereg (names,sid,emails,mobiles) VALUES (`$regname`,`$sponserid`,`$regemail`,`$regmobile`)";
mysql_query($sql) or die(mysql_error());
return "Registration Success";
}
}
I get an error like Unknown column 'john' in 'field list'. New to OOPS pls help...Thnx in advance.....
Try now. This is not an OOPS related error, just the database thing.
class dbcon
{
public function __construct() //This is the connection construct.
{
$server = "localhost";
$user = "eplu";
$pass = "123456"; //Change on hosting server
$db = "epl";
mysql_connect($server, $user, $pass) or die("Error connecting to sql server: ".mysql_error());
mysql_select_db($db);
}
public function createUser($regname,$sponserid,$regemail,$regmobile){
$sql = "INSERT INTO onlinereg (names,sid,emails,mobiles) VALUES ('$regname','$sponserid','$regemail','$regmobile')";
mysql_query($sql) or die(mysql_error());
return "Registration Success";
}
}
Its because you are using backticks in your SQL query values. You need to use apostrophes instead of backticks, else the query will think you are referencing another column, in this case, 'john'
Change:
INSERT INTO onlinereg (names,sid,emails,mobiles) VALUES (`$regname`,`$sponserid`,`$regemail`,`$regmobile`)
to:
INSERT INTO onlinereg (names,sid,emails,mobiles) VALUES ('$regname','$sponserid','$regemail','$regmobile')
Simple change
`name`
to 'name'
You are using wrong quotes. This question is not really related to OOP

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

Call a method to connect to the DB with mysqli

Hi i am trying to move from MySQL to MySQLi in my PHP script, i had this system class with the function that connects to the database that i call whenever i need, with a simple method like this:
Sys::database_connect();
the actual code of the function is:
function database_connect(){
require 'conf.php';//configuration file with database variables (sql_)
mysql_connect($sql_serv, $sql_user, $sql_pw) OR die('ERRO!!! não ligou a base de dados');
mysql_select_db($sql_bd);
}
after calling the function i can query the database without problem.
But I cant do the same with mysqli if I put this in the sys class:
function database_connect(){
require 'conf.php';
$mysqli = new mysqli($sql_serv, $sql_user, $sql_pw, $sql_bd);
if (mysqli_connect_errno()) {
printf("Ligação à Base de dados falhou: %s\n", mysqli_connect_error());
exit();
}
}
When I call
Sys::database_connect();
it connects to the database but i can't query has i used to what i would like would be a simple method as I have done with normal MySQL, if somebody can explain what am I doing wrong or why exactly I cannot do it like that...
Thank you in advance;
Fernando Andrade.
Your later queries have to use the mysqli connection identifier, you create when connecting to the database. So save this to a property of your system class and use it later on.
function database_connect(){
require 'conf.php';
$mysqli = new mysqli($sql_serv, $sql_user, $sql_pw, $sql_bd);
if (mysqli_connect_errno()) {
printf("Ligação à Base de dados falhou: %s\n", mysqli_connect_error());
exit();
}
Sys::$dbConn = $mysqli;
}
and then later on
function query( $sql ) {
Sys::$dbConn->query( $sql );
// error handling etc.
}
I wrote an extend for the mysqli database class
class database extends mysqli {
function __construct() {
parent::__construct('host', 'user', 'password', 'database');
if(mysqli_connect_error()) {
die('Connect error ('.mysqli_connect_errno().')'.mysqli_connect_error());
}
parent::query("SET NAMES 'utf8'");
}
function query($query) {
$result = parent::query($query);
if(!$result) {
echo "<strong>MySQL error</strong>: ".$this->error."<br />QUERY: ".$query;
die();
}
if(!is_object($result)) {
$result = new mysqli_result($this);
}
return $result;
}
}
So connecting to database is $db = new database()
Executing a query is $db->query(YOUR QUERY);

PDO refuses to switch between multiple Databases!

Please I am very new to PDO, rather a novice at PHP as well. I am currently working on a project that involves connections to many databases: MySQL, MSSQL and Oracle. So I am using the class below, with PDO, for my connection. The class code is below.
class db {
private static $objInstance;
/*
* Class Constructor - Create a new database connection if one doesn't exist
* Set to private so no-one can create a new instance via ' = new DB();'
*/
private function __construct() {}
/*
* Like the constructor, we make __clone private so nobody can clone the instance
*/
private function __clone() {}
/*
* Returns DB instance or create initial connection
* #param
* #return $objInstance;
*/
public static function getDB($DBtype, $DBindex) {
include('vars.inc.php');
if (!self::$objInstance){
$DBid = $DBindex - 1;
switch ($DBtype){
case "mysql":
self::$objInstance = new PDO("mysql:host=".$dbvars[$DBid][0].";dbname=".$dbvars[$DBid][1], $dbvars[$DBid][2], $dbvars[$DBid][3]);
break;
case "mssql":
self::$objInstance = new PDO("odbc:Driver={SQL Server};Server=".$dbvars[$DBid][0].";Database=".$dbvars[$DBid][1], $dbvars[$DBid][2], $dbvars[$DBid][3]);
break;
case "oci";
self::$objInstance = new PDO("oci:dbname=//".$dbvars[$DBid][0].":".$dbvars[$DBid][4]."/".$dbvars[$DBid][1], $dbvars[$DBid][2], $dbvars[$DBid][3]);
break;
// Add other case(s) here if another RDBMS (Relational Database Management system) is used
default:
break;
}
self::$objInstance-> setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}
return self::$objInstance;
}
}
And here is the vars include file that is required by the class, I used an array cos I felt this way, new databases can be added easily to the vars file by a non-programmer over time. Of course, here, I have changed the var file values.
define('DB_SERVER', 'localhost');
define('DB_NAME', 'db1name');
define('DB_USER', 'root');
define('DB_PASSWORD', 'rootpass');
define('DB_PORT', '');
define('DB2_SERVER', 'xxx.xxx.xx.xxx');
define('DB2_NAME', 'db2name');
define('DB2_USER', 'root2');
define('DB2_PASSWORD', 'rootpass2');
define('DB2_PORT', '');
define('DB3_SERVER', 'xx.xxx.xxx.xxx');
define('DB3_NAME', db3name');
define('DB3_USER', 'root3');
define('DB3_PASSWORD', 'rootpass3');
define('DB3_PORT', '');
define('DB4_SERVER', 'xxx.xx.xxx.xx');
define('DB4_NAME', 'oracledb');
define('DB4_USER', 'root4');
define('DB4_PASSWORD', 'rootpass4');
define('DB4_PORT', '1521');
$dbvars = array( array(DB_SERVER, DB_NAME , DB_USER, DB_PASSWORD, DB_PORT),
array(DB2_SERVER, DB2_NAME , DB2_USER, DB2_PASSWORD, DB2_PORT),
array(DB3_SERVER, DB3_NAME , DB3_USER, DB3_PASSWORD, DB3_PORT),
array(DB4_SERVER, DB4_NAME , DB4_USER, DB4_PASSWORD, DB4_PORT)
);
Now the problem is that, whenever I have connected to one database and try to run my queries on another one, PDO keeps remembering the old database. But if I independently run either query, everything is fine. Can someone please help with this, or suggest a better method? :(
E.g.
include('./includes/db.class.php');
try {
$result = DB::getDB("mysql", 3)->query("SELECT myrow FROM mytable");
foreach($result as $row){
print $row['myrow'].'<br />';
}
}catch(PDOException $e){
echo $e->getMessage();
}
echo "<br />Then<br /><hr /><br />";
try {
$result = DB::getDB("mysql", 1)->query("SELECT yourrow FROM yourtable");
foreach($result as $row){
print $row['yourrow'].'<br />' ;
}
}catch(PDOException $e){
echo $e->getMessage();
}
In this case, PDO will simply keep checking DATABASE db1name for TABLE yourtable rather than check DATABASE db3name. So PDO will throw an error:
SQLSTATE[42S02]: Base table or view not found: 1146 Table 'db1name.yourtable' doesn't exist
You have it setup as a singleton. So your next call to Db::getDB returns the original instance. If you want to cache the instances for the duration of the script, change $objInstance to an array, and then instead of doing:
if (!self::$objInstance){
Do
$signature = $DBtype . $DBindex;
if (!isset(self::$objInstances[$signature])) {
Of course you'll need to change the assignment lines and the return line as well, but I think you get the idea...
It appears that your getDB function will only connect once because of this line:
if (!self::$objInstance){
So the first time you execute it, it will connect, but on all subsequent calls the logic is ignored.
I suggest adding another property to your class that stores the current DBType and changing your conditional to:
if (!self::$objInstance || $DBtype != self::$dbtype){
You would have to set $dbtype inside each case of the switch statement.

Categories