Optimized code for mysql insert query - php

Hello i am writing a module for inserting data in MySQL table. It is very easy but in my module i am receiving four mobile number. The first one is user's mobile no and other three are reference mobile number. User's mobile no is mandatory field but reference are not. this time i am checking each reference mobile no by using isset() and empty() function in PHP.
but i have to write multiple if-else block. like
if(isset($_POST['mobileno_1']) && !empty($_POST['mobileno_1'])){
$mobileno1 = $_POST['mobileno_1'];
}else{
$mobileno1 = 0;
}
if(isset($_POST['mobileno_2']) && !empty($_POST['mobileno_2'])){
$mobileno2 = $_POST['mobileno_2'];
}else{
$mobileno2 = 0;
}
if(isset($_POST['mobileno_3']) && !empty($_POST['mobileno_3'])){
$mobileno3 = $_POST['mobileno_3'];
}else{
$mobileno3 = 0;
}
$sql = "INSERT INTO refferencemobile(mobileno, mobile1, mobile2, mobile3) VALUES($mobileno, $mobileno1, $mobileno2, $mobileno3)";
is there any optimized way to do this.so that it can reduce number of if-else block.

empty already checks if a variable isset so this simplifies the if statments.
You can also use ternary conditions. These look like:
$someCondition ? 'a' : 'b';
Which will evaluate to 'a' if $someCondition is true and 'b' otherwise.
Putting this together we can get:
//If $_POST['mobileno_1'] isset and has a non false value use $_POST['mobileno_1']
$mobileno1 = !empty($_POST['mobileno_1']) ? $_POST['mobileno_1'] : 0;
$mobileno2 = !empty($_POST['mobileno_2']) ? $_POST['mobileno_2'] : 0;
$mobileno3 = !empty($_POST['mobileno_3']) ? $_POST['mobileno_3'] : 0;
As user1281385 pointed out in the comments you are using posted values directly in a query. You need to make sure these are sanitised or, better yet, use prepared statements.

Something like this perhaps:
$mobileno3 = (isset($_POST['mobileno_3']) && !empty($_POST['mobileno_3']))
? $_POST['mobileno_3']
: 0;
You can even turn it into a function.
function GetMobileNo($mobileNo)
{
return (isset($mobileNo) && !empty($mobileNo)) ? $mobileNo : 0;
}
$mobileno3 = GetMobileNo($_POST['mobileno_3']);

sample/test code here http://codepad.org/5ybUcmcN
$mobileno1 = getMobileNo($_POST['mobileno_1']);
$mobileno2 = getMobileNo($_POST['mobileno_2']);
$mobileno3 = getMobileNo($_POST['mobileno_3']);
/* example
$mobileno1 = getMobileNo('abc');
$mobileno2 = getMobileNo('111');
$mobileno3 = getMobileNo('');
*/
$sql = "INSERT INTO refferencemobile(mobileno, mobile1, mobile2, mobile3) VALUES($mobileno, $mobileno1, $mobileno2, $mobileno3)";
function getMobileNo($mobileNo){
// check for if its set or not OR empty OR not an integer
if(!isset($mobileNo) || empty($mobileNo) || !is_int($mobileNo)){
return 0;
}
return $mobileNo; // valid number
}

Related

adding up sums of multiple variables in php

ok
so I have been stuck on this problem for a while and I'm sure there is a more elegant way of doing it.
I have 3 columns in a database -
Stand1 | Stand2 | Stand3
each column will either have a stand number (i.e D30) or 'Not Assigned'
What I need to do is count how many stands have been assigned to that customer.
For example :
D30 | not assigned | not assigned would = 1
D30 | B30 | E30 = 3
The code I have so far is
if ($row["stand1"] == 'Not Assigned') {
$stand1 = '0';
}
else {
$stand1 = '1';
}
if ($row["stand2"] == 'Not Assigned') {
$stand2 = '0';
}
else {
$stand2 = '1';
}
if ($row["stand3"] == 'Not Assigned') {
$stand3 = '0';
}
else {
$stand3 = '1';
}
I then thought I could try and count how many stand were assigned :
$standcount = $stand1 + $stand2 + $stand3
But when I print this out (everything else is in an array so loops through every customer) all I get is the total 3 for every customer.
I tried saving the data into an array like:
$standcount = array($stand1, $stand2, $stand3);
But I get the same result. I thought a foreach loop may work but not sure how to do it.
I would suggest you to:
Set the columns' default value to NULL, so that if no value is provided in an entry you'll have a null value instead of a string (that can contains different letters, as in your case). After that you can simply perform the isset() check against each value.
Use a function to avoid code repetition (the main source of errors), something like:
function check($value) {
return (isset($value)) ? 1 : 0;
}
$stand_1 = check($row["stand1"]);
$stand_2 = check($row["stand2"]);
$stand_3 = check($row["stand3"]);
If you instead want to use a string as "Not Assigned" or "NA", you can perform a case-insensitive check with strcasecmp() between the strings in case, for any reason, a value contains an extra space or a lower-case letter.
In this case the check function would be:
function check($str) {
return (strcasecmp($str, "NA") == 0) ? 0 : 1;
}
$stand_1 = check($row["stand1"]);
$stand_2 = check($row["stand2"]);
$stand_3 = check($row["stand3"]);

Undefined variable array

I get an error on line 15 that says "Undefined variable: row2". How can I resolve this?
$limit = 20;
$res1 = mysql_query('SELECT *
FROM contact
WHERE name = "Greg"');
$res2 = mysql_query('SELECT name
FROM contact c, passport p
ON c.idNum = p.iNum
WHERE date >= "2015-03-03" AND t< "2015-03-21');
if(!$res1 && !$res2) {
die('Query no valid: ' . mysql_error());
}
else {
while(($row1 = mysql_fetch_array($res1)) || ($row2 = mysql_fetch_array($res2))) {
$sub = $row1['num'] - $row2['num'];
if($sub <= $limit) {
echo '<br>row name is: ', $row2['name'];
}
}
}
What I'm trying to do is get a number from the first table (it only results to just Greg's row). Then subtract it with the numbers from the results of the second table. The result of this is placed into the sub variable and it's check to see if it's <= 20. If yes, it prints out the row. If not, it goes back to while loop to check another row. Am I going about the right way so far?
You need to change the while() loop's condition. Consider this example:
$a = 1;
if ($a == 1 || $b = 2) {
var_dump(isset($b));
}
Output of var_dump() will be boolean false because $b does not exist, which is the same case why your $row2 is undefined.
The thing is, while evaluation conditions with ||, PHP will stop evaluating other conditions once the match is found, so other comparisons or assignments on the right side will not be performed.
Change your while to be like this, you need both $row1 and $row2 anyway:
while(($row1 = mysql_fetch_array($res1)) && ($row2 = mysql_fetch_array($res2))) {
(note the && instead of ||)
Also, looks like you may want to use SELECT c.* in your second query, too, because you're only selecting the name column, and trying to use num too.
Note : Select all columns in your 2nd Query if num is already available in your columns so your problem will be solved then.!
Note : Try to replace || with && and you will be good to go.
By using || or OR as in conceptional language as I would say it.You are making the code like in a way that either and only one will pass but if you are passing both ones so then you should replace || with && so that's why your $row2 will be already created then so it will be available for more operation.!
$limit = 20;
$res1 = mysql_query('SELECT *
FROM contact
WHERE name = "Greg"');
$res2 = mysql_query('SELECT *
FROM contact c, passport p
ON c.idNum = p.iNum
WHERE date >= "2015-03-03" AND t< "2015-03-21');
if(!$res1 && !$res2) {
die('Query no valid: ' . mysql_error());
}
else {
while(($row1 = mysql_fetch_array($res1)) && ($row2 = mysql_fetch_array($res2))) {
$sub = $row1['num'] - $row2['num'];
if($sub <= $limit) {
echo '<br>row name is: ', $row2['name'];
}
}
}

PHP - Change value of variable before inserting into sql - Without Ajax

I have the variable
$sql1 .= "Brukertype";
Which gets information set from an already-filled textbox. It can either have the value Administrator or the value Iskjører.
What is the best way to change these values before inserting them into SQL?
The Administrator value should get changed to the value 1 and Iskjører gets changed to the value 2.
I can't use a select function (dropdown list) on the question because it needs to be enabled/disabled on my command.
This is a reasonable place to use a switch statement. You want a 'marshaling' function, like this:
function marshal_input($input) {
$result = 0;
switch ($input){
case 'Administrator':
$result = 1;
break;
case 'Iskjører':
$result = 2;
break;
case 'SomethingYouHaventThoughtOfYet':
$result = 3;
break;
default:
$result = 0;
break;
}
}
However, the implementation of the marshaling function can be almost anything:
function marshal_input($input) {
$options = array("Administrator" => 1, "Iskjører" =>2);
return $options[$input];
}
The point is that you need some code that maps from the human-readable form to the numerical representation the db needs. Then you just call it like so:
$sql_version = marshal_input($sql1);//Doesn't overwrite the variable
//...or...
$sql1 = marshal_input($sql1);//Note this overwrites the variable.
Since you have stated:
It can eighter have the value "Administrator" or the value "Iskjører"...
we only check whether the value is 'Administrator' or not.
Try this:
$val = 'Administrator'; // user input variable
$sql_val = ($val == 'Administrator') ? 1 : 2;
If value is 'Administrator' set $sql_val to 1, else set $sql_val to 2

PHP conditions in ajax

The code below is part of an ajax script. Everything else is working perfectly except what is below.
I have no idea why this is happening :
$q_e = mysqli_query($sqllink,"SELECT * FROM events_parent WHERE id='$id_parent'");
$r_e = mysqli_fetch_array($q_e);
if($id_cure == $r_e['id_cure']){
$same = 1;
}else{
$same = 2;
}
if($same == 1){ //condition A
# cure is the same
mysqli_query($sqllink,"UPDATE events_parent ... ")
}elseif($same == 2){ // condition B
# cure is changed
mysqli_query($sqllink,"UPDATE events_parent ...")
}
No matter what the value of $same is, the my code still goes into condition A when it should just go into condition B. Even if i stop the script like this :
if($id_cure == $r_e['id_cure']){
$same = 1;
}else{
$same = 2;
}
echo "same : $same";
exit();
It outputs "same : 2", it does the mysql update correctly set in condition B but it also does the update set in condition A.
What am I doing wrong ? I tried using "===" instead of "==" but not result... Does anyone has an idea ?

PHP prevent double clean url (improvements?)

For a client at work we have build a website.The website has an offering page which can contain variants of the same type/build, so they ran into problems with double clean-urls.
Just now I wrote a function to prevent that from happening by appending a number to the URL. If thatclean url also exists it counts up.
E.g.
domain.nl/product/machine
domain.nl/product/machine-1
domain.nl/product/machine-2
Updated! return $clean_url; on recursion and on return
The function I wrote works fine, but I was wondering if I have taken the right approach and if it maybe could be improved. Here's the code:
public function prevent_double_cleanurl($cleanurl)
{
// makes sure it doesnt check against itself
if($this->ID!=NULL) $and = " AND product_ID <> ".$this->ID;
$sql = "SELECT product_ID, titel_url FROM " . $this->_table . " WHERE titel_url='".$cleanurl."' " . $and. " LIMIT 1";
$result = $this->query($sql);
// if a matching url is found
if(!empty($result))
{
$url_parts = explode("-", $result[0]['titel_url']);
$last_part = end($url_parts);
// maximum of 2 digits
if((int)$last_part && strlen($last_part)<3)
{
// if a 1 or 2 digit number is found - add to it
array_pop($url_parts);
$cleanurl = implode("-", $url_parts);
(int)$last_part++;
}
else
{
// add a suffix starting at 1
$last_part='1';
}
// recursive check
$cleanurl = $this->prevent_double_cleanurl($cleanurl.'-'.$last_part);
}
return $cleanurl;
}
Depending on the likeliness of a "clean-url" being used multiple times, your approach may not be the best to roll with. Say there was "foo" to "foo-10" you'd be calling the database 10 times.
you also don't seem to sanitize the data you shove into your SQL queries. Are you using mysql_real_escape_string (or its mysqli, PDO, whatever brother)?
Revised code:
public function prevent_double_cleanurl($cleanurl) {
$cleanurl_pattern = '#^(?<base>.*?)(-(?<num>\d+))?$#S';
if (preg_match($cleanurl_pattern, $base, $matches)) {
$base = $matches['base'];
$num = $matches['num'] ? $matches['num'] : 0;
} else {
$base = $cleanurl;
$num = 0;
}
// makes sure it doesnt check against itself
if ($this->ID != null) {
$and = " AND product_ID <> " . $this->ID;
}
$sql = "SELECT product_ID, titel_url FROM " . $this->_table . " WHERE titel_url LIKE '" . $base . "-%' LIMIT 1";
$result = $this->query($sql);
foreach ($result as $row) {
if ($this->ID && $row['product_ID'] == $this->ID) {
// the given cleanurl already has an ID,
// so we better not touch it
return $cleanurl;
}
if (preg_match($cleanurl_pattern, $row['titel_url'], $matches)) {
$_base = $matches['base'];
$_num = $matches['num'] ? $matches['num'] : 0;
} else {
$_base = $row['titel_url'];
$_num = 0;
}
if ($base != $_base) {
// make sure we're not accidentally comparing "foo-123" and "foo-bar-123"
continue;
}
if ($_num > $num) {
$num = $_num;
}
}
// next free number
$num++;
return $base . '-' . $num;
}
I don't know about the possible values for your clean-urls. Last time I did something like this, my base could look like some-article-revision-5. That 5 being part of the actual bullet, not the duplication-index. To distinguish them (and allow the LIKE to filter out false positives) I made the clean-urls look like $base--$num. the double dash could only occur between the base and the duplication-index, making things a bit simpler…
I have no way to test this, so its on you, but here's how I'd do it. I put a ton of comments in there explaining my reasoning and the flow of the code.
Basically, the recursion is unnecessary will result in more database queries than you need.
<?
public function prevent_double_cleanurl($cleanurl)
{
$sql = sprintf("SELECT product_ID, titel_url FROM %s WHERE titel_url LIKE '%s%%'",
$this->_table, $cleanurl);
if($this->ID != NULL){ $sql.= sprintf(" AND product_ID <> %d", $this->ID); }
$results = $this->query($sql);
$suffix = 0;
$baseurl = true;
foreach($results as $row)
{
// Consider the case when we get to the "first" row added to the db:
// For example: $row['titel_url'] == $cleanurl == 'domain.nl/product/machine'
if($row['title_url'] == $cleanurl)
{
$baseurl = false; // The $cleanurl is already in the db, "this" is not a base URL
continue; // Continue with the next iteration of the foreach loop
}
// This could be done using regex, but if this works its fine.
// Make sure to test for the case when you have both of the following pages in your db:
//
// some-hyphenated-page
// some-hyphenated-page-name
//
// You don't want the counters to get mixed up
$url_parts = explode("-", $row['titel_url']);
$last_part = array_pop($url_parts);
$cleanrow = implode("-", $url_parts);
// To get into this block, three things need to be true
// 1. $last_part must be a numeric string (PHP Duck Typing bleh)
// 2. When represented as a string, $last_part must not be longer than 2 digits
// 3. The string passed to this function must match the string resulting from the (n-1)
// leading parts of the result of exploding the table row
if((is_numeric($last_part)) && (strlen($last_part)<=2) && ($cleanrow == $cleanurl))
{
$baseurl = false; // If there are records in the database, the
// passed $cleanurl isn't the first, so it
// will need a suffix
$suffix = max($suffix, (int)$last_part); // After this foreach loop is done, $suffix
// will contain the highest suffix in the
// database we'll need to add 1 to this to
// get the result url
}
}
// If $baseurl is still true, then we never got into the 3-condition block above, so we never
// a matching record in the database -> return the cleanurl that was passed here, no need
// to add a suffix
if($baseurl)
{
return $cleanurl;
}
// At least one database record exists, so we need to add a suffix. The suffix we add will be
// the higgest we found in the database plus 1.
else
{
return sprintf("%s-%d", $cleanurl, ($suffix + 1));
}
}
My solution takes advantage of SQL wildcards (%) to reduce the number of queries from n down to 1.
Make sure that you ensure problematic case I described in lines 14-20 works as expected. Hyphens in the machine name (or whatever it is) could do unexpected things.
I also used sprintf to format the query. Make sure you sanitize any string that is passed through as a string (e.g. $cleanurl).
As #rodneyrehm points out, PHP is very flexible with what it considers a numeric string. You might consider switching out is_numeric() for ctype_digit() and see how that works.

Categories