This is my fonction.php :
<?php
function connect(){
$servername = "localhost";
$username = "xxx";
$password = "xxxx";
$dbname = "xxx";
// Create connection
$conn = new mysqli($servername, $username, $password, $dbname);
// Check connection
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
if ($conn->query($sql) === TRUE) {
echo "New record created successfully";
} else {
echo "Error: " . $sql . "<br>" . $conn->error;
}
$conn->close();
}
}
?>
But it does not works with my code when I want to call this function :
<?php
include("fonctions.php");
?>
<html>
<form name="inscription" method="post" action="form.php">
xxx : <input type="text" name="xxx"/> <br/>
xxx: <input type="text" name="xxx"<br/>
<input type="submit" name="valider" value="OK"/>
</form>
<?php
if (isset ($_POST['valider'])){
$titre=$_POST['xxx'];
$auteur=$_POST['xxx'];
connect();
$sql = 'INSERT INTO xxx (`xxx`, `xxx`) VALUES("'.$xxx.'","'.$xxx.'")';
}
?>
</body>
</html>
Before I was using mysql_connect and it was more simple, my fonction was like this :
<?php
function connect(){
$base = mysql_connect ('localhost', 'root', '');
mysql_select_db ('MaBase', $base) ;
}
?>
What is the best way to create a good include with my mysql params ? THanks all for any help.
Include obligatory statement about using PDO or mysqli and prepared statements when using variables in your SQL statements...
You aren't passing your function a SQL statement to use, or otherwise defining $sql in the function.
function connect($sql){
For defining it, and then to call it
$sql_statement="select foo from bar where bee=1";
$res=connect($sql_statement);
You'll also need your function to return some sort of value.
What I've done is create a generic function that takes a SQL statement and an array of positional parameters, the function then uses PDO and prepared statement to execute the query using the parameters, and then returns an array with appropriate data. $ret[0] is a bool to indicate success, if false then [2..N] contain(s) error message(s), if true then [2..N] contains returned record set for a select, number of rows affected for update, delete, and last_insert_id for an insert statement (detected by using regular expression on the query string)
This is written once, and require_once()'d all across 15 web apps for the college I work at.
To this you i suggest you to use OOP approach i am just suggesting this with my own way you can try it with different ways no problem in my answer i am using two class first class does all the database connection and mysqli real escape conversion and staff other class is query class it's handle all the querying staff
database.class.php
//databaseconnection
class DatabaseConnections{
function connect($databaseNaem){
try{
return $connection=mysqli_connect("localhost","user","password",'database');
}catch(Exception $e){
echo 'Message:'.$e->getMessage();
}
}
function CloseConnection($dataObject){
if(mysqli_close($dataObject)){
return 1;
}else{
echo "coudn't Close the Database Connection";
}
}
function convert($connection , $vari){
return mysqli_real_escape_string($connection,$vari);
}
}
//queryclass
class Query{
function queryNoresult($stmt){
if($stmt->execute()){
return 1;
}
}
function queryNumOfRows($stmt){
$stmt->execute();
$result = $stmt->get_result();
return mysqli_num_rows($result);
}
function QueryResult($stmt){
$stmt->execute();
$result = $stmt->get_result();
return $result;
}
function illcallothers($stmt,$callto){
if($callto == 1){
return $this->queryNoresult($stmt);
}if ($callto==2) {
return $this->queryNumOfRows($stmt);
}
if($callto == 3){
return $this->QueryResult($stmt);
}
}
}
as you can see at the end i have created a function call illcallothers and this function takes what you want do with your query it's takes only 2 parameters
Created statement
The function number
there 3 option in this
if you call $query->illcallothers($stmt,1) this call the function
only for execute best for delete and insert because it's return 1 if
it's success
if you call $query->illcallothers($stmt,2) this call the function that return number of rows that returned nothing else best for check it data is availbe before using while
if you call $query->illcallothers($stmt,3) this will return result set from your query
Now lets go to your problem execution
//first you have to require the database file
require_once('database.class.php');
//Then you have to create object from them
$mymainObj = new DatabaseConnections();//obj from database
$connetion = $mymainObj->connect('databasename');//this will return a connection Object
$stmt = $connection->stmt_init(); //then the statement you need the connection object to this
$query = new Query();//object from the query class
//i am not going to put form part in here it will get messy
$titre= $mymainObj->convert($connection,$_POST['xxx']);//calling mysqli realescape funciton in databaseconnection
$auteur=$mymainObj->convert($connection,$_POST['xxx']);
//now you have create the sql
$sql = 'INSERT INTO xxx (`xxx`, `xxx`) VALUES(?,?)';//when using stmt this how we tell mysql that we have this much parameters and then we pass them after preparing
if($stmt->prepare($sql)){
$stmt->bind_param('ss',$title,$author);
if($query->illcallothers($stmt,1)){
echo "Query Success";
}
}
It should be,
<?php
function connect(){
$servername = "localhost";
$username = "xxx";
$password = "xxxx";
$dbname = "xxx";
// Create connection
$conn = new mysqli($servername, $username, $password, $dbname);
// Check connection
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
return false;
}else{
return $conn;
}
}
?>
Your query should be,
<?php
if (isset($_POST['valider'])){
$titre=$_POST['xxx'];
$auteur=$_POST['xxx'];
$connection = connect();
if($connection != false){
$sql = 'INSERT INTO xxx (`xxx`, `xxx`) VALUES("'.$xxx.'","'.$xxx.'")';
$result=$connection->query($sql);
if($result){
echo "done";
}else{
echo "faild";
}
}
}
?>
You should take a tour/learn the basics of OOP
It seems like all the above answers missed that you have two variables with the same name:
$sql = 'INSERT INTO xxx (`xxx`, `xxx`) VALUES("'.$xxx.'","'.$xxx.'")';
Both are called $xxx
IF YOU thought that the names of your public variables shoulden't be shown publicly here, and changed them to 'xxx', then please edit your question and don't change them to the same name (e.g change to $name and $password for example)
Related
My question is, how efficient are PHP Mysqli prepared statements? From what I have understand from basic reading, prepared statements 1) help in security using bound inputs 2) speed up and 'reduce' data sent to the server by somewhat 'pre-packaging' or 'preparing' the sql query to an extent, and once data is available, it just attaches the data to the prepared statement and executes it. This also helps on 'repeated' use of the same statement when inserting the same data (different values) repeatedly, because the statement is prepared only once.
Now, I am building a website with several functionalities, and all (or most) of them use JQuery and AJAX to get obtain user input, do some checks (either in the JS/JQ or in PHP), Send the data to a PHP file PHP_AJAX_Handler.php specified in the AJAX URL. The PHP file prepares the SQL statemtns to insert data into database, then return JSON success/failure messages. For example, most of my features/functionality are programmed as follows; below is one file which I am using to 1) check for existing continent-country pair, and 2) insert the new continent-country pair.
HTML:
<input type='text' id='continent'>
<input type='text' id='country'>
<button id='btn1'></button>
<p id='p1'></p>
<p id='p2'></p>
<p id='p3'></p>
JQuery:
$("#btn1")click(function(){
var Cntt = $("#continent").val();
var Ctry = $("#country").val();
$.post("PHP_AJAX_Handler.php",{CN:cntt,CT:ctry},function(DAT)
{ var RET_j = json.PARSE(dat);
if(RET_j.PASS=='FAIL')
{ $('#p1').html(RET_j.PASS);
$('#p2').html(RET_j.MSG1);
}
if(RET_j.PASS=='OKAY')
{ $('#p1').html(RET_j.PASS);
$('#p3').html(RET_j.MSG2);
} }
);
});
PHP_AJAX_Handler.php
<?PHP
session_start();
if( (isset($_POST['CT'])) && (isset($_POST['CN'])))
{ require_once ("golin_2.php");
$CN = $_POST['CN'];
$CT = $_POST['CT'];
$ER = "";
$CONN = mysqli_connect($SERVER, $USER, $PASS, $DBNAME);
If($CONN == FALSE)
{ $ER = $ER . "Err: Conn Could not connect to Databse ".mysqli_connect_errno().' '.mysqli_connect_error();
}
else
{ $SQL_1 = "SELECT * FROM sailors.continental_regions WHERE CONTINENT = ? AND COUNTRY = ?";
if(!($STMT_1 = mysqli_stmt_init($CONN)))
{ $ER = $ER . "Err: Stmt Prepare Failed";
}
else
{ if(!mysqli_stmt_prepare($STMT_1, $SQL_1)) ///FIRST SET of prepared statement lines
{ $ER = $ER . "Err: Stmt Prepare Failed";
}
else
{ if(!mysqli_stmt_bind_param($STMT_1,"ss",$CN, $CT))
{ $ER = $ER . "Err: Stmt Prepare Failed";
}
else
{ if(!(mysqli_stmt_execute($STMT_1)))
{ $ER = $ER . "Err: Stmt_1 Execute Failed";
}
else
{ $RES_1 = mysqli_stmt_get_result($STMT_1);
$NUMROWS_1 = mysqli_num_rows($RES_1);
if($NUMROWS_1>0)
{ $ER = $ER . "Err: duplicate '$CN' '$CT' pair";
}
if($NUMROWS_1==0)
{ $SQL_2 = "INSERT INTO DB.continental_regions (CONTINENT,COUNTRY) values (?, ?)";
if(!($STMT_2=(mysqli_stmt_init($CONN))))
{ $ER = $ER . "Err: Init2 failed";
}
else
{ if(!mysqli_stmt_prepare($STMT_2, $SQL_2)) ///SECOND SET of prepared statement lines
{ $ER = $ER . "Err: Prep2 failed".mysqli_error($CONN);
}
else
{ if(!mysqli_stmt_bind_param($STMT_2,"ss",$CN, $CT))
{ $ER = $ER . "Err: Bind2 failed";
}
else
{
if(!(mysqli_stmt_execute($STMT_2)))
{ $ER = $ER . "Err: Exec failed";
}
else
{ $arr['PASS'] = 'OK';
}
}
}
}
}
}
}
}
}
mysqli_free_result($RES_1);
mysqli_stmt_close($STMT_1);
mysqli_stmt_close($STMT_2);
mysqli_close($CONN);
}
if($ER!=="")
{ $arr['MSG'] = $ER;
$arr['PASS'] = 'FAIL';
}
if($arr['PASS']=="OK")
{ $arr['MSG2'] = "Insert Success";
}
echo json_encode($arr);
}
else
{ header("location: ../Error_Fail.php");
}
?>
As you can see, the PHP file is turning out to be pretty long. There is one set of prepare statements to check if the CC pair exists already in table, then another to insert the CC pair.
From what I see, for each AJAX request to add a new pair of values, the mysqli statements are prepared over again. Then again for the next request, and so on. I imagine this is creating a lot of overhead and data to the server just to achieve Security. Is this true for other people developing web applications with AJAX-POST-PHP? to me it seems unavoidable that for each prepare, values can only be inserted one time? How to get around to preparing this statement once, and only doing repeat executes whence data is available? I can't seem to get my head around the 'efficiency' factor of prepared statements..
Thanks.. would appreciate some advise from some seasoned programmers out there..
You said:
As you can see, the PHP file is turning out to be pretty long.
That is true, but that is not the fault of prepared statements. You must have been learning PHP development from a poorly written tutorial. This code does not need to be so long. In fact, it can be severely shortened.
Just fixing your existing code made it much more readable. I used OOP-style mysqli and I removed all these if statements. You should enable error reporting instead.
<?php
session_start();
if (isset($_POST['CT'],$_POST['CN'])) {
require_once "golin_2.php";
$CN = $_POST['CN'];
$CT = $_POST['CT'];
$ER = "";
$arr = [
'PASS' => "OK",
'MSG2' => "Insert Success",
]; // successful state should be the default outcome
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$CONN = new mysqli($SERVER, $USER, $PASS, $DBNAME);
$CONN->set_charset('utf8mb4'); // always set the charset
// To check existance of data in database we use COUNT(*)
$stmt = $CONN->prepare("SELECT COUNT(*) FROM sailors.continental_regions WHERE CONTINENT = ? AND COUNTRY = ?");
$stmt->bind_param("ss", $CN, $CT);
$stmt->execute();
$NUMROWS = $stmt->get_result()->fetch_row()[0];
if ($NUMROWS) {
$ER .= "Err: duplicate '$CN' '$CT' pair";
} else {
$stmt = $CONN->prepare("INSERT INTO DB.continental_regions (CONTINENT,COUNTRY) values (?, ?)");
$stmt->bind_param("ss", $CN, $CT);
$stmt->execute();
}
if ($ER) {
$arr = [
'PASS' => "FAIL",
'MSG' => $ER,
];
}
echo json_encode($arr);
} else {
header("location: ../Error_Fail.php");
}
If you have a composite UNIQUE key on these two columns in your table then you can remove the select statement. Also, you should clean up your response preparation. The successful state should be the default and it should be replaced with the error message only if something went wrong.
In this example, I removed one SQL statement. The whole thing is now much simpler.
<?php
define('DUPLICATE_KEY', 1062);
session_start();
if (isset($_POST['CT'],$_POST['CN'])) {
require_once "golin_2.php";
$CN = $_POST['CN'];
$CT = $_POST['CT'];
$arr = [
'PASS' => "OK",
'MSG2' => "Insert Success",
]; // successful state should be the default outcome
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$CONN = new mysqli($SERVER, $USER, $PASS, $DBNAME);
$CONN->set_charset('utf8mb4'); // always set the charset
try {
$stmt = $CONN->prepare("INSERT INTO continental_regions (CONTINENT,COUNTRY) values (?, ?)");
$stmt->bind_param("ss", $CN, $CT);
$stmt->execute();
} catch (mysqli_sql_exception $e) {
if ($e->getCode() !== DUPLICATE_KEY) {
// if it failed for any other reason than duplicate key rethrow the exception
throw $e;
}
// if SQL failed due to duplicate entry then set the error message
$arr = [
'PASS' => "FAIL",
'MSG' => "Err: duplicate '$CN' '$CT' pair",
];
}
echo json_encode($arr);
} else {
header("location: ../Error_Fail.php");
}
Regarding performance.
There is no problem with performance in this example and prepared statements don't improve or degrade the performance. I assume you are trying to compare the performance to static SQL queries, but in your simple example there should be no difference at all. Prepared statements can make your code faster compared to static queries when you need to execute the same SQL many times.
If you find writing the 3 lines of code each time too much, then you can create a wrapper function that will reduce it for you to a single function call. In fairness you should avoid using mysqli on its own. Either switch to PDO or use some kind of abstraction library around mysqli.
When I run the page with an empty database, it will insert the data correctly. When I run the page again, it displays there is already an ID in the database, but it inserts it anyway. Not sure how or why but I've tried every combination of booleans inside the if statements and cant get it to chooch correctly.
//pass in an ID to compare:
function checkOrderID($orderID) {
//Connect to the database:
$mysqli = new mysqli("localhost", "root", "", "price");
if (mysqli_connect_errno()) {
printf("Connect failed: %s\n", mysqli_connect_error());
exit();
}
//Ask the database for some sweet, sweet data:
$stmt1 = "SELECT orderID FROM orders";
$result = $mysqli->query($stmt1);
//flag (we want to believe that there are no similar IDS so lets make it true):
$flag = true;
//while we got some data, display that shit
while ($row = $result->fetch_assoc()) {
//asign data to variable:
$rowOrderID = $row['orderID'];
//Does it match? if it does set the flag to false so it doesnt get inserted.
if ($rowOrderID == $orderID) {
echo "Row ID" . $row["orderID"] . " Passed ID: " . $orderID . "<br>";
echo "This order is already in the database" . "<br>";
$flag = false;
}
}
//hand the flag over to who ever needs it
return flag;
}
.
if (checkOrderID($orderID) == true) {
//some mysql insert logic here
}
Why are you making this complicated. just do something like this:
$con=mysqli_connect("localhost","root","","price");
$check_query = mysqli_query($con,"SELECT * FROM orders WHERE orderID = $orderID");
if (mysqli_num_rows($check_query) == 0) {
//mysql insert logic here
}
(Noted of course you are going to have your connection logic as well)
Note: You are using Mysqli in object oriented manner but in this example i have not used object oriented manner of DB connection. The connection variable $con must be passed to mysqli_query() method.
Also... random side note, but it's generally a good idea to have a password for your root mysql user.
Here better and short, but please try to use DB connection globally not inside your mothod and try to use prepared statements. But except those you can use following code.
//pass in an ID to compare:
function checkOrderID($orderID) {
//Connect to the database: I suggest use global DB connection
$mysqli = new mysqli("localhost", "root", "", "price");
if (mysqli_connect_errno()) {
printf("Connect failed: %s\n", mysqli_connect_error());
exit();
}
//gets recodrs based on $orderID passed to this method
$stmt1 = "SELECT * FROM orders where orderID=$orderID"; //Try to use prepared statement
$result = $mysqli->query($stmt1);
//Store number of rows found
$row_count = $result->num_rows;
if($row_count>0){
return true;
}
else{
return false;
}
}
If I run this code , the value in the SQL base is added 5x.
Code:
function token($u) {
include('../config.php');
$token=md5(rand()+$u);
$date = date('Y-m-d H:i:s');
$tokenQuery = 'INSERT INTO '.$prefix.'tokens(`token`, `user`, `date`) VALUES ("'.$token.'","'.$u.'","'.$date.'")';
$mysqli->query($tokenQuery);
}
token ('filips');
See how it look my SQL base
My config is:
$host = 'my server';
$user = 'my username';
$pass = 'my password';
$data = 'pn_16734995_filipcms_demo';
$prefix = 'fc_';
$mysqli = new mysqli($host,$user,$pass, $data);
$mysqli->query("SET NAMES 'utf8'" );
if ($mysqli->connect_errno) {
echo "Server not working: (" . $mysqli->connect_errnor. ") " . $mysqli->connect_error;
}
Nothing in your code will make the INSERT statement happen 5 times. However, if you echo "function called"; inside of your function, you can see if the function is being called 5 times, then you can figure out where up the line your function is being called 5 times.
you don't need to include the whole file just pass $mysqli as a parameter or put it in a global scope;
function token($u,$mysqli) {
}
OR
function token($u) {
global $mysqli;
}
I'm trying to update my datebase from a php archive but i can't:
Before you ask: The names from db are written correctly and the if works too...
<?php
if(isset($_GET["ans"]) && isset($_GET["name"]))
{
include("con.php");
$con = con();
$answer = $_GET["ans"];
$nam = $_GET["name"];
if($answer="firefly" ||$answer="Firefly" ||$answer="FIREFLY")
{
$le=2;
$sc=50;
$update = "UPDATE User SET Level='$le', Score='$sc' where Name = '$nam'";
mysql_query($update,$con);
// header("Location: lv1b.php?n=$nam");
}
else {
echo "try again..." ;
}
}
?>*
This is the con.php...
<?php
function con()
{ $server="localhost"; $user="root"; $pass="";
$con= mysql_connect($server, $user,$pass);
mysql_select_db("games"); return $con;
}
Your if statement currently is assigning values, not testing equality, you can also skip the three tests by using one of the case conversion functions... so instead the if line should be:
if(strtolower($answer)=="firefly") {
Next up - as pointed out in comments - you're using the out-of-date MySQL library, you should rather be using MySQLI or PDO
Also you're wide open to SQL injection, you should be escaping any value you're using in MySQLi see mysqli_real_escape_string. In your example this means escaping the value of $nam
A potential alternative script-fragment (using MySQLi and the above if statement changes) might look something like:
<?php
$mysqli = new mysqli("localhost", /*username*/"root", /*pass*/"", /*dbname*/);
$name=$mysqli->real_escape_string($_GET["name"]);
if (strtolower($_GET["ans"])=="firefly") {
if (!$mysqli->query("UPDATE user SET level='2',score='50' ".
"WHERE name='$name'")) {
echo "query failed";
} else {
echo "Updated"
}
$mysqli->close();
} else {
echo "try again..";
}
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