Best practices / most practical ways to implement mysqli connections - php

I'm working on streamlining a bit our db helpers and utilities and I see that each of our functions such as for example findAllUsers(){....} or findCustomerById($id) {...} have their own connection details for example :
function findAllUsers() {
$srv = 'xx.xx.xx.xx';
$usr = 'username';
$pwd = 'password';
$db = 'database';
$port = 3306;
$con = new mysqli($srv, $usr, $pwd, $db, $port);
if ($con->connect_error) {
die("Connection to DB failed: " . $con->connect_error);
} else {
sql = "SELECT * FROM customers..."
.....
.....
}
}
and so on for each helper/function. SO I thought about using a function that returns the connection object such as :
function dbConnection ($env = null) {
$srv = 'xx.xx.xx.xx';
$usr = 'username';
$pwd = 'password';
$db = 'database';
$port = 3306;
$con = new mysqli($srv, $usr, $pwd, $db, $port);
if ($con->connect_error) {
return false;
} else {
return $con;
}
}
Then I could just do
function findAllUsers() {
$con = dbConnection();
if ($con === false) {
echo "db connection error";
} else {
$sql = "SELECT ....
...
}
Is there any advantages at using a function like this compared to a Class system such as $con = new dbConnection() ?

You should open the connection only once. Once you realize that you only need to open the connection once, your function dbConnection becomes useless. You can instantiate the mysqli class at the start of your script and then pass it as an argument to all your functions/classes.
The connection is always the same three lines:
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$con = new mysqli($srv, $usr, $pwd, $db, $port);
$con->set_charset('utf8mb4');
Then simply pass it as an argument and do not perform any more checks with if statements.
function findAllUsers(\mysqli $con) {
$sql = "SELECT ....";
$stmt = $con->prepare($sql);
/* ... */
}
It looks like your code was some sort of spaghetti code. I would therefore strongly recommend to rewrite it and use OOP with PSR-4.

Related

linking my database to my server on xampp for the first time [duplicate]

I'm working on streamlining a bit our db helpers and utilities and I see that each of our functions such as for example findAllUsers(){....} or findCustomerById($id) {...} have their own connection details for example :
function findAllUsers() {
$srv = 'xx.xx.xx.xx';
$usr = 'username';
$pwd = 'password';
$db = 'database';
$port = 3306;
$con = new mysqli($srv, $usr, $pwd, $db, $port);
if ($con->connect_error) {
die("Connection to DB failed: " . $con->connect_error);
} else {
sql = "SELECT * FROM customers..."
.....
.....
}
}
and so on for each helper/function. SO I thought about using a function that returns the connection object such as :
function dbConnection ($env = null) {
$srv = 'xx.xx.xx.xx';
$usr = 'username';
$pwd = 'password';
$db = 'database';
$port = 3306;
$con = new mysqli($srv, $usr, $pwd, $db, $port);
if ($con->connect_error) {
return false;
} else {
return $con;
}
}
Then I could just do
function findAllUsers() {
$con = dbConnection();
if ($con === false) {
echo "db connection error";
} else {
$sql = "SELECT ....
...
}
Is there any advantages at using a function like this compared to a Class system such as $con = new dbConnection() ?
You should open the connection only once. Once you realize that you only need to open the connection once, your function dbConnection becomes useless. You can instantiate the mysqli class at the start of your script and then pass it as an argument to all your functions/classes.
The connection is always the same three lines:
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$con = new mysqli($srv, $usr, $pwd, $db, $port);
$con->set_charset('utf8mb4');
Then simply pass it as an argument and do not perform any more checks with if statements.
function findAllUsers(\mysqli $con) {
$sql = "SELECT ....";
$stmt = $con->prepare($sql);
/* ... */
}
It looks like your code was some sort of spaghetti code. I would therefore strongly recommend to rewrite it and use OOP with PSR-4.

How to connect to MySQL database in PHP using mysqli extension?

I have code like this to connect my server database:
<?php
$con = mysqli_connect("", "username", "password", "databasename");
if (mysqli_connect_errno()) {
echo "Failed to connect to MySQL: " . mysqli_connect_error();
}
But it displayed "Failed to connect to MySQL", what is wrong with this code? First time I am trying it in web server, whereas my localhost worked perfectly.
mysqli_connect("","username" ,"password","databasename");//Server name cannot be NULL
use loaclhost for server name(In Loacl)
<?php
$con = mysqli_connect("localhost","username" ,"password","databasename");
if (mysqli_connect_errno())
{
echo "Failed to connect to MySQL: " . mysqli_connect_error();
}
?>
Or can use MySQLi Procedural
<?php
$servername = "localhost";
$username = "username";
$password = "password";
// Create connection
$con = mysqli_connect($servername, $username, $password);
// Check connection
if (!$con) {
die("Connection failed: " . mysqli_connect_error());
}
echo "Connected successfully";
?>
EDIT 01
$servername = "localhost";
$username = "root";
$password = "";
To connect to the MySQL database using mysqli you need to execute 3 lines of code. You need to enable error reporting, create instance of mysqli class and set the correct charset.
<?php
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$mysqli = new mysqli('localhost', 'username', 'password', 'dbname', 3307);
$mysqli->set_charset('utf8mb4'); // always set the charset
The parameters in the mysqli constructor are all optional, but most of the time you would want to pass at least 4 of them. In the correct order they are:
MySQL Host. Most of the time it is localhost, but if you connect to a remote host it will be some other IP address. Make sure this does not contain the http protocol part. It should either be an IP address or the URL without protocol.
Username. This is the username of your MySQL user. To connect to the MySQL server you need to have a valid user with the right privileges.
Password.
Database name. This is the MySQL database name you want to connect to.
Port. Most of the time the default port is the correct one, but if you use for example wampserver with MariaDB, you might want to change it to 3307.
Socket name. Specifies the socket or named pipe that should be used.
Unfortunately the charset is not one of these parameters, so you must use a dedicated function to set this very important parameter.
Please beware never to display the connection errors manually. Doing so is completely unnecessary and it will leak your credentials.
On unrelated note: I do not recommend to use MySQLi in a new project. Please consider using PDO, which is overall a much better API for connecting to MySQL.
Why use mysqli? Just use PDO for safer mysql connection just use:
$hostname='localhost';
$username='root';
$password='';
$dbh = new PDO("mysql:host=$hostname;dbname=dbname",$username,$password);
You should specify hostname
$con = mysqli_connect("localhost","username" ,"password","databasename");
If it returns an error like
Failed to connect to MySQL: Can't connect to local MySQL server through socket '/var/lib/mysql/mysql.sock'
Replace localhost with 127.0.0.1.
If still you cant connect check if mysql server is actually running.
service mysqld start
Then, try the one of the following following:
(if you have not set password for mysql)
mysql -u root
if you have set password already
mysql -u root -p
$localhost = "localhost";
$root = "root";
$password = "";
$con = mysql_connect($localhost,$root,$password) or die('Could not connect to database');
mysql_select_db("db_name",$con);
<?php
$servername="";
$username="";
$password="";
$db="";
$conn=mysqli_connect($servername,$username,$password,$db);
//mysql_select_db($db);
if (!$conn) {
echo "Error: Unable to connect to MySQL." . PHP_EOL;
echo "Debugging errno: " . mysqli_connect_errno($conn) . PHP_EOL;
echo "Debugging error: " . mysqli_connect_error($conn) . PHP_EOL;
exit;
}
#session_start();
$event_name = $_POST['first_name'];
$first_name = $_POST['last_name'];
$sql = "INSERT INTO customer(first_name, last_name,) VALUES ('$first_name', '$last_name')";
$conn->query($sql);
$lastInsertId = mysqli_insert_id($conn);
?>
A better method is to keep the connection and the login parameters apart.
<?php
class Database{
protected $url;
protected $user;
protected $passw;
protected $db;
protected $connection = null;
public function __construct($url,$user,$passw,$db){
$this->url = $url;
$this->user = $user;
$this->passw = $passw;
$this->db = $db;
}
public function __destruct() {
if ($this->connection != null) {
$this->closeConnection();
}
}
protected function makeConnection(){
//Make a connection
$this->connection = new mysqli($this->url,$this->user,$this->passw,$this->db);
if ($this->connection->connect_error) {
echo "FAIL:" . $this->connection->connect_error;
}
}
protected function closeConnection() {
//Close the DB connection
if ($this->connection != null) {
$this->connection->close();
$this->connection = null;
}
}
protected function cleanParameters($p) {
//prevent SQL injection
$result = $this->connection->real_escape_string($p);
return $result;
}
public function executeQuery($q, $params = null){
$this->makeConnection();
if ($params != null) {
$queryParts = preg_split("/\?/", $q);
if (count($queryParts) != count($params) + 1) {
return false;
}
$finalQuery = $queryParts[0];
for ($i = 0; $i < count($params); $i++) {
$finalQuery = $finalQuery . $this->cleanParameters($params[$i]) . $queryParts[$i + 1];
}
$q = $finalQuery;
}
$results = $this->connection->query($q);
return $results;
}
}?>
This in combination with a database factory keeps the data separated and clean.
<?php
include_once 'database/Database.php';
class DatabaseFactory {
private static $connection;
public static function getDatabase(){
if (self::$connection == null) {
$url = "URL";
$user = "LOGIN";
$passw = "PASSW";
$db = "DB NAME";
self::$connection = new Database($url, $user, $passw, $db);
}
return self::$connection;
}
}
?>
After that you can easily make your (class based) your CRUD classes (objectname+DB)
<?php
include_once "//CLASS";
include_once "//DatabaseFactory";
class CLASSDB
{
private static function getConnection(){
return DatabaseFactory::getDatabase();
}
public static function getById($Id){
$results = self::getConnection()->executeQuery("SELECT * from DB WHERE Id = '?'", array(Id));
if ($results){
$row = $results->fetch_array();
$obj = self::convertRowToObject($row);
return $obj;
} else {
return false;
}
}
public static function getAll(){
$query = 'SELECT * from DB';
$results = self::getConnection()->executeQuery($query);
$resultsArray = array();
for ($i = 0; $i < $results->num_rows; $i++){
$row = $results->fetch_array();
$obj = self::convertRowToObject($row);
$resultsArray[$i] = $obj;
}
return $resultsArray;
}
public static function getName($Id){
$results = self::getConnection()->executeQuery("SELECT column from DB WHERE Id = '?'", array($Id));
$row = $results->fetch_array();
return $row['column'];
}
public static function convertRowToObject($row){
return new CLASSNAME(
$row['prop'],
$row['prop'],
$row['prop'],
$row['prop']
);
}
public static function insert ($obj){
self::getConnection()->executeQuery("INSERT INTO DB VALUES (null, '?', '?', '?')",
array($obj->prop, $obj->prop, $obj->prop));
}
public static function update ($propToUpdate, $Id){
self::getConnection()->executeQuery("UPDATE User SET COLTOUPDATE = ? WHERE Id = ?",
array($propToUpdate, $Id));
}
}
And with this fine coding it's a piece of cake to select items in frontend:
include 'CLASSDB';
<php
$results = CLASSDB::getFunction();
foreach ($results as $class) {
?>
<li><?php echo $class->prop ?><li>
<php } ?>
The easiest way to connect to MySQL server using php.
$conn=new mysqli("localhost", "Username", "Password", "DbName");
if($conn->connect_error)
{
die("connection faild:".$conn->connect_error);
}
echo "Connection Successfully..!";
localhost like this (MySQLi Procedural)
<?php
$servername ="localhost";
$username="username";//username like (root)
$password="password";//your database no password. (" ")
$database="database";
$con=mysqli_connect($servername,$username,$password,$database);
if (!$con) {
die("Connection failed: " . MySQL_connect_error());
}
else{
echo "Connected successfully";
}

Prepared statement database connection must be instansiated first?

The parts in bold are what I am questioning. Inside the search_for_new_user function, if I change $conn->prepare to $this->db_connection()->prepare. I receive a lost connection error. However in the function right above it db_conn_test I can use this syntax. In both cases I am returning the $connection so I don't understand why there must be a difference in syntax.
class Database {
function db_connection() {
$server = "localhost";
$user = "user";
$password = "password";
$database = "database";
return $connection = new mysqli($server, $user, $password, $database);
}
function db_conn_test() {
if (**$this->db_connection()->connect_errno**) {
die($this->db_connection()->connect_errno . ": " . $this->db_connection()->connect_error);
} else {
echo "connected to mysql database";
}
}
function search_for_new_user($email) {
**$conn = $this->db_connection();**
if ($stmt = **$conn->prepare**("SELECT email FROM users where email = ?")) {
$stmt->bind_param("s", $email);
$stmt->execute();
$stmt->bind_result($result);
$stmt->fetch();
echo $result;
$stmt->close();
$conn->close();
}
}
}
In db_conn_test you call db_connection twice only if you got connection error during first db_connection call, so in this case connection to DB is not created.
But in search_for_new_user you create connection twice.
I.e.:
in db_conn_test:
// if connection not created, because you got error
if ($this->db_connection()->connect_errno) {
// therefore each time you call db_connection(),
// you again try create connection, and got same error
// and return it in die text
die($this->db_connection()->connect_errno . ": " . $this->db_connection()->connect_error);
} else {
echo "connected to mysql database";
}
but in search_for_new_user: you call db_connection() and create connection(if all is ok). And then if you call db_connection in second try, first connection is gone away and you got error.
Your class should looks like this:
class Database {
protected $connection;
function db_connection() {
if ($this->connection !== null) {
return $this->connection;
}
$server = "localhost";
$user = "user";
$password = "password";
$database = "database";
return $this->connection = new mysqli($server, $user, $password, $database);
}
}

PHP MySQL connection error

guys!I got a littile trouble.
There is connection.inc.php in "includes" folder:
<?php
function dbConnect($usertype, $connectionType = 'mysqli') {
$host = 'localhost';
$db = 'testdb';
if ($usertype == 'read') {
$user = 'readuser';
$pwd = 'testpass';
} elseif ($usertype == 'write') {
$user = 'writeuser';
$pwd = 'testpass';
} else {
exit('Unrecognized connection type');
}
if ($connectionType == 'mysqli') {
return new mysqli($host, $user, $pwd, $db) or die('Cannot open database');
} else {
try {
return new PDO("mysql:host=$host;dbname=$db", $user, $pwd);
} catch(PDOException $e) {
echo 'Cannot connect to database';
exit;
} // end of try block
} // end of $connectionType if
} // end of function
I use Linux for this test,and the lastest xampp 1.7.4
But things become worse when I use the following code:(I already have created my DB, and two users 'readuser' and 'writeuser')
<?php
// I use mysqli extension to connect my DB
require_once(includes/connection.inc.php);
// connect to DB
$conn = dbConnect('read');
// I need to get some picture infomations from images table
$sql = 'SELECT * FROM images';
$result = $conn->query($sql) or die(mysqli_error());
// find out how many records were retrieved
$numRows = $result->num_rows;
echo "We have $numRows pictures in DB";
?>
And when I load it in my browser:
Fatal error:Call to a member function query() on a non-object in /opt/lampp/htdocs/mysqli.php on line 9
So I guess $conn is not a object now,but It works when I write this code:
<?php
$host = 'localhost';
$user = 'readuser';
$pass = 'testpass';
$db = 'testdb';
$sql = 'SELECT * FROM images';
$conn = new mysqli($host, $user, $pass, $db);
$result = $conn->query($sql) or die(mysqli_error());
$numRows = $result->num_rows;
echo "We have $numRows pictures in DB";
?>
And it outputs:We have 8 pictures in DB
That's really a strange thing,I can't figure it out...Thanks guys!
Try saving the new mysqli() result as a variable, then return that variable instead. That logic makes no sense, I know, but I've had problems like that before.
$a = new mysqli($host, $user, $pwd, $db) or die ('Cannot open database');
return $a;

"Undefined Variable" notice

Im new to php so im sure this is an easy one. Im getting this error
Notice: Undefined variable: conn in C:\Dev\Webserver\Apache2.2\htdocs\EclipsePHP\thecock\php\db.php on line 23
for this code
<?php
$host = "localhost"; $database = "dbname"; $username = "user"; $password = "pass";
$conn = new mysqli($host, $username, $password, $database);
if (! $conn) {
printf("Connect failed: %s\n", mysqli_connect_error());
exit();
}else{
echo("all ok!");
}
function getContent($id) {
$sql = "SELECT content FROM blocktext WHERE id=$id";
if ($rs = $conn->query($sql)) { # line 23
if ($row = $rs->fetch_assoc()) {
echo stripslashes($row['content']);
}
$rs->close();
}
}
?>
How do I fix the notice?
Change your function to:
function getContent($id, $conn) {
$sql = "SELECT content FROM blocktext WHERE id=$id";
if ($rs = $conn->query($sql)) {
if ($row = $rs->fetch_assoc()) {
echo stripslashes($row['content']);
}
$rs->close();
}
}
You don't declare the "original" $conn in the scope of the function. Inside the function you only have access to variables declared inside the function or provided via parameters.
Another way would be to declare the variable as global in your function:
function getContent($id) {
global $conn;
$sql = "SELECT content FROM blocktext WHERE id=$id";
if ($rs = $conn->query($sql)) {
if ($row = $rs->fetch_assoc()) {
echo stripslashes($row['content']);
}
$rs->close();
}
}
But you should only do this, if there is no other way. Globals make it hard to debug and maintain the code.
See also Variable scope and why global variables are bad.
Edit:
Yes e.g. you can have a DB class:
class DB {
private static $conn = null;
public static function getConnection() {
if (is_null(DB::$conn)) {
$host = "localhost"; $database = "dbname"; $username = "user"; $password = "pass";
DB::$conn = new mysqli($host, $username, $password, $database);
}
return DB::$conn;
}
}
Of course this is not the best implementation ;) But it should give you the right idea. Then you can get the the connection:
DB::getConnection()
conn is a global variable. To access it within a function:
function getContent($id) {
global $conn;
...
}
Otherwise the function can't see it.

Categories