I am developing a database-driven website using Laravel. Now I am having a problem with updating database. I want to run bulk update. Normally I run like this.
$data = [
[
'col_1'=>$value1
],
[
'col_1'=>$value2
],
[
'col_1'=>$value3
],
[
'col_1'=>$value4
]
];
MyTableObject::update($data)->where('col_2'=>$col_2_val);
As you can see in the above code, where clause is checking for only one condition for all rows that are to be updated. But what I want is that I want the different where clause condition for each row or query. To use foreach and run query for each row, it will be time-consuming because I have to update a lot of rows. To demonstrate it, it will be something like this.
$data = [
[
'col_1'=>$value1,
'col_2'=>$where_value_1 // This is not the column to be updated. That is for where clause.
],
[
'col_1'=>$value2,
'col_2'=>$where_value_2 // This is not the column to be updated. That is for where clause.
],
[
'col_1'=>$value3,
'col_2'=>$where_value_3
],
[
'col_1'=>$value4,
'col_2'=>$where_value_4
]
];
MyTableObject::update($data)->where('where_col_name'=>'col_2');
I found this link, but the answers are not clear and complete. Is it possible to do it in Laravel, and how can I do it?
If I'm understanding this correctly, col_1 is the value you wish to use in update and col_2 is the value you're querying against. Try the following (may need some adjustments)
collect($data)->each(function(array $row) {
MyTableObject::where('where_col_name', $row['col_2'])->update(['col_1' => $row['col_1']]);
});
Here is the batch update function which I wrote to use in my Laravel projects. Its first parameter is the table name string, second is the key name string on which you want to update the row or rows and mostly it will be the 'id', the third parameter is the data array in the format:
array(
array(
'id' => 1,
'col_1_name' => 'col_1_val',
'col_2_name' => 'col_2_val',
//.....
),
array(
'id' => 2,
'col_1_name' => 'col_1_val',
'col_2_name' => 'col_2_val',
//.....
),
//.....
);
Function:
private function custom_batch_update(string $table_name = '', string $key = '', Array $update_arr = array()) {
if(!$table_name || !$key || !$update_arr){
return false;
}
$update_keys = array_keys($update_arr[0]);
$update_keys_count = count($update_keys);
for ($i = 0; $i < $update_keys_count; $i++) {
$key_name = $update_keys[$i];
if($key === $key_name){
continue;
}
$when_{$key_name} = $key_name . ' = CASE';
}
$length = count($update_arr);
$index = 0;
$query_str = 'UPDATE ' . $table_name . ' SET ';
$when_str = '';
$where_str = ' WHERE ' . $key . ' IN(';
while ($index < $length) {
$when_str = " WHEN $key = '{$update_arr[$index][$key]}' THEN";
$where_str .= "'{$update_arr[$index][$key]}',";
for ($i = 0; $i < $update_keys_count; $i++) {
$key_name = $update_keys[$i];
if($key === $key_name){
continue;
}
$when_{$key_name} .= $when_str . " '{$update_arr[$index][$key_name]}'";
}
$index++;
}
for ($i = 0; $i < $update_keys_count; $i++) {
$key_name = $update_keys[$i];
if($key === $key_name){
continue;
}
$when_{$key_name} .= ' ELSE ' . $key_name . ' END, ';
$query_str .= $when_{$key_name};
}
$query_str = rtrim($query_str, ', ');
$where_str = rtrim($where_str, ',') . ')';
$query_str .= $where_str;
$affected = DB::update($query_str);
return $affected;
}
It will produce and execute the query string like this:
UPDATE table_name SET col_1_name = CASE
WHEN id = '1' THEN 'col_1_value'
WHEN id = '2' THEN 'col_1_value'
ELSE col_1_name END,
col_2_name = CASE
WHEN id = '1' THEN 'col_2_value'
WHEN id = '2' THEN 'col_2_value'
ELSE col_2_name END
WHERE id IN('1','2')
Related
I'm working with an API to retrieve records based on user input.
There are filters and filter groups that will be concatenated, however, I do not want the last AND or OR in the nested for each loop to be concatenated to the string.
I would like to have an if statement that looks for the last item in the nested foreach loop and concatenates a different string to the end, like this:
if($i == $lastItem) {
$conditions .= 'WHERE ' . $type . ' = '. "'". $tag . "'";
}
else {
$conditions .= 'WHERE ' . $type . ' = '. "'". $tag . "'" . ' ' . $condition . " ";
}
What is the best practice for finding the last item of a nested for each loop using PHP?
Here is the reference code:
$conditions = "";
$filters = "";
foreach($request->filters as $key=>$filter) {
foreach($filter as $item) {
if($item['tag']) {
$type = $item['code'];
$tag = $item['tag'];
$condition = $item['condition'];
$conditions .= 'WHERE ' . $type . ' = '. "'". $tag . "'" . ' ' . $condition . " ";
}
}
$groupCondition = $request->conditions[$key]['condition'];
$filters .= '('.$conditions.') ' . $groupCondition . " ";
}
Here is an example of a request, the two objects are combined in the foreach loop:
filter: {
0 {
0 {
code: 'gl_code',
condition: 'OR',
tag: '10-140-4700-0401'
}
1 {
0 {
code: 'ty_letter_no',
condition: 'AND',
tag: 'AM123'
},
1 {
code: 'gl_code',
condition: 'OR',
tag: '10-140-4700-0401'
}
}
groupConditions: {
0 {
condition: 'OR'
}
1 {
condition: 'AND'
}
}
Here an example of the current output:
"(WHERE ty_letter_no = 'AM123' AND )
OR
(WHERE ty_letter_no = 'AM123' AND WHERE solicit_code = '19-10NL' AND WHERE ty_letter_no = 'AU' AND )
AND
(WHERE ty_letter_no = 'AM123' AND WHERE solicit_code = '19-10NL' AND WHERE ty_letter_no = 'AU' AND WHERE solicit_code = '19-04HRGOLF' AND )
AND "
I would like it to output:
"(WHERE ty_letter_no = 'AM123')
OR
(WHERE ty_letter_no = 'AM123' AND WHERE solicit_code = '19-10NL' AND WHERE ty_letter_no = 'AU')
AND
(WHERE ty_letter_no = 'AM123' AND WHERE solicit_code = '19-10NL' AND WHERE ty_letter_no = 'AU' AND WHERE solicit_code = '19-04HRGOLF')"
I shall work under these assumptions:
the request comes from a "LEGO model" builder, so that the condition entry is always present, but sometimes not significant (specifically, when it is the last of its group).
the resulting code has to be a valid SQL condition.
the string values do not need escaping and have been proofed against SQL injection.
If this is so, then you can use a limited state machine to achieve your result:
$completeCondition = '';
$groupjoin = '';
foreach ($request->filter as $index => $conditions) {
$conditionjoin = '';
$partialCondition = '';
foreach ($conditions as $triplet) {
$partialCondition .= "{$conditionjoin}{$triplet->code} = '{$triplet->tag}'";
$conditionjoin = " {$triplet->condition} ";
}
$completeCondition .= "{$groupjoin}({$partialCondition})";
$groupjoin = " {$request->groupConditions[$index]->condition} ";
}
if (!empty($completeCondition)) {
$completeCondition = " WHERE {$completeCondition}";
}
Using this version of your request,
$request = json_decode('{
"filter": [
[
{ "code": "gl_code", "condition": "OR", "tag": "10-140-4700-0401" }
],
[
{ "code": "ty_letter_no", "condition": "AND", "tag": "AM123" },
{ "code": "gl_code", "condition": "OR", "tag": "10-140-4700-0401" }
]
],
"groupConditions": [ { "condition": "OR" }, { "condition": "AND" } ]
}');
the result is the following, valid SQL:
WHERE (gl_code = '10-140-4700-0401')
OR (ty_letter_no = 'AM123' AND gl_code = '10-140-4700-0401')
(if the destination language is not SQL then the code can be changed slightly, of course).
a more refined result (PDO support)
Normally you do not want to include the request strings in your SQL code as is, because this allows the user to arbitrarily alter the SQL code you will execute. For example if I were to send along a tag of
'||SLEEP(60)||'
the code above would happily encode it as, say, gl_code = ''||SLEEP(60)||'', which is a valid SQL request and will be executed, halting your thread for sixty seconds. If I know you're using MySQL, I can perform some tricks with the LOCK() function and try to exhaust the internal metadata memory. If you're really unlucky and composite queries have not been disabled (they usually are!), then I very much fear I can own your SQL server. Even if they are, there are several dirty tricks that can be done with LEFT JOINs, UNIONs and SELECT 'code' INTO DUMPFILE '/var/www/nasty.php', and not all installations are hardened against all of them.
To avoid this we use PDO and SQL parameterization. This requires sending the query in two parts, a prepared query like
`...AND gl_code = :value1`
and a binding list containing ...':value1' => 'AL-1234-56'....
$completeCondition = '';
$groupjoin = '';
$bindingList = array();
foreach ($request->filter as $index => $conditions) {
$conditionjoin = '';
$partialCondition = '';
foreach ($conditions as $triplet) {
$bind = ':b' . count($bindingList);
$partialCondition .= "{$conditionjoin}{$triplet->code} = {$bind}";
$conditionjoin = " {$triplet->condition} ";
$bindingList[$bind] = $triplet->tag;
}
$completeCondition .= "{$groupjoin}({$partialCondition})";
$groupjoin = " {$request->groupConditions[$index]->condition} ";
}
if (!empty($completeCondition)) {
$completeCondition = " WHERE {$completeCondition}";
}
// Now we could safely do (supposing $pdo is my PDO DB object)
$stmt = $pdo->prepare($completeCondition);
$stmt->execute($bindingList);
while ($row = $stmt->fetch()) {
// Do something with the row.
}
Just an idea: you can always understand if the current iteration is the first (by using a flag).
In this way, you can:
skip the first iteration
save at each iteration the current item, to be used at the next iteration
Update the query at the Nth iteration appending information related to the (N-1)th iteration
Outside the loop append the information related to the last iteration applying the modifications you need
Something like
$conditions = "";
$filters = "";
$isFirst = true;
foreach($request->filters as $key=>$filter) {
foreach($filter as $item) {
if($isFirst)
{
$isFirst = false;
}
else
{ if($previousItem['tag']) {
$type = $previousItem['code'];
$tag = $previousItem['tag'];
$condition = $previousItem['condition'];
$conditions .= 'WHERE ' . $type . ' = '. "'". $tag . "'" . ' ' . $condition . " ";
}
}
$previousItem = $item;
}
$groupCondition = $request->conditions[$key]['condition'];
$filters .= '('.$conditions.') ' . $groupCondition . " ";
}
if(isset($previousItem))
{
$type = $previousItem['code'];
$tag = $previousItem['tag'];
$conditions .= 'WHERE ' . $type . ' = '. "'". $tag . "'"
}
You could try adapting this solution to your needs.
To strictly answer your question, can you see if you're working on the last iteration by checking the current iteration (in your case, the key) against the length (count()) of the array. You can avoid doing something on that iteration by making sure that if( $iteration < $length - 1 ), then you're not in the last iteration. If you want to check that you are in the last, if( $iteration == $length - 1 ).
To address the larger scope of the question:
When programmatically building queries, I've often found it easier to make use of the WHERE 1=1 to start, since it allows you to implode() an array using AND as a glue (and some DBMS will not even parse the 1=1).
$filters = "";
$length = count($request->filters);
foreach($request->filters as $key => $filter) {
$conditions = array( "WHERE 1=1" );
foreach($filter as $item){
$tag = $item['tag'];
$type = $item['code'];
$condition = $item['condition'];
$conditions[] = "{$type} = '{$tag}'";
}
// Build the conditions
$filters .= sprintf( '(%s)', implode(' AND ', $conditions ) );
// If this isn't the last item, add the group conditions
$filters .= ( $key < $length-1 ) ? " {$request->conditions[$key]['condition']} " : '';
}
The last line checks to make sure it's not the last item (by making sure the current index is less than the $length-1 before appending that last condition. Using the above, you'd end up with a filter like:
(WHERE 1=1 AND gl_code = '10-140-4700-0401') OR (WHERE 1=1 AND ty_letter_no = 'AM123' AND gl_code = '10-140-4700-0401')
If the service you're sending that to doesn't like the 1=1 (it shouldn't have any effect at all, but if it does) you can do $filters = str_replace( '1=1 AND ', '', $filters ); at the end.
(WHERE gl_code = '10-140-4700-0401') OR (WHERE ty_letter_no = 'AM123' AND gl_code = '10-140-4700-0401')
Also note that this doesn't output strictly valid SQL, just the format you requested (I'm assuming the service wants the filters in this format for their own reasons)
Here's a quick example
I use CodeIgniter, and when an insert_batch does not fully work (number of items inserted different from the number of items given), I have to do the inserts again, using insert ignore to maximize the number that goes through the process without having errors for existing ones.
When I use this method, the kind of data I'm inserting does not need strict compliance between the number of items given, and the number put in the database. Maximize is the way.
What would be the correct way of a) using insert_batch as much as possible b) when it fails, using a workaround, while minimizing the number of unnecessary requests?
Thanks
The Correct way of inserting data using insert_batch is :
CI_Controller :
public function add_monthly_record()
{
$date = $this->input->post('date');
$due_date = $this->input->post('due_date');
$billing_date = $this->input->post('billing_date');
$total_area = $this->input->post('total_area');
$comp_id = $this->input->post('comp_id');
$unit_id = $this->input->post('unit_id');
$percent = $this->input->post('percent');
$unit_consumed = $this->input->post('unit_consumed');
$per_unit = $this->input->post('per_unit');
$actual_amount = $this->input->post('actual_amount');
$subsidies_from_itb = $this->input->post('subsidies_from_itb');
$subsidies = $this->input->post('subsidies');
$data = array();
foreach ($unit_id as $id => $name) {
$data[] = array(
'date' => $date,
'comp_id' => $comp_id,
'due_date' => $due_date,
'billing_date' => $billing_date,
'total_area' => $total_area,
'unit_id' => $unit_id[$id],
'percent' =>$percent[$id],
'unit_consumed' => $unit_consumed[$id],
'per_unit' => $per_unit[$id],
'actual_amount' => $actual_amount[$id],
'subsidies_from_itb' => $subsidies_from_itb[$id],
'subsidies' => $subsidies[$id],
);
};
$result = $this->Companies_records->add_monthly_record($data);
//return from model
$total_affected_rows = $result[1];
$first_insert_id = $result[0];
//using last id
if ($total_affected_rows) {
$count = $total_affected_rows - 1;
for ($x = 0; $x <= $count; $x++) {
$id = $first_insert_id + $x;
$invoice = 'EBR' . date('m') . '/' . date('y') . '/' . str_pad($id, 6, '0', STR_PAD_LEFT);
$field = array(
'invoice_no' => $invoice,
);
$this->Companies_records->add_monthly_record_update($field,$id);
}
}
echo json_encode($result);
}
CI_Model :
public function add_monthly_record($data)
{
$this->db->insert_batch('monthly_record', $data);
$first_insert_id = $this->db->insert_id();
$total_affected_rows = $this->db->affected_rows();
return [$first_insert_id, $total_affected_rows];
}
AS #q81 mentioned, you would split the batches (as you see fit or depending on system resources) like this:
$insert_batch = array();
$maximum_items = 100;
$i = 1;
while ($condition == true) {
// code to add data into $insert_batch
// ...
// insert the batch every n items
if ($i == $maximum_items) {
$this->db->insert_batch('table', $insert_batch); // insert the batch
$insert_batch = array(); // empty batch array
$i = 0;
}
$i++;
}
// the last $insert_batch
if ($insert_batch) {
$this->db->insert_batch('table', $insert_batch);
}
Edit:
while insert batch already splits the batches, the reason why you have "number of items inserted different from the number of items given" might be because the allowed memory size is reached. this happened to me too many times.
Hi so I have an insert statement which works well, but need to create a separate update function which uses array keys and array values, which would be quite like the insert function but updates.
I have this for my insert
$sql = "INSERT INTO $tablename (".implode(",", array_keys($DATA).")" . " DATA ('".implode("','",array_values($DATA))."')";
connect()->query($sql);
This is what I have for my update so far but am stuck with it,
<?php
function updatethis (array $id, array $values, $tablename)
{
$sql = "UPDATE $tablename SET (".implode(",", array_keys($DATA)).")" . " DATA ('".implode("','",array_values($DATA))."')";
dbconnect()->query($sql);
}
?>
Therefore I would like help on the update feature please .
So I am getting an error with the UPDATE syntax
This is the part i am struggling with, i cna give further explanation, but i must have put in the wrong syntax to update the database after i click edit on the index page it calls the function just the syntax is incorrect.
also its php to mySQL
index page for PHP updatee fucntion
{
$values = array();
$idValues = array($idColumn => $id);
foreach($_POST as $key => $value)
{
if(!empty($value) && ($value != "Submit"))
{
$values[$key] = $value;
}
}
$result = update($idValues, $values, $tableName);
}
Edit: Error I am getting
edit has not been successfull from below
if(isset($_POST['Submit']))
{
if($result>0)
{
echo 'Edit has been successful. Return to index page';
}
else
{
echo 'Edit has not been successful.';
}
}
My code
function updateAll(array $id, array $values, $tablename)
{
$sIDColumn = key($id);
$sIDValue = current($id);
$arrayValues = $values;
array_walk($values, function(&$value, $key){
$value = "{$key} = '{$value}'";
});
$sUpdate = implode(", ", array_values($values));
$sql = "UPDATE {$tablename} SET {$sUpdate} WHERE {$sIDColumn} = '{$sIDValue}'";
connect()->query($sql);
}
My aim: takes the input of the unique identifier of the row to be edited as an array of 1 then the value plus the name of the column representing the primary key, an array containing the values indexed by the column names as well as a string representing the table name useing array_keys and array_vaules like th insert but to update
You cannot UPDATE in the same way of INSERT. It should be like this :
$valueSets = array();
foreach($values as $key => $value) {
$valueSets[] = $key . " = '" . $value . "'";
}
$conditionSets = array();
foreach($id as $key => $value) {
$conditionSets[] = $key . " = '" . $value . "'";
}
$sql = "UPDATE $tablename SET ". join(",",$valueSets) . " WHERE " . join(" AND ", $conditionSets);
See details here http://dev.mysql.com/doc/refman/5.7/en/update.html
I believe the pattern you are using is incorrect?
UPDATE table SET (rows) DATA ('values');
I think updates look more like this:
UPDATE table SET row1 = 'value1', row2 = 'value2';
In which case, this may be closer to what you are looking for.
function updatethis(array $id, array $values, $tablename)
{
$sIDColumn = key($id);
$sIDValue = current($id);
$arrayValues = $values;
array_walk($values, function(&$value, $key){
$value = "{$key} = '{$value}'";
});
$sUpdate = implode(", ", array_values($values));
$sql = "UPDATE {$tablename} SET {$sUpdate} WHERE {$sIDColumn} = '{$sIDValue}'";
dbconnect()->query($sql);
}
Using it, I get this query:
$testArray = array(
"id" => 19,
"username" => "test"
);
updatethis(array("id" => 9), $testArray, "users");
UPDATE users SET id = '19', username = 'test' WHERE id = '9'
I hope this at least helps but when it comes to databases, I only know MySQL and it is possible you are using another language.
I think you can try something like this :
$champs : Array of fields to update
$valeurs : Array of value to update fields
$conditions : Array of conditions
protected function modify($table,$champs,$valeurs,$conditions){
$Requete = "UPDATE ".$table." SET ";
$nbChamps = count($champs);
$nbValeurs = count($valeurs);
if($nbChamps == $nbValeurs){
for($i = 0; $i < $nbChamps ; $i++){
if($i < ($nbChamps - 1)){
if(is_numeric($valeurs[$i]))
$Requete = $Requete.$champs[$i]." = ".$valeurs[$i].",";
else
$Requete = $Requete.$champs[$i]." = '".$valeurs[$i]."',";
}
else
if(is_numeric($valeurs[$i]))
$Requete = $Requete.$champs[$i]." = ".$valeurs[$i]." ";
else
$Requete = $Requete.$champs[$i]." = '".$valeurs[$i]."' ";
}
$Requete = $Requete.$this->genereConditions($conditions);
$this->db->query($Requete);
}
else
throw new Exception("Le nombre de champs n'est pas identique au nombre de valeurs", 1);
}
private function genereConditions($conditions){
$condition = "WHERE ";
for($i = 0 ; $i < count($conditions); $i++){
if($i < (count($conditions)) - 1)
$condition = $condition.$conditions[$i]." AND ";
else
$condition = $condition.$conditions[$i];
}
return $condition;
}
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'm using the following code to validate a 'set' of input fields. 4 fields per set (width/height/length/weight). If a set of my input fields are empty then it won't display that row of data in my final $all variable.
Here is a previous topic on the subject: Removing Data from Variable if Input Fields incomplete - PHP - this works great.
However, this time I am using "Placeholder" text (input field value attribute) and therefore I need my PHP to check whether that placeholder value exists.
Here is my Pseudo Code, however I'm unsure how to achieve with regular PHP:
if ((pNUM-VALUEheight = "Height (cm)" OR pNUM-VALUEwidth = "Width (cm)" OR pNUM-VALUElength = "Length (cm)" OR pNUM-VALUEweight = "Weight (kg)"))
Then
// Don't store in $all variable
Else
// Do store set of values in $all variable
End If
Here is my current PHP code:
...
$ierrors = array();
$all = '';
// Loop over the values 1 through 20
foreach( range( 1, 20) as $i)
{
// Create an array that stores all of the values for the current number
$values = array(
'p' . $i . 'height' => $_POST['p' . $i . 'height'],
'p' . $i . 'width' => $_POST['p' . $i . 'width'],
'p' . $i . 'length' => $_POST['p' . $i . 'length'],
'p' . $i . 'weight' => $_POST['p' . $i . 'weight']
);
// Assume all values are empty.
$allEmpty = true;
// Validate every value
foreach( $values as $key => $value)
{
if( empty($value))
$ierrors[] = "Value $key is not set";
else
$allEmpty = false;
// You can add more validation in here, such as:
if( !is_numeric( $value) )
$ierrors[] = "Value $key contains an invalid value '$value'";
}
// Join all of the values together to produce the desired output
if (!$allEmpty)
$all .= implode( '|', $values) . "\n\n";
}
...
Many thanks for any pointers here or please let me know if any clarity is needed.
Thank you
As you're using jQuery, I'd use a bit of JavaScript to clear the input fields on submit:
$('form').submit(function() {
$(this).find('input[type=text]').each(function() {
var domElement = $(this).get(0);
if (domElement.value == domElement.defaultValue) {
domElement.value = '';
}
});
});
Watch out for typos, didn't test.
You can then check in your PHP file for empty strings and don't have to explicitly state all the possible values (they might change slightly, after all):
if ($_POST['inputName'] == '')
OR
you could use a simple for loop:
for ($i = 0, $numFields = 20; $i <= $numFields; ++$i) {
if ($_POST['p' . $i . 'width'] != 'Width (cm)' && $_POST['p' . $i . 'height'] != 'Height (cm)') {
// add row to table
}
}
What about doing something like this with your HTML:
<input type="text" name="length[]">
<input type="text" name="width[]">
Then you can do something like this in PHP:
if(array_keys($_POST['length']) != array_keys($_POST['width']))
{
// Incomplete post
}
$all_keys = array_merge(array_keys($_POST['length']), array_keys($_POST['width']));
foreach($all_keys as $curr_key)
{
// $_POST['length'][$curr_key]
// $_POST['width'][$curr_key]
}
While using JS is good to validate information from the client before submission. You should always check your values server side as well.