Connect object and variabile $object-> $variabile [ PHP ] - php

I try to make query to database, base on user input, because I have multiple inputs in single form it's a big more complicated.
I decide to check if input is filled like:
$query = "";
if((trim($searchParams->firstname)))
$query .= "firstname,";
which works correctly for me, and after I check each input I explode string to array by , and foreach it
$querys = explode(",", $query);
foreach($querys as $q)
{
...
}
What basically create an array of all filled inputs, however just their names base on what i need to get values as well.
So I try to add something like this to query
$searchParams->$q;
But this doesn't work (say it's empty despite the fact if i echo it before it's filled)
I try to do something really dirt as:
$param = "$searchParams->".$q;
$values .= $param;
which say
Object of class could not be converted to string ( if i var_dump($q) it say its string so i dont understand)
I think I 'm doing it really badly but thats the only thing I found out as potentially useful. Any advise to fix this will be helpful.
p.s. Here is how final query should looks like:
"SELECT * FROM candidates WHERE firstname = ? AND surname = ?" ,$searchParams->firstname, $searchParams->surname

Related

A form can return varying number of values, trying to use the returned values in doctrine query

I have saved a bunch of parsed messages in a db, and I want to be able to pull out results depending on user input. I would like to sort by 1-4 values (more options later on), username, id, email or date and time. I've been using doctrine to do my other queries, but this one, I just can't figure out.
My issue is, I don't see how I could possibly check which values are passed into the method and only query for those.
For example:
User enters "bob" into username and "bob#example.com" into the email field. For this scenario I would need doctrine to look something like this:
$queryBuilder
->select('*')
->from('m2m_messages')
->where('username = ' . $queryBuilder->createNamedParameter($params[username]))
->andWhere('email = ' . $queryBuilder->createNamedParameter($params[email]))
$query = $queryBuilder->execute();
But I would like it to change, without creating all the copies separately for each occasion... If I wanted to specify the ID and email, it should only take those values.
I am passing the values in through an array which only contain the search terms I need to use in the sql. For above example it would look something like this:
$params [
username => 'bob',
email => 'bob#example.com'
]
I haven't found a way to implement an if(isset) into my code that would allow me to automatically only use the values I passed into the method.
My goal is to be able to enter details into any number of fields, the values entered get passed in an array, and any combination of them is accepted and crafted into the sql script, without having to write 20+ different sql scripts separately.
Something like this?
$queryBuilder
->select('*')
->from('m2m_messages');
if (count($params) > 0) {
$isFirst = true;
foreach ($params as $paramKey => $paramValue) {
if ($isFirst) {
$queryBuilder->where(sprintf('%1$s = %2$s', $paramKey, $queryBuilder->createNamedParameter($paramValue)));
$isFirst = false;
} else {
$queryBuilder->andWhere(sprintf('%1$s = %2$s', $paramKey, $queryBuilder->createNamedParameter($paramValue)));
}
}
}
$query = $queryBuilder->execute();
The concept is to iterate through your parameters and add the where conditions supplied in $params.

Php search Splitting criteria type

I have a php search form with two fields. One for $code another for '$name'.The user uses one or the other, not both.
The submit sends via $_POST.
In the receiving php file I have:
SELECT * FROM list WHERE code = '$code' OR name = '$name' ORDER BY code"
Everything works fine, however I would like that $code is an exact search while $name is wild.
When I try:
SELECT * FROM list WHERE code = '$code' OR name = '%$name%' ORDER BY code
Only $code works while $name gives nothing. I have tried multiple ways. Changing = to LIKE, putting in parentheses etc. But only one way or the other works.
Is there a way I can do this? Or do I have to take another approach?
Thanks
If you only want to accept one or the other, then only add the one you want to test.
Also, when making wild card searches in MySQL, you use LIKE instead of =. We also don't want to add that condition if the value is empty since it would become LIKE '%%', which would match everything.
You should also use parameterized prepared statements instead of injection data directly into your queries.
I've used PDO in my example since it's the easiest database API to use and you didn't mention which you're using. The same can be done with mysqli with some tweaks.
I'm using $pdo as if it contains the PDO instance (database connection) in the below code:
// This will contain the where condition to use
$condition = '';
// This is where we add the values we're matching against
// (this is specifically so we can use prepared statements)
$params = [];
if (!empty($_POST['code'])) {
// We have a value, let's match with code then
$condition = "code = ?";
$params[] = $_POST['code'];
} else if (!empty($_POST['name'])){
// We have a value, let's match with name then
$condition = "name LIKE ?";
// We need to add the wild cards to the value
$params[] = '%' . $_POST['name'] . '%';
}
// Variable to store the results in, if we get any
$results = [];
if ($condition != '') {
// We have a condition, let's prepare the query
$stmt = $pdo->prepare("SELECT * FROM list WHERE " . $condition);
// Let's execute the prepared statement and send in the value:
$stmt->execute($params);
// Get the results as associative arrays
$results = $stmt->fetchAll(PDO::FETCH_ASSOC);
}
The variable $results will now contain the values based on the conditions, or an empty array if no values were passed.
Notice
I haven't tested this exact code IRL, but the logic should be sound.

PHP SQL Match like value from array

So I am using PHP and SQL (PDO) to write a query that would take values from an array of check box's (names[]) so for instance someone could submit the values "Bob", "John" and "Bill" and I want to match those with a column in the database.
Problem: Database is an import from Excel spreadsheet used for years and there is no set format for the column I match with, some examples of values stored the database could look like any of the following:
"Bill & Bob"
Bill
John and Bill
"Bill"
John, Bill, and Bob
John will perform the task
As you can see I need to use Like %value% to match values because The post request will send just Bill, John and Bob. My problem is how do I do it with the array passed because it could be just John or it could be 2 or all 3, but you can't use something like WHERE column LIKE in(array) correct? Would my best bet be to run the query once for each name and append the results to a single array? I know I could make some sort of dynamic statement that is something like:
WHERE column LIKE '%Bob%' OR
column LIKE '%John%' OR
column LIKE '%Bill%';
My problem doing it that way is that the above method is susceptible to SQL injection if the input isn't satisfied correct? Even if I use a bindValue() and make each one a bindable variable then I have to figure out how many binds there are and I feel like if I have to add names in the future it would be more difficult than it should be. Is the best way to do it what I said above about one query executed multiple times for, once for each name and then append the results together?
Thanks in advance.
EDIT:
Driver is PDO, Engine is MSSQL
You can do it like this.
//Prepare an array with names
$names = [
':name_1' => '%Bob%',
':name_2' => '%Bill%',
];
//build the where
$whereQuery = '';
foreach($names as $bind => $value) {
if(empty($whereQuery)) $whereQuery .= ' OR ';
$whereQuery .= ' column LIKE '.$bind;
}
//here is missing the code with SQL and pdo preparing query
//after preparing query just execute with $names
$sth->execute($names);
Be careful this example provide only code helping you to figure out the solution.
Hope this helps
You should definitely normalize your database.
But just quick approach and since php was mentioned you can generate query like
$names = ['John','Bob','Bill'];
$query = 'SELECT * FROM my_weird_table WHERE ';
$first = true;
foreach ($names as $name) {
if ($first) {
$query .= '`column` LIKE "%'.$name.'%" ';
$first = false;
} else {
$query .= 'OR `column` LIKE "%'.$name'.'%" ';
}
}

Assign POST values to an array in a loop and put array into a database

I have an array containing the names of form input names:
$minmax = array('bed_min', 'bed_max', 'rec_min', 'rec_max', 'bath_min', 'bath_max', 'value_min', 'value_max');
The names are identical to the corresponding columns in a database. Instead of using an sql query like so:
$bed_min=$_POST['bed_min'];
$bed_max=$_POST['bed_max'];
$rec_min=$_POST['rec_min'];
$rec_max=$_POST['rec_max'];
$bath_min=$_POST['bath_min'];
$bath_max=$_POST['bath_max'];
$value_min=$_POST['value_min'];
$value_max=$_POST['value_max'];
$query = "UPDATE first_page SET bed_min='$bed_min', bed_max='$bed_max', rec_min='$rec_min', rec_max='$rec_max', bath_min='$bath_min', bath_max='$bath_max', value_min='$value_min', value_max='$value_max', WHERE email_address='$email' ";
Is there a way to automate all this into a smaller lump of code? I know the POST values should not be added to the query diectly, so maybe a loop to assign the POST values to a corresponding array of variables using something like:
foreach ($minmax as $var){
$var = $_POST[$var]
}
(nb i dont think this snippet will work but ive added it because I think with a bit of editing it might!)
After the list of variables have been assigned the POST values, do the update in the $query using two arrays, one with the list of values and one with the list of database columns. Again I dont know how this will work, so pointers would be helpful!
You don't really need the $minmax array of form input names since you can get those from the keys of $_POST.
If the values are all numbers, like they seem to be, then you could do it all in one line like this:
$query = "UPDATE first_page SET " . vsprintf(implode("='%d', ", array_keys($sanitized_POST))."='%d'", array_values($sanitized_POST))." WHERE email_address='$email'";
That's assuming you have already sanitized the items from $_POST into a new array named $sanitized_POST. I know you said in the above comment to ignore sanitization, but I thought I'd add it so you know I'm not suggesting to use the values straight from $_POST.
You could sanitize the $_POST array with something like this:
$sanitized_POST = array_map(function($item) {
return mysqli::real_escape_string($item);
}, $_POST);
Honestly though, you should try to come up with a solution that uses prepared statements.
On a side note, if you have the sanitized post array, then this one line will essentially do what Quixrick has done with variable variables in one of the other answers:
extract($sanitized_POST);
If you assume that all of the values in post have the same names (array keys) as your columns, then something like this could work for you:
$query = "UPDATE first_page SET ";
foreach ($_POST as $key => $var){
$query .= " $key='$var',";
}
$query = rtrim($query,',') . " WHERE email_address='$email' ";
You probably want to use 'Variable Variables' here. Basically, you'd use a double dollar sign $$ to create a variable with the name of the array value.
$_POST['bed_min'] = 'Rick';
$minmax = array('bed_min', 'bed_max', 'rec_min', 'rec_max', 'bath_min', 'bath_max', 'value_min', 'value_max');
foreach ($minmax as $var){
$$var = $_POST[$var];
}
print "<BR>BED MIN: ".$bed_min;
This outputs:
BED MIN: Rick

Making multiple replacements using str_replace in php

OK here's the problem:
I'm trying to write the query function for a database class in my project and I want to make it easier to escape the sql and check if it is harmful to the database in anyway.
Let's say I have a query like this:
INSERT INTO users (id,name,email,username,birthdate)
VALUES(1,'Josh','josh101#coolsite.com','josh101','1978-11-02')
But it won't really help If I hardcode this into the function. So lets say I used a question mark for all the values I want to insert and then pass an array to the function containing the actual values I want to replace, just like the way it's done in codeigniter.
Here's a sample:
//Here's the way the function appears in the class definition.
public function query($sql,$params=array()){
if (!empty($params) && is_string($sql)):
//do some stuff here.
elseif (empty($params) && is_string($sql)):
//do some other stuff here.
else:
//bad sql argument.
die("Mysql_database ERROR: The query submitted is not a string!");
endif;
}
//Here's where the function is applied.
$sql="INSERT INTO users (id,name,email,username,birthdate)
VALUES(?,?,?,?,?)";
$params=array(1,'Josh','josh101#coolsite.com','josh101','1978-11-02');
$db= new Mysql_database();
$response=$db->query($sql,$params);
Now here's what I want to do:
If the second argument is not provided, just run the query as it is.
Else check the elements of the array provided for their type and escape them properly then replace them in their appropriate positions in the pseudo-sql string provided.
The problem is that it seems that all the question marks get replaced by only the first element of the array:
Here's the code:
/*assuming I already have a function called create_array that well,
basically creates an array with n elements
specified in the first parameter and fills each element with the value provided in
the second parameter.*/
$toreplace = create_array(substr_count($sql, "?"),"?");
$sqlComplete = str_replace($toreplace, $params, $sql);
If I echo $sqlComplete I get this:
INSERT INTO users (id,name,email,username,birthdate)
VALUES(1,1,1,1,1)
What can I do so that each element of $params is put in its appropriate position in the sql string?
PS: Please don't tell me to just use codeigniter because I'm trying to challenge myself here a bit by building a project from scratch, I don't want to always depend on frameworks to get the job done.
Maybe just use MySQL prepared statements?
It can be done like this:
$params=array(1,'Josh','josh101#coolsite.com','josh101','1978-11-02');
$sql="INSERT INTO users (id,name,email,username,birthdate)
VALUES(?,?,?,?,?)";
foreach($params as $param)
{
$pos = strpos($sql, '?');
if($pos !== false)
{
$sql = substr_replace($sql,"'" . $param . "'",$pos,1);
}
}
echo $sql;
Outputs
INSERT INTO users (id,name,email,username,birthdate) VALUES('1','Josh','josh101#coolsite.com','josh101','1978-11-02')
This doesn't do any escaping, it just populates the values in the query. You'll need to add the escaping that's appropriate to the framework/DB API.

Categories