I have the following arrays and I would like to convert each one of them into individual strings. In other words, break the array into individual pieces.
$formatsArray = $_POST['formats'];
$topicsArray = $_POST['topics'];
This is because I would like to include the individual strings in the following query "
$resources = "select * from resources where
stage LIKE '%".$stage."%'
AND format LIKE '%".$formats."%'";
$run_query = mysqli_query($con, $resources);
This is because format expect an individual string for comparison, such as lets assume the array is ["video", "blogs", "articles"], it wouldn't work if format was to be compared with video,blogs,articles but rather video, blogs or articles.
I hope this is clear, and for any clarification, please advise.
All the best,
Update:
$formats = explode(',', $formatsArray);
$topics = explode(',', $topicsArray);
$resources = "select * from resources where
stage LIKE '%".$stage."%'
AND format LIKE '%".$formats."%' AND topic LIKE '%".$topics."%' ";
update:
$run_query = mysqli_query($con, $resources);
while($row = mysqli_fetch_array($run_query)) {
$data[] = array(
'format' => $row['format'],
'title' => $row['title'],
'costs' => $row['cost'],
'stage' => $row['stage'],
'topic' => $row['topic'],
'link' => $row['link']
);
}
Update
include('db.php');
$query = 'select * from resources where ';
$query .= 'stage LIKE :stage and';
$execute[':stage'] = '%' . $stage . '%';
if(!empty($_POST['formats'])){
foreach($_POST['formats'] as $key => $format) {
$query .= 'format LIKE :format' . $key . ' and ';
$execute[':format' . $key] = '%' . trim($format) . '%';
}
}
if(!empty($_POST['topics'])){
foreach($_POST['topics'] as $key => $topic) {
$query .= 'topic LIKE :topic' . $key . ' and ';
$execute[':topic' . $key] = '%' . trim($topic) . '%';
}
}
$query = rtrim($query, ' and ');
if(!empty($execute)) {
$stmt = $con->prepare($query);
$stmt->execute($execute);
} else {
echo 'You must search for something';
}
while($row = mysqli_fetch_array($query)) {
$data[] = array(
'format' => $row['format'],
'title' => $row['title'],
'costs' => $row['cost'],
'stage' => $row['stage'],
'topic' => $row['topic'],
'link' => $row['link']
);
}
Ignoring the necessity of prepared statements, you could do:
$formats = implode('","', $formatsArray);
$topics = implode('","', $topicsArray);
$resources = "select * from resources where
stage LIKE '%".$stage."%'
AND format IN(".$formats.") AND topic IN(\"".$topics."\") ";
By adding the " before and after each , when you implode each array, your array would become e.g.
video","blogs","articles
So, we need to add the " to the beginning and end of each IN list. This will make the final query like:
select * from resources where
stage LIKE '%".$stage."%'
AND format IN("video","blogs","articles") AND ...
I think this would do it. This also will resolve the injection hole by using prepared statements.
$query = 'select * from resources where ';
if(!empty($_POST['formats'])){
foreach($_POST['formats'] as $key => $format) {
$query .= 'stage LIKE :stage' . $key . ' or ';
$execute[':stage' . $key] = '%' . trim($format) . '%';
}
}
if(!empty($_POST['topics'])){
foreach($_POST['topics'] as $key => $topic) {
$query .= 'topic LIKE :topic' . $key . ' or ';
$execute[':topic' . $key] = '%' . trim($topic) . '%';
}
}
$query = rtrim($query, ' or ');
if(!empty($execute)) {
echo $query;
print_r($execute);
//$stmt = $mysqli->prepare($query);
//$stmt->execute($execute);
} else {
echo 'You must search for something';
}
Gives you a query of
select * from resources where stage LIKE :stage0 or stage LIKE :stage1 or topic LIKE :topic0 or topic LIKE :topic1 or topic LIKE :topic2 or topic LIKE :topic3
and bound values of:
Array
(
[:stage0] => %test%
[:stage1] => %test1%
[:topic0] => %value1%
[:topic1] => %value2%
[:topic2] => %value3%
[:topic3] => %value4%
)
Here's the initial code I had for when I thought the data was paired..
foreach($formats as $key => $format) {
$topic = $topics[$key];
$query .= '(stage LIKE :stage' . $key . ' and topic LIKE :topic' . $key . ') or ';
$execute[':stage' . $key] = '%' . trim($format) . '%';
$execute[':topic' . $key] = '%' . trim($topic) . '%';
}
A few links on prepared statements:
http://php.net/manual/en/mysqli.quickstart.prepared-statements.php
http://php.net/manual/en/mysqli.prepare.php
http://php.net/manual/en/mysqli-stmt.execute.php
Related
I have this array:
Array
(
[users] => Array
(
[0] => Array
(
[column] => email
[value] => fskdjhfkjf#mai.com
)
[1] => Array
(
[column] => nickname
[value] => dpucci
)
)
[social] => Array
(
[0] => Array
(
[column] => user_id
[value] => opweirpor
)
)
)
Starting from this array I'll have to build a string that will look like this:
insert(users, array(email=>fskdjhfkjf#mai.com,nickname=>dpucci)
And another like this:
insert(social, array(user_id=>opweirpor)
This is what I am doing:
foreach ($tables as $table => $queries) {
foreach ($queries as $query) {
$insert .= $query['column'] . '=>' . $query['value'] . ',';
}
echo 'insert(' . $table . ', array(' . $insert . ')';
}
The problem is that the result I am getting is the following:
insert(users, array(email=>fskdjhfkjf#mai.com,nickname=>dpucci)
and:
insert(social, array(email=>fskdjhfkjf#mai.com, nickname=>dpucci, user_id=>opweirpor)
This is because the variable $insert is incremented each new loop and it is adding ALL the results instead that only the ones I need for each $tables loop.
How can I achieve the expected result?
Because you keep appending your string to the same $insert in the inner loop, which is ran many times. Just clear the insert variable after you have finished with it, i.e. after your inner loop. (Untested)
foreach ($tables as $table => $queries) {
foreach ($queries as $query) {
$insert .= $query['column'] . '=>' . $query['value'] . ',';
}
echo 'insert(' . $table . ', array(' . $insert . ')';
// add this line
$insert = "";
}
or, put it before the inner foreach loop, which has an advantage to ensure $insert is not polluted with previous codes or otherwise uninitialized giving PHP warnings.
foreach ($tables as $table => $queries) {
// add this line
$insert = "";
foreach ($queries as $query) {
$insert .= $query['column'] . '=>' . $query['value'] . ',';
}
echo 'insert(' . $table . ', array(' . $insert . ')';
}
However, your code actually creates
insert(users, array(email=>fskdjhfkjf#mai.com,nickname=>dpucci,)
Note the comma after dupcci. Which I don't think is what you want. To fix this, simply remove the trailing comma with substr:
foreach ($tables as $table => $queries) {
// add this line
$insert = "";
foreach ($queries as $query) {
$insert .= $query['column'] . '=>' . $query['value'] . ',';
}
// add one more line here
$insert = substr($insert, 0, -1);
echo 'insert(' . $table . ', array(' . $insert . ')';
}
Also, check your desired output. It seems that the brackets are not balanced and the strings are unquoted. Are you sure it is what you want?
Reset the variable $insert.
foreach ($tables as $table => $queries) {
$insert = '';
foreach ($queries as $query) {
$insert .= $query['column'] . '=>' . $query['value'] . ',';
}
echo 'insert(' . $table . ', array(' . $insert . ')';
}
I want to update multiple rows in the database with codeigniters update_batch() function.
But the field specified in the where should also be changed.
The following code should make it clear:
$set = array(
array(
'token' => '65787131678754',
'device' => 'none',
'new_token_value' => ''
),
array(
'token' => '75798451315464',
'device' => 'none',
'new_token_value' => ''
)
);
$this->db->update_batch(TBL_NAME, $set, 'token');
Tokens specified in token should be updated with device to 'none' and the token itself should be set to empty string ''.
Is this possible with update_batch() function?
In sql I would write something like
UPDATE TBL_NAME
SET token='', device='none'
WHERE token='65787131678754'
for one update but this is not practicable for multiple, so I want to use the update_batch() function.
I created a helper function mostly identical to the codeigniter batch_update() function.
But with the ability to update the index itself. The new value is defined by index_update_key.
function update_batch($db, $table = '', $set = NULL, $index = NULL, $index_update_key = '') {
if ($table === '' || is_null($set) || is_null($index) || !is_array($set)) {
return FALSE;
}
$sql = 'UPDATE ' . $db->protect_identifiers($table) . ' SET ';
$ids = $when = array();
$cases = '';
//generate the WHEN statements from the set array
foreach ($set as $key => $val) {
$ids[] = $val[$index];
foreach (array_keys($val) as $field) {
if ($field != $index && $field != $index_update_key) {
$when[$field][] = 'WHEN ' . $db->protect_identifiers($index)
. ' = ' . $db->escape($val[$index]) . ' THEN ' . $db->escape($val[$field]);
} elseif ($field == $index) {
//if index should also be updated use the new value specified by index_update_key
$when[$field][] = 'WHEN ' . $db->protect_identifiers($index)
. ' = ' . $db->escape($val[$index]) . ' THEN ' . $db->escape($val[$index_update_key]);
}
}
}
//generate the case statements with the keys and values from the when array
foreach ($when as $k => $v) {
$cases .= "\n" . $db->protect_identifiers($k) . ' = CASE ' . "\n";
foreach ($v as $row) {
$cases .= $row . "\n";
}
$cases .= 'ELSE ' . $k . ' END, ';
}
$sql .= substr($cases, 0, -2) . "\n"; //remove the comma of the last case
$sql .= ' WHERE ' . $index . ' IN (' . implode(',', $ids) . ')';
return $db->query($sql);
}
Now I can do the following
$set = array(
array(
'token' => '657871316787544',
'device' => 'none',
'new_token_value' => ''
),
array(
'token' => '757984513154644',
'device' => 'none',
'new_token_value' => ''
)
);
update_batch($this->db, 'table_name', $set, 'token', 'new_token_value');
and the sql output is
UPDATE `b2c` SET
`token` = CASE
WHEN `token` = '657871316787544' THEN ''
WHEN `token` = '757984513154644' THEN ''
ELSE token END,
`device` = CASE
WHEN `token` = '657871316787544' THEN 'none'
WHEN `token` = '757984513154644' THEN 'none'
ELSE device END
WHERE token IN (657871316787544,757984513154644)
$this->db->where('option1', $option1);<br/>
$this->db->update_batch('table_name', $data, 'option2');
I want to take an associative array and parse that to put into the SET part of an UPDATE query:
My call with the associative array:
$this->ccQuery( 'emails', array('user_id' => $id, 'email_address' => $request->email) );
function ccQuery( $t, $a, $id=null )
{
foreach($a as $key=>$value)
{
$setfields[] = $key . "='" . $value . "'";
}
$setfields = implode(', ', $setfields);
$testquery2 = 'UPDATE mytable_'.$t.' SET ' .$setfields. ' WHERE user_id="'.$user_id;
...
}
setfields is empty. What am I doing wrong?
Maybe something like:
...
$testquery2 = "UPDATE mytable_"
foreach($a as $key=>$value)
{
$testquery2 = $testquery2 ."$t SET '$value' WHERE user_id= '$id'";
}
...
Is there any way to make the below-given code reusable for different tables, e.g. using foreach? So, how to send and use arrays of column names and values? Any example is highly appreciated.
<?php
include_once 'include/DatabaseConnector.php';
if(isset($_POST['flightNum'])) {
$flightNum=$_POST['flightNum'];
$from=$_POST['from'];
$STADate=$_POST['STADate'];
$query = 'UPDATE flightschedule
SET frm="'.$from.'",STADate="'.$STADate.'"
WHERE flightNum="'.$flightNum.'"';
DatabaseConnector::ExecuteQuery($query);
echo '1';
} else {
echo '0';
}
?>
UPDATE: What if I don't know column names apriori? How to create flexible UPDATE statement?
you can convert your code into a reusable function. for example.
function updateDB($tableName, $flightNum, $from, $STADate) {
include_once 'include/DatabaseConnector.php';
$query = 'UPDATE ' . $tableName
SET frm="'.$from.'",STADate="'.$STADate.'"
WHERE flightNum="'.$flightNum.'"';
$execute = DatabaseConnector::ExecuteQuery($query);
return $execute;
}
and to use it
if(isset($_POST['flightNum']) {
$update = updateDB('flightschedule', $_POST['flightNum'], $_POST['from'], $_POST['STADate']);
echo $update;
}
Update:
I want to send an array of column names to the function 'updateDB'.
Let's say these are column names for SET and WHERE parts of UPDATE
statement. And then I could use FOREACH, but I need some example for
this.
this is how you can do it.
function updateDB($tableName, $columns, $where) {
//do some validation here to check if proper data is being passed like
if(!isarray($columns)) {
throw new Exception('argument two $columns should be an associative array');
}
include_once 'include/DatabaseConnector.php';
$query = 'UPDATE ' . $tableName;
foreach($columns as $column => $data) {
$query .= ' SET ' . $column . ' = ' . $data . ', ';
}
//remove last comma from the update query string
$query = substr($query, 0, -1);
$query .= ' WHERE ' . $where['column'] . ' = ' . $where['value'];
$execute = DatabaseConnector::ExecuteQuery($query);
return $execute;
}
and to use it.
if(isset($_POST['flightNum']) {
$columns = array(
'frm' => $_POST['frm'],
'STADate' => $_POST['STADate']
);
$where = array(
'column'=> 'flightNum',
'value' => $_POST['flightNum']
);
$update = updateDB('flightschedule', $columns, $where);
echo $update;
}
Something like this should work:
function generateUpdateQuery($table, $fields, $where) {
$updateFields = array();
foreach ($fields as $k => $v) {
$updateFields[] = $k.' = \''.$v.'\'';
}
$sqlQuery = 'UPDATE '.$table.
' SET '.implode(', ', $updateFields).
' WHERE '.implode(' AND ', $where);
return $sqlQuery;
}
echo generateUpdateQuery('table_name',
array(
'field_a' => '10',
'field_b' => 'hello',
'field_c' => 'world'),
array(
'id=12',
'datetime > NOW()')
);
Keep in mind that this is a simple example without any security check. Something like PDO would be recommended.
Moreover, if you're looking for something more robust and flexible you should give a look to a ORM system, like Doctrine
I want to generate the array $result_array. There is no error at the page, but not works!
that not works !
//BOF: Result Array
$result_array = '';
$result_array .= '"messages" => "' . $errors .'",';
$result_array .= '"this_addr_type" => "' . (int)$_REQUEST['edit'] .'",';
if (ACCOUNT_GENDER == 'true') {
$result_array .= '"gender_male" => "' . $male .'",';
$result_array .= '"gender_female" => "' . $female .'",';
}
$result_array .= '"firstname" => "' . $entry['entry_firstname'] .'",';
$result_array .= '"lastname" => "' . $entry['entry_lastname'] .'",';
if (ACCOUNT_COMPANY == 'true') {
$result_array .= '"company" => "' . $entry['entry_company'] .'",';
}
$result_array .= '"street_address" => "' . $entry['entry_street_address'] .'",';
if (ACCOUNT_SUBURB == 'true') {
$result_array .= '"suburb" => "' . $entry['entry_suburb'] .'",';
}
$result_array .= '"postcode" => "' . $entry['entry_postcode'] .'",';
$result_array .= '"city" => "' . $entry['entry_city'] .'",';
if (ACCOUNT_STATE == 'true') {
$result_array .= '"state" => "' . $entry['entry_state'] .'",';
}
$result_array .= '"country" => "' . $entry['entry_country_id'] .'"';
//EOF: Result Array
$_RESULT = array($result_array);
that works
$_RESULT = array(
"this_addr_type" => (int)$_REQUEST['edit'],
"gender_male" => $male,
"gender_female" => $female,
"firstname" => $entry["entry_firstname"],
"lastname" => $entry["entry_lastname"],
"company" => $entry["entry_company"],
"street_address" => $entry["entry_street_address"],
"suburb" => $entry["entry_suburb"],
"postcode" => $entry["entry_postcode"],
"city" => $entry["entry_city"],
"state" => $entry["entry_state"],
"country" => $entry["entry_country_id"]
);
Because you're trying to get PHP to treat a string as code. My question would be "why" - but if you MUST do it, you're looking for eval : http://php.net/manual/en/function.eval.php
// untested
$_RESULT = eval("return " . "array($result_array)" . ";");
Will probably give you the result you're loking for.
The real qusetion is why aren't you just doing this:
if (ACCOUNT_GENDER == 'true') {
$result_array['gender_male'] = $male;
$result_array['gender_female'] = $female;
}
PHP doesn't work that way. A string is not always equivalent to the actual thing you want to use.
The first example just creates an array with one really large string. The "=>"s are included in that string and are not interpreted to create a new array element. Look at the second example. Are the "=>"s there inside of quotes?
You already answered your own question. The first cannot work. You are just creating a long string and then stick that string as single element into an array.
But looking at your two examples I suppose you're wanting to do something like this:
$result_array = array();
if($somecondition) {
$result_array = array_merge($result_array, array("entry1" => "data1", "entry2" => "data2"));
}
if($someothercondition) {
$result_array = array_merge($result_array, array("other_entry" => "more_data"));
}
$_RESULT = $result_array;
You can create PHP array like this:
$array = array();
or
$array[] = 'whatever';
But in your code, you are using:
$result_array .= '"messages" => "' . $errors .'",';
Which is not how to create PHP array.
//BOF: Result Array
$_RESULT = array();
$_RESULT["messages"] = $errors;
$_RESULT["this_addr_type"] = (int)$_REQUEST['edit'];
if (ACCOUNT_GENDER == 'true') {
$_RESULT["gender_male"] = $male;
$_RESULT["gender_female"] = $female;
}
$_RESULT["firstname"] = $entry['entry_firstname'];
$_RESULT["lastname"] = $entry['entry_lastname'];
if (ACCOUNT_COMPANY == 'true') {
$_RESULT["company"] = $entry['entry_company'];
}
$_RESULT["street_address"] = $entry['entry_street_address'];
if (ACCOUNT_SUBURB == 'true') {
$_RESULT["suburb"] = $entry['entry_suburb'];
}
$_RESULT["postcode"] = $entry['entry_postcode'];
$_RESULT["city"] = $entry['entry_city'];
if (ACCOUNT_STATE == 'true') {
$_RESULT["state"] = $entry['entry_state'];
}
$_RESULT["country"] = $entry['entry_country_id'];
//EOF: Result Array
Why are you trying to do this? Are you storing the array in text somewhere? If it doesn't need to be human readable, you should look at:
http://php.net/manual/en/function.serialize.php
http://php.net/manual/en/function.unserialize.php
// $_RESULT as a string
$str = serialize($_RESULT);
// Back as an array
$arr = unserialize($str);