reducing repetitive code in PHP - php

I'm using this same block of code in numerous PHP files and sometimes in the same PHP file (e.g., when there's an if/else. I know there's a better way, but I'm not quite sure how to do it. I want to replace this big block with something, but not sure what fits. require maybe?
$hostname = 'localhost';
$database = 'dev_testing';
$username = 'root';
$password = 'XXXXXX';
$dbh = new PDO("mysql:host=$hostname;dbname=$database", $username, $password);
$dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

The answers by #maalls and #TahaPaksu are good, but #marcB's comment is even better: usually you'd want to connect to the database only once per script execution. I don't want to kick you right in the direction of dependency injection, but as an intermediate solution, I'd like to suggest this class, which looks roughly like a singleton, but is actually the Memoization pattern implementation (see also PHP Design Patterns for other pattern examples).
Anyway: the code:
class Database() {
static private $connection = null;
public static function getConnection() {
if (static::$connection === null) {
$hostname = 'localhost';
$database = 'dev_testing';
$username = 'root';
$password = 'XXXXXX';
$dbh = new PDO("mysql:host=$hostname;dbname=$database", $username, $password);
$dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
static::$connection = $dbh;
}
return static::$connection;
}
}
In your script you can call it using
$dbh = Database::getConnection();
You can call that line as often as you like but it will only connect to the database the first time it's called for that script. Subsequent calls will just return the same connection. This will save quite some overhead on your database.

Create a separate file (for ex. "connection.php"), put the code in it, and everywhere you need it, include the following at the begining of your code:
require_once('connection.php');

you can use a global function which you include in top of your php files:
require_once("db.php");
file db.php:
function db_connect(){
$hostname = 'localhost';
$database = 'dev_testing';
$username = 'root';
$password = 'XXXXXX';
$dbh = new PDO("mysql:host=$hostname;dbname=$database", $username, $password);
$dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
return $dbh;
}
and in your files:
$dbh = db_connect();
...
// don't forget to close db before you open a new connection!
$dbh = null;

Related

Keeping MYSQL connection open

Is it possible to keep MySQL connection open from the beginning of a php file and close it at the end of that particular script?
If yes please help me because I'm having problem with this:
Prevent clash in MYSQL database
Thank you all.
This is how I open and close connection with my database:
$host = "localhost";
$root = "myusername";
$pass = "mypassword";
$DBname = "mydatabase";
$link = mysqli_connect($host, $root, $pass, $DBname);
function close_connection($link) {
$link ->close();
}
I call the function close_connection() whenever I want to stop the connection with my database. Hope this helps!
-Ed

NetBeans 8.2 PHP Code Completion Issue

So i've been having an issue with NetBeans code completion. I'm currently trying to set up a database connection that i can use in my other files. Inside of my connection.php file, I have access to all of the usual database methods. My end goal is to use prepared statements for my queries.
However, when i am inside my register.php file, with connection.php required at the top, suddenly code completion doesn't work anymore. I get the generic popup. This is the file i would like to actually use those prepared statements in. I would also like to avoid having to open a new connection in every file.
So my question to you is, is it me or is it NetBeans?
connection.php
$host = "localhost";
$username = "root";
$pass = "password";
$database = "LoganWebsiteUserLogin";
try {
$conn = new PDO('mysql:host=localhost;dbname=' . $database . ';charset=utf8mb4', $username, $pass);
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
echo "Connected Successfully!";
} catch (PDOException $e) {
echo "Connection failed! " . $e->getMessage();
}
register.php
<?php
require 'connection.php';
// Create session variables
$_SESSION['firstName'] = $_POST['firstName'];
$_SESSION['lastName'] = $_POST['lastName'];
$_SESSION['email'] = $_POST['email'];
// trying to access $conn from connection.php here, however autocomplete for
// it is not working. NetBeans doesn't know that $conn is a PDO
$conn->
It works in PhpStorm but not in Netbeans. But anyway, global variables are not recommended and lead to unwanted side effects. Maybe try a different approach.
Example:
connection.php
<?php
function db(): PDO
{
static $pdo = null;
if (!$pdo) {
$host = "localhost";
$username = "root";
$password = "password";
$database = "LoganWebsiteUserLogin";
$options = [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_PERSISTENT => false,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8mb4 COLLATE utf8mb4_unicode_ci",
];
$pdo = new PDO("mysql:host=$host;dbname=$database;charset=utf8mb4", $username, $password, $options);
}
return $pdo;
}
register.php
<?php
require_once __DIR__ . '/connection.php';
// Create session variables
$_SESSION['firstName'] = $_POST['firstName'];
$_SESSION['lastName'] = $_POST['lastName'];
$_SESSION['email'] = $_POST['email'];
// Works :-)
db()->

How to fix server error 500 when executing PHP script?

I am trying to insert into a database through PHP. However, when I connect to the PHP file I get server 500 error. Would anyone be able to spot what I am doing wrong?
<?php
include 'db-security.php';
function db_login()
{
$userName = filter_input(INPUT_POST, "userName");
$password = filter_input(INPUT_POST, "password");
//binding the variable to sql.
$statement = $link->prepare("INSERT INTO user(username, password)
VALUES($userName, $password)");
//execute the sql statement.
$statement->execute();
}
db_login();
?>
Updated:
I have discovered the error occurs when i add filer_input or $_post to the php.
<?php
include 'db-security.php';
function db_login() {
global $conn;
// use my eaxmple to filter input to get the data out of the form, because security.
//$userName = filter_input(INPUT_POST, "userName");
$userName = $_POST['userName'];
$password = $_POST['password'];
//$password = filter_input(INPUT_POST, "password");
//binding the variable to sql.
$stmt = $conn->prepare("INSERT INTO user(username, password)VALUES(:usrname, :pswd)");
$stmt->bindParam(':pswd', $password);
$stmt->bindParam(':usrname', $userName);
$stmt->execute();
//execute the sql statement.
}
db_login();
?>
db-security.php
<?php
include_once 'conf.php';
function db_connect() {
// Define connection as a static variable, to avoid connecting more than once
static $conn;
// Try and connect to the database, if a connection has not been established yet
if(!isset($conn)) {
// Load configuration as an array. Use the actual location of your configuration file
try
{
$conn = new PDO("mysql:host=localhost;port=3307;dbname=database", DB_USERNAME,DB_PASSWORD);
// stores the outcome of the connection into a class variable
$db_msg = 'Connected to database';
}
catch(PDOException $e)
{
$conn = -1;
$db_msg = $e->getMessage();
}
//$conn = new PDO(DB_HOST,DB_USERNAME,DB_PASSWORD , MAIN_DB);
}
}
db_connect();
?>
Where is $link defined? In 'db-security.php'? If yes then you have a variable scope problem. Just pass $link in the function call. This would have to be done for all functions.
define function as = function db_login($link)
call function like = db_login($link);
EDIT:
Don't use a function for 'db-security.php' it should be like this:
<?php
$conn = new PDO('mysql:host=localhost;dbname=testdb;charset=utf8', 'username', 'password');
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$conn->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
?>
This is not complete code, just a sample. Now $conn is in the global variable scope and using global in the functions will work. Or just pass $conn to the function and not use global at all.
EDIT2:
Below are the working sample scripts. You need to change some information to match your setup. I'm not sure why the function is called db_login() since the function actually adds the user/password into the 'user' table.
conf.php
<?php
define('DB_USERNAME', 'test');
define('DB_PASSWORD', '123456');
?>
db-security.php
<?php
include_once 'conf.php';
try
{
$conn = new pdo("mysql:host=localhost; dbname=test; charset=utf8", DB_USERNAME, DB_PASSWORD);
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);
$conn->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
}
catch(PDOException $e)
{
die('Unable to connect to database!');
}
?>
main script
<?php
include 'db-security.php';
function db_login()
{
global $conn;
$userName = $_POST['userName'];
$password = $_POST['password'];
$stmt = $conn->prepare("INSERT INTO user(username, password) VALUES(:usrname, :pswd)");
$stmt->bindParam(':usrname', $userName);
$stmt->bindParam(':pswd', $password);
$stmt->execute();
}
db_login();
?>
So you need to bind your parameters after prepare statement
$stmt = $link->prepare("INSERT INTO user(username, password)VALUES(:usrname, :pswd)");
$stmt->bindParam(':pswd', $password);
$stmt->bindParam(':usrname', $userName);
$stmt->execute();
I have been looking at your code and I would advice you to try a different approach. I've been wrapping my head around this subject for a while when learning PHP. Best advice i've had is that you can best try when fetching information from the DB is using a try/catch statement everytime. Sounds annoying or problematic but it easy to overlook and well written maintained code because you know every try catch block will execute or catch the error atleast.
With PDO being one of the best solutions because it can connect with multiple databases the best way to execute getting information from the Database is this:*
I am gonna give you my example of something i wrote. I don't want to write it all out in your situation because i feel that's something you can better do to learn what went wrong and i hope this gives you a step in the right direction.
database.php
$serverName = "";
$dbName = "";
$userName = "";
$password = "";
try {
$db = new PDO("mysql:host=$serverName;dbname=$dbName", $userName, $password);
// Set the PDO error mode to exception
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$db->exec("SET NAMES 'utf8'");
}
catch(PDOException $e){
echo"Connection failed: " . $e->getMessage();
exit;
}
?>
index.php Executing a simple commmand get firstName from employers
<?php
require_once 'database.php';
try
{
$sQuery = "
SELECT
firstName
FROM
employees
";
$oStmt = $db->prepare($sQuery);
$oStmt->execute();
while($aRow = $oStmt->fetch(PDO::FETCH_ASSOC))
{
echo $aRow['firstName'].'<br />';
}
}
catch(PDOException $e)
{
$sMsg = '<p>
Regelnummer: '.$e->getLine().'<br />
Bestand: '.$e->getFile().'<br />
Foutmelding: '.$e->getMessage().'
</p>';
trigger_error($sMsg);
}
?>
Good luck and i hope my index.php is helpful in showing you how I find is the best way momentarily to talk to the database.

Variables Undefined when in Function

I am working on a project, and I am getting undefined errors for $host, $dbname, $user, and $pass.
But the errors only occur when those are inside of the dbConnect() function.
Here's the code (upload.php):
<?php
error_reporting(E_ALL);
require('config.php');
$filename = htmlentities($_FILES['file']['name']);
$tmpname = $_FILES['file']['tmp_name'];
$filesize = $_FILES['file']['size'];
$filetype = $_FILES['file']['type'];
function dbConnect() {
try {
global $dbcon;
$dbcon = new PDO("mysql:host=$host;dbname=$dbname", $user, $pass);
}
catch (PDOException $e) {
echo $e->getMessage();
}
}
if (dbConnect()) {
print('worked');
}
config.php:
<?php
global $host, $user, $pass, $dbname;
$host = "localhost"; // MySQL Hostname
$user = "root"; // MySQL User
$pass = "mypass"; // MySQL Password
$dbname = "files";
You need to pass the variables into the function as parameters. Variables declared outside a function are not available inside that function:
function dbConnect($user, $pass, $host, $dbname) {
try {
global $dbcon;
$dbcon = new PDO("mysql:host=$host;dbname=$dbname", $user, $pass);
}
# ...
Read more about Variable Scope in PHP.
I would suggest that you use an array to store your connection string info.
First, create a function in your config.php page that returns the necessary DB connection string info. To use, you would simply declare a variable within upload.php of $dbconfig that stores the values returned from the loadDBConfig() function in your config.php file. You will then execute the dbConnect() function by declaring your $dbcon variable and setting the value to dbConnect(). This will return the result of your function to the variable, which you can then check for the desired result.
This solution removes the need for global variables and improves the organization.
Note: Your entire DB interaction should technically be moved to a class for improved portability.
upload.php:
...
function dbConnect() {
$dbconfig = loadDBConfig();
try {
$dburl = "mysql:host=" . $dbconfig['host'] . ";dbname=" . $dbconfig['dbname'];
return new PDO($dburl, $dbconfig['user'], $dbconfig['pass']);
} catch (PDOException $e) {
echo $e->getMessage();
}
}
$dbcon = dbConnect();
...
config.php:
<?php
function loadDBConfig(){
$host = "localhost"; // MySQL Hostname
$user = "root"; // MySQL User
$pass = "mypass"; // MySQL Password
$dbname = "files";
return array('host' => $host, 'user' => $user, 'pass' => $pass, 'dbname' => $dbname);
}
?>
You need to declare those vars GLOBAL inside dbConnect too.
function dbConnect() {
try {
global $dbcon;
global $host, $user, $pass, $dbname;
$dbcon = new PDO("mysql:host=$host;dbname=$dbname", $user, $pass);
}
catch (PDOException $e) {
echo $e->getMessage();
}
}
EDIT
Yes, globals aren't a really good idea - they hinder code reuse and "pollute" the namespace, you never known which variables are there and which aren't, and risk changing a variable which was used somewhere else.
A better way to approach the problem would be to pass the required information as "parameters". The same applies to the return value, which could be a resource (if everything went well) or a string representing an error message.
function dbConnect($host, $dbname, $user = 'nobody', $pass = '') {
try {
return new PDO("mysql:host=$host;dbname=$dbname", $user, $pass);
}
catch (PDOException $e) {
return $e->getMessage();
}
}
You would call such a function passing the parameters and checking its output, which if everything went well, is expected to be an object:
if (!is_object($conn = dbConnect($host, $dbname, $user, $pass) {
die("There was an error: $conn");
}
Another advantage of parameters is that you can have default values for parameters (e.g., if you wrote dbConnect($host, $dbname), the function would "understand" and use 'nobody' and an empty password for the remaining parameters).

php Call to a member function prepare() on a non-object problem

<?php
$dbtype = 'mysql';
$mysql_host = "localhost";
$mysql_database = "mydb";
$mysql_user = "root";
$mysql_password = "";
try {
$db = new PDO ( $dbtype . ':host=' . $mysql_host . ';dbname=' . $mysql_database, $mysql_user, $mysql_password, array (PDO::ATTR_PERSISTENT => true ) );
return $db;
} catch ( PDOException $e ) {
return false;
}
?>
Above are my db.php
<?php
require db.php";
...
global $db;
$stmt = $db->prepare ( "INSERT INTO quote (title, contactname) VALUES (:a, :b);" );
I actually able to run it properly under my IDE (ZendStudo wamp server) but once i upload to host server i got this error. Anybody facing the same problem before can guide me how to fix?
There can me many reasons, but one obivious is that is you had a PDOException, then $db == false, which would explain the error message.
Try to check if $db is correctly set as a PDO or false.
PDO does not throw exceptions unless you explicitly instruct it to do so:
$db = new PDO(...);
$db ->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

Categories