My script requires connections to several databases. Some parts only need to connect to one, which is all fine and dandy, however in some cases I need to perform queries on different database in a single script execution.
Currently I'm doing something like this:
function db_connect($which) {
if($which == "main") {
$maindb = mysqli_connect(HOSTNAME_1, USER, PASSWORD, MAIN_DB);
return $maindb;
} elseif($which == "stats") {
$statsdb = mysqli_connect(HOSTNAME_2, USER, PASSWORD, STATS_DB);
return $statsdb;
}
}
$maindb = db_connect("main");
$statsdb = db_connect("stats");
I maintain the actual hostname, username, password and db name in a config file full of constants.
I then use the respective links on different queries.
Is there a cleaner way to do this?
Quite good, although you shoul try not to duplicate your code :
function db_connect($which) {
if($which == "main") {
$host = HOSTNAME_1;
$db = MAIN_DB;
} elseif($which == "stats") {
$host = HOSTNAME_2;
$db = STATS_DB;
} else {
throw new Exception('unknown db');
}
return mysqli_connect($host, USER, PASSWORD, $db);
}
$maindb = db_connect("main");
$statsdb = db_connect("stats");
That seems to be ok. An alternative would be to use the class mysqli instead of the functions in order to manipulate objects instead of identifiers.
You could store your databaseconfigs in arrays and use that. That's how codeigniter does it.
function get_database_config(){
$config['main']['hostname'] = "host1";
$config['main']['user'] = "user1";
$config['main']['password'] = "pass1";
$config['main']['database'] = "database1";
$config['stats']['hostname'] = "host2";
$config['stats']['user'] = "user2";
$config['stats']['password'] = "pass2";
$config['stats']['database'] = "database2";
return $config;
}
function db_connect($db)
{
$config = get_database_config();
return mysqli_connect(
$config[$db]['hostname'],
$config[$db]['user'],
$config[$db]['password'],
$config[$db]['database']
);
}
If you don't want to work with an associative array and prefer to work with constants, you could name your constants as MAIN_HOSTNAME, STATS_HOSTNAME, ... and use constant($which . '_HOSTNAME') as input for mysqli_connect().
Related
I’m trying to write a PHP script with MySQLi to query a database.
I’d like it if the user-input could be checked against the database and then return a result from the column ‘conjugation’ if the string in the column ‘root’ of the table ‘normal_verbs’ is in the input.
So if the user input is something like "foobar", and the root-column has "foo", I'd like it to see 'foo' in 'foobar' and return that value of 'conjugation' in that row.
I can’t seem to get the query to work like I want it to. The one I'm using below is basically just a placeholder. I don't entirely understand why it doesn't work.
What I’m trying, is this :
function db_connect() {
static $connection;
if(!isset($connection)) {
$connection = mysqli_connect('localhost','user','password','Verb_Bank');
}
if($connection === false) {
return mysqli_connect_error();
}
return $connection;
}
function db_query($query) {
$connection = db_connect();
$result = mysqli_query($connection,$query);
return $result;
}
function db_quote($value) {
$connection = db_connect();
return "'" . mysqli_real_escape_string($connection,$value) . "'";
}
$m= db_query("SELECT `conjugation` from normal_verbs where `root` in (" . $y . ")");
if($m === false) {
// Handle failure - log the error, notify administrator, etc.
} else {
// Fetch all the rows in an array
$rows = array();
while ($row = mysqli_fetch_assoc($m)) {
$rows[] = $row;
}
}
print_r ($rows);
It’s not giving me any errors, so I think it’s connecting to the database.
EDIT2: I was wrong. I was missing something obvious due to misunderstanding MySQLi and have edited the code accordingly. So the above code does work in that it connects to the database and returns a result, but I'm still stumped on a viable SQL statement to do what I want it to do.
Please try this:
SELECT 'conjugation' FROM 'normal_verbs' WHERE " . $y . " LIKE CONCAT('%',root,'%')
It selects all rows where root contains $y anywhere.
In addition, your code is vulnerable to SQL injections. Please look here for more information.
Try this SQL Query Like this
SELECT `conjugation` from normal_verbs where `root` like '%$y%'
I am very new to php programming. I have written a sign up html file where the user enters his email and password. If the user has already registered, I am redirecting to sign-in screen and if the user is new use, I am persisting in the database. Now if the user enters wrong password, he will again be redirected to sign-in screen but this time I want to show a message on the screen, that the password entered is incorrect. The sign in screen should not display the message when the user navigates directly to the sign in screen.
The code snippet is shown below:
<?php
define('DB_HOST', 'hostname');
define('DB_NAME', 'db_name');
define('DB_USER','username');
define('DB_PASSWORD','password');
$con=mysql_connect(DB_HOST,DB_USER,DB_PASSWORD) or die("Failed to connect to MySQL: " . mysql_error());
$db=mysql_select_db(DB_NAME,$con) or die("Failed to connect to MySQL: " . mysql_error());
function NewUser() {
$email = $_POST['email'];
$password = $_POST['password'];
$query = "INSERT INTO WebsiteUsers (email,pass) VALUES ('$email','$password')";
$data = mysql_query ($query)or die(mysql_error());
if($data) {
header('Location: reg-success.html');
}
}
function SignUp() {
if(!empty($_POST['email'])){
$emailQuery = mysql_query("SELECT * FROM WebsiteUsers WHERE email = '$_POST[email]'");
if($row = mysql_fetch_array($emailQuery)) {
$query = mysql_query("SELECT * FROM WebsiteUsers WHERE email = '$_POST[email]' AND pass = '$_POST[password]'");
if($row = mysql_fetch_array($query)) {
echo 'validated user. screen that is accessible to a registered user';
}else{
echo 'Redirect to the sign in screen with error message';
}
}else{
NewUser();
}
}
}
if(isset($_POST['submit']))
{
SignUp();
}
?>
Please let me know how to get this implementation using php
Here are a couple of classes that may help you prevent injection hacks plus get you going on how to do what you are trying to do in general. If you create classes for your tasks, it will be easier to re-use what your code elsewhere. I personally like the PDO method to connect and grab info from a DB (you will want to look up "binding" to help further prevent injection attacks), but this will help get the basics down. This is all very rough and you would want to expand out to create some error reporting and more usable features.
<?php
error_reporting(E_ALL);
// Create a simple DB engine
class DBEngine
{
protected $con;
// Create a default database element
public function __construct($host = '',$db = '',$user = '',$pass = '')
{
try {
$this->con = new PDO("mysql:host=$host;dbname=$db",$user,$pass, array(PDO::ATTR_ERRMODE => PDO::ERRMODE_WARNING));
}
catch (Exception $e) {
return 0;
}
}
// Simple fetch and return method
public function Fetch($_sql)
{
$query = $this->con->prepare($_sql);
$query->execute();
if($query->rowCount() > 0) {
$rows = $query->fetchAll();
}
return (isset($rows) && $rows !== 0 && !empty($rows))? $rows: 0;
}
// Simple write to db method
public function Write($_sql)
{
$query = $this->con->prepare($_sql);
$query->execute();
}
}
// Your user controller class
class UserControl
{
public $_error;
protected $db;
// Save the database connection object for use in this class
public function __construct($db)
{
$this->_error = array();
$this->db = $db;
}
// Add user to DB
protected function Add()
{
$email = htmlentities($_POST['email'],ENT_QUOTES);
// Provided you have a php version that supports better encryption methods, use that
// but you should do at least a very basic password encryption.
$password = hash('sha512',$_POST['password']);
// Use our handy DBEngine writer method to write your sql
$this->db->Write("INSERT INTO WebsiteUsers (`email`,`pass`) VALUES ('$email','$password')");
}
// Fetch user from DB
protected function Fetch($_email = '')
{
$_email = htmlentities($_email,ENT_QUOTES);
$password = hash('sha512',$_POST['password']);
// Use our handy DBEngine fetcher method to check your db
$_user = $this->db->Fetch("SELECT * FROM WebsiteUsers WHERE email = '$_email' and password = '$password'");
// Return true if not 0
return ($_user !== 0)? 1:0;
}
// Simple fetch user or set user method
public function execute()
{
// Check that email is a valid format
if(filter_var($_POST['email'], FILTER_VALIDATE_EMAIL)) {
// Save the true/false to error reporting
$this->_error['user']['in_db'] = $this->Fetch($_POST['email']);
// Asign short variable
$_check = $this->_error['user']['in_db'];
if($_check !== 1) {
// Add user if not in system
$this->Add();
// You'll want to expand your add feature to include error reporting
// This is just returning that it made it to this point
$this->_error['user']['add_db'] = 1;
}
else {
// Run some sort of login script
}
// Good email address
$this->_error['email']['validate'] = 1;
}
else
// Bad email address
$this->_error['email']['validate'] = 0;
}
}
// $_POST['submit'] = true;
// $_POST['email'] = 'jenkybad<script>email';
// $_POST['password'] = 'mypassword';
if(isset($_POST['submit'])) {
// Set up a db connection
$db = new DBEngine('hostname','dbname','dbuser','dbpass');
// Create instance of your user control
$_user = new UserControl($db);
// Execute instance
$_user->execute();
// Check for basic erroring
print_r($_user->_error);
} ?>
We are trying to complete / fix the below code, We cant seem to do the following.
Check if 'Check_Activation' is set to 'NULL' within the Database
IF value is NULL direct the user to one of the forms (1,2,3)
And finally if the 'Check_Activation' has already been activated and isn't 'NULL' prevent user from accessing one of the 3 forms.
I know its basicly there but we can't seem to figure out the final bug.
Please have a quick look at the code below and if anyone notices anything that isn't right please advice us.
Paste Bucket / Version
Website URL
<?php
$username = $_POST['username'];
$activation_code = $_POST['activation_code'];
$activation_codeurl = $activation_code;
$usernameurl = $username;
$db_host = "localhost";
$db_name = "aardvark";
$db_use = "aardvark";
$db_pass = "aardvark";
$con = mysql_connect("localhost", $db_use, $db_pass);
if (!$con){
die('Could not connect: ' . mysql_error());
}
mysql_select_db($db_name, $con);
$checkcustomer = mysql_query("SELECT `Check_Activation` FROM `members` WHERE `Username` = '".$username."' & `Activation` = '".$activation_code."'; ");
$array = mysql_fetch_array($checkcustomer);
if (is_null($array['Check_Activation'])) {
$username = substr($username, 0, 1);
if($username == '1') {
$redirect_url='form-one.php?membernumber='.$usernameurl.'&activation_code='.$activation_codeurl;
} elseif($username == '2') {
$redirect_url='form-two.php?membernumber='.$usernameurl.'&activation_code='.$activation_codeurl;
} elseif($username == '3') {
$redirect_url='form-three.php?membernumber='.$usernameurl.'&activation_code='.$activation_codeurl;
}
header("Location:". $redirect_url);
}
else
{
?>
Try this, You need to fetch the row from table and then you can check the values,
$val = mysql_fetch_array($checkcustomer);
if (is_null($val['Check_Activation']))
instead of
$val = mysql_query($checkcustomer);
if ($val == 'NULL')
NOTE: Use mysqli_* functions or PDO instead of using mysql_* functions(deprecated)
before I get into the technicality of what your are trying to accomplish, I have some advice for your code in general. You should avoid using the mysql api as it is deprecated, and use the mysqli api instead. I think you will also find that it is easier to use.
Now for the code:
You have this line in your code which seems to be incorrect, $checkcustomer is a result set from your previous query, so why are you running it as a query again?
$val = mysql_query($checkcustomer);
You already have the result set so do this:
$array = mysql_fetch_array($checkcustomer);
And then take the value of Check_Aviation;
if (is_null($array['Check_Aviation'])) {
//Do Something
}
Should solve your issue
This question already has answers here:
Executing mysqli_query inside a function
(2 answers)
Closed 7 years ago.
I'm having some problems performing a mysql query inside a php function. The error I am getting is
Notice: Undefined variable: link in C:\path\api\inc\restFunctions.php on line 16
There are several files calling each other so I will attempt to outline the necessary information.
URL Accessed:
localhost/serverList/api/rest.php?action=allServers
serverList/api/rest.php
<?php
include 'inc/restFunctions.php';
$possibleCalls = array('allServers','allEnvs','allTypes','false');
if(isset($_GET['action'])){
$action = $_GET['action'];
}
else{
$action = 'false';
}
if(in_array($action,$possibleCalls)){
switch ($action){
case 'allServers':
$return = allServers();
break;
case 'allEnvs':
$return = allEnvs();
break;
case 'allTypes':
$return = allTypes();
break;
case 'false':
$return = falseReturn();
break;
}
}
serverList/api/inc/restFunctions.php
<?php
include ('inc/config.php');
function allServers(){
$serverInfoQuery = "SELECT * FROM servers"
$allServerResults = $link->query($serverInfoQuery);
$json = array();
while($row = $allServerResults->fetch_assoc()){
$json[]['serverID'] = $row['serverID'];
$json[]['environment'] = $row['environment'];
$json[]['type'] = $row['type'];
$json[]['serverIP'] = $row['serverIP'];
$json[]['serverDescription'] = $row['serverDescription'];
$json[]['serverCreatedBy'] = $row['serverCreatedBy'];
$json[]['serverCreatedDtTm'] = $row['serverCreatedDtTm'];
$json[]['serverUpdatedBy'] = $row['serverUpdatedBy'];
$json[]['serverUpdatedDtTm'] = $row['serverUpdatedDtTm'];
}
$jsonResults = json_encode($json);
return $jsonResults;
}
?>
serverList/api/inc/config.php
<?php
$host = 'localhost';
$user = 'userName';
$password = 'password';
$database = 'database';
$link = new mysqli($host, $user, $password, $database);
if (mysqli_connect_errno()) {
exit('Connect failed: '. mysqli_connect_error());
}
?>
I have verified that the query being called works. I also verified that the connection info (masked above) works by using a different page of this software that queries the db.
I'm assuming I must have missed a quote or paren somewhere, but I'm baffled as to where it might be.
The problem is with PHP variable scoping. Add this line inside of allServers() function before you refer to the $link variable for the first time:
global $link;
See more here:
http://php.net/manual/en/language.variables.scope.php
In my opinion using global variables is not a good solution. You might override $link ($link is rather usual name for a variable you may be using for another purposes) variable in some scope by accident, resulting in lot's of confusion and difficult debugging.
Just pass it as a function parameter - much cleaner and easier to read:
function AllServers($link) {
$serverInfoQuery = "SELECT * FROM servers";
$allServerResults = $link->query($serverInfoQuery);
//More PHP code
}
if(in_array($action,$possibleCalls)){
switch ($action){
case 'allServers':
$return = allServers($link);
break;
}
}
To be honest, even better solution would be using some generic classes/functions to establish your mysql connection like so:
class DB {
private static $link = null;
public static function getConnectionResource() {
//In that way we "cache" our $link variable so that creating new connection
//for each function call won't be necessary
if (self::$link === null) {
//Define your connection parameter here
self::$link = new mysqli($host, $user, $password, $database);
}
return self::$link;
}
}
function getAllServers() {
$link = DB::getConnectionResource();
//Preform your query and return results
}
Use global variable
function allServers(){
global $link
...
...
...
... your code follows
I am currently storing in MySQL database image names for easier way to retrieve the actual images. I am having problems with the php code I created that stores the names. Duplicate and blank insertions are being made into the DB without my permission.
Is there a way to avoid this issue of duplicate or blank values being inserted when the page refreshed?
<?
$images = explode(',', $_GET['i']);
$path = Configuration::getUploadUrlPath('medium', 'target');
if (is_array($images)) {
try {
$objDb = new PDO("mysql:host=" . $host . ";dbname=" . $db, $user, $pass);
$objDb->exec('SET CHARACTER SET utf8');
} catch (PDOException $e) {
echo 'There was a problem';
}
$sql = "INSERT INTO `urlImage` (`image_name`) VALUES ";
foreach ($images as $image) {
$value[] = "('" . $image . "')"; // collect imagenames
}
$sql .= implode(',', $value) . ";"; //build query
$objDb->query($sql);
}
?>
First, you should be checking for blank names in your foreach statement, as such:
foreach ($images as $image) {
if($image!='') {
$value[] = "('".$image."')"; // collect imagenames
}
}
Secondly, you should look into header("Location: ..."); to prevent users from refreshing the page.
Thirdly, you could also set a session variable or cookie to prevent a user from uploading the same image twice.
Lastly, if the image names are unique, you can set a UNIQUE index on the image name. Then use INSERT IGNORE and that will remove all of your duplicates.
I reformatted things into what I think should be slightly more readable and more easily separate what's going on in the code. I also updated your queries to show how you can properly "sanitize" your input.
I still think the process by which you're going about sending the data to the server is wrong, but hopefully this code helps you out a little bit. I'd also do this more object orientedly.. but I feel that leaves the scope of your question just a little bit =P. It's kind of like everyone else is saying though, the logic for your code was only off just slightly.
As for the duplication thing, look into checking if the file already exists before adding it to the database.
<?php
$_GET['i'] = 'file1.png, file2.png, file3.png'; // This is just for testing ;].
$images = retrieve_images();
insert_images_into_database($images);
function retrieve_images()
{
//As someone else pointed out, you do not want to use GET for this and instead want to use POST. But my goal here is to clean up your code
//and make it work :].
$images = explode(',', $_GET['i']);
return $images;
}
function insert_images_into_database($images)
{
if(!$images)//There were no images to return
return false;
$pdo = get_database_connection();
foreach($images as $image)
{
$sql = "INSERT INTO `urlImage` (`image_name`) VALUES ( ? )";
$prepared = $pdo->prepare($sql);
$prepared->execute(array($image));
}
}
function get_database_connection()
{
$host = 'localhost';
$db = 'test';
$user = 'root';
$pass = '';
try {
$pdo = new PDO("mysql:host=" . $host . ";dbname=" . $db, $user, $pass);
$pdo->exec('SET CHARACTER SET utf8');
} catch(PDOException $e) {
die('There was a problem');
}
return $pdo;
}
The easiest way to avoid duplicates upon refresh is to re-direct the page after the POST, so just doing header("Location: {$_SERVER['PATH_INFO']}"); should solve that for you.
To avoid empty entries try is_array($images) && count($images)
You probably should change the following line:
if(is_array($images)){
to this:
if(!empty($images) && is_array($images)){
explode() returns an empty array even if no "i" parameter is provided
Try setting a session variable and tell it to exit or redirect when session variable is not set.
For example
if (!isset($_SESSION['session_name']))
{
exit();
}