Confused by how !empty() works in my if-condition - php

I'm confused by what counts as empty in this code logic. I have a variable amount of table rows (additional rows are dynamically inserted via ajax) that each accept four inputs. The logic I want is for a particular row - whose inputs are incomplete - to be unable to update a database:
if ((isset($_POST['_branch']) && !empty($_POST['_branch']))
&& (isset($_POST['_day']) && !empty($_POST['_day']))
&& (isset($_POST['_starttimepicker']) && !empty($_POST['_starttimepicker']))
&& (isset($_POST['_endtimepicker']) && !empty($_POST['_endtimepicker']))) {
$b_id = $_POST['_branch'];
$w_date = $_POST['_day'];
$s_time = $_POST['_starttimepicker'];
$e_time = $_POST['_endtimepicker'];
// ... rest of code comes here
}
The code snippet where the four inputs are handled:
<td>
<input class="form-control" type="text" id="_starttimepicker" name="_starttimepicker[]" placeholder="Enter Time" />
</td>
<td>
<input class="form-control" type="text" id="_endtimepicker" name="_endtimepicker[]" placeholder="Enter Time" />
</td>
When I have start time and end time "empty" (haven't interacted with them; the placeholder remains as "Enter Time"), the if-condition logic above still processes and the database is ultimately updated (with bad values). Even when I try to play around with the default value parameter (I have value = "" and "red"):
<td>
<input class="form-control" type="text" id="_starttimepicker" name="_starttimepicker[]" value="" placeholder="Enter Time" />
</td>
<td>
<input class="form-control" type="text" id="_endtimepicker" name="_endtimepicker[]" value="red" placeholder="Enter Time" />
</td>
The if logic still processes (also, the relevant database value where I had value="red" remains as "". I thought it would have taken the default value "red", so maybe I'm misunderstanding this).
What am I misunderstanding? Any advice?

I see that you use input arrays. To check empty form fields that are input arrays, you need more complicate than just empty().
Example HTML form:
<form method="post">
<input class="form-control" type="text" id="_starttimepicker" name="_starttimepicker[]" placeholder="Enter Time" />
<input class="form-control" type="text" id="_endtimepicker" name="_endtimepicker[]" placeholder="Enter Time" />
<button type="submit">Submit</button>
</form>
Here is PHP function to check it and how to use.
$_starttimepicker = ($_POST['_starttimepicker'] ?? []);
// in PHP older than 7.0 use (isset($_POST['_starttimepicker']) ? $_POST['_starttimepicker'] : []) instead.
$_endtimepicker = ($_POST['_endtimepicker'] ?? []);
/**
* Check if ANY fields are empty.
*
* #param array $fields The input form field, one by one.
* #return bool Return `true` if one of a form field is empty. Return `false` for otherwise.
*/
function isEmptyFields(...$fields)
{
$foundEmpty = false;
foreach ($fields as $field) {
if (is_array($field) && !empty($field)) {
foreach ($field as $index => $value) {
if (empty($value)) {
$foundEmpty = true;
break;
}
}
} else {
if (empty($field)) {
$foundEmpty = true;
break;
}
}
}
return $foundEmpty;
}
if (!isEmptyFields($_starttimepicker, $_endtimepicker)) {
// if all fields are NOT empty.
echo 'save your data.';
}
Tested submit the form by filled all fields, the result is in condition (save your data.) but if empty just one, it will not goes into if condition.

Related

My HTML form won't post the default values to my sql query unless I manually change at least one item on the form (including an option select)? [duplicate]

This question already has answers here:
mySQL UPDATE query returns "0 rows affected"
(11 answers)
Closed 9 days ago.
I have a simple html 5-field (plus 1 dropdown of option words), form where some dollar amounts are entered. A submit button has an action of a php page that prepares the stmnt to execute, performs a mysql UPDATE, sends me an SMS, etc.
There are default values, zeroes actually, that fill the form to start it out. They're just standard $variables.
The html input fields all have "value" that is an echoed php variable.
If you do not change at least ONE value (not all 5), there are no affected rows and the UPDATE query fails.
THIS INCLUDES SIMPLY CHANGING THE DROPDOWN ITEM VALUE.
Not only must a value be changed, but it cannot be cleared and re-entered as the default value. It must be different.
The form has a test function that strips characters and such before posting.
The post uses ternary operators to use a 0 if left empty, otherwise use what was entered.
I have tried it removing "required" in the html form.
I have tried removing the ternary operator (since a required input field can't be empty anyway).
I have tried leaving a field empty.
I don't get anything posted to the error log, as it just as affected rows = 0.
The form fields look like this:
<form action="proc.php" method="post" >
<fieldset>
<h2>input form</h2>
<b>November: $</b>
<input type="number" step="0.01" name="november" size="7" value="<?php echo $nov; ?>" required>
<b>December: $</b>
<input type="number" step="0.01" name="december" size="7" value="<?php echo $dec; ?>" required>
<b>January: $</b>
<input type="number" step="0.01" name="january" size="7" value="<?php echo $jan; ?>" required>
<b >February: $</b>
<input type="number" step="0.01" name="february" size="7" value="<?php echo $feb; ?>" required>
<b>March: $</b>
<input type="number" step="0.01" name="march" size="7" value="<?php echo $mar; ?>" required>
<input id="makechanges" class="makechanges" type="submit" value="submit" size ="50" name="submit">
</form>
This is the action php page that prepares and makes the query.
function test_input($data) {
$data = trim($data);
$data = stripslashes($data);
$data = htmlspecialchars($data);
return $data;
}
if ($_SERVER['REQUEST_METHOD'] == "POST") {
$novpil = test_input($_POST['november']);
$decpil = test_input($_POST['december']);
$janpil = test_input($_POST['january']);
$febpil = test_input($_POST['february']);
$marpil = test_input($_POST['march']);
}
$stmt = $connmember->prepare(" UPDATE smfqg_themes SET
`value` = CASE `variable`
WHEN 'cust_novpil' THEN ?
WHEN 'cust_decpil' THEN ?
WHEN 'cust_janpil' THEN ?
WHEN 'cust_febpil' THEN ?
WHEN 'cust_marpil' THEN ?
ELSE `value`
END
WHERE id_member = ? ");
$stmt->bind_param('sssssi', $novpil, $decpil, $janpil, $febpil, $marpil, $who);
$stmt->execute();
if ($stmt->affected_rows > 0) {
//echo 'GOOD' ;
// $greenbar = true;
sendsms($first, $last, $who);
header('Refresh: 3; URL=https://example.com/success.php');
} else {
echo 'something went wrong, standby:';
header('Refresh: 3; URL= https://example.com/return.php');
}
$stmt->close();
$connmember->close();
}
I have echoed the _post values on the action page to see what was brought over, and whether I leave the default values or use my own, they echo fine before the query runs.
I tried ternaries that tested for that default zero to be both a number or string. I also did a cast (to int and float) for the default values before they got put in the html form, since the default values come from a table as a string (even though just a 0). No luck.
It would seem that you must either change one field value OR simply change the dropdown to make the form work. Leaving all untouched won't work.
Empty(0) Evals as true, so no change is detected. You will have to either add another condition or use something else than empty()

How can I make some questions in a form required, depending on the questions answered?

Depending on which questions are filled out, I want to make half the inputs required and the other half to leave empty.
Basically I have a form like this:
//first set
<p>Source: <input type="text" name="source" class="task_input"></p>
<p>Date Earned: <input type="text" name="date_earned" class="task_input"></p>
<p>Amount Earned: <input type="text" name="earned" class="task_input"></p>
//second set
<p>Recipient: <input type="text" name="recipient" class="task_input"></p>
<p>Date Given: <input type="text" name="date_given" class="task_input"></p>
<p>Amount Given: <input type="text" name="given" class="task_input"></p>
and I want the user to either fill out the first set or the second set, and fill out all 3 of whatever the user chooses.
I have an if statement set up for errors that looks like this:
if (isset($_POST['submit'])) {
if ((empty($_POST['source'])||($_POST['date_earned'])||($_POST['earned']))&&(empty($_POST['recipient'])&&($_POST['date_given'])&&($_POST['given']))){
$errors = "Looks like you left something out...";
}elseif ((empty($_POST['recipient'])||($_POST['date_given'])||($_POST['given']))&&(empty($_POST['source'])&&($_POST['date_earned'])&&($_POST['earned']))){
$errors = "Looks like you left something out...";
}else{
//submit
The issue is that it sends an error message if anything is left empty, even though I tried to split it up. My other option is to take away all error messages, but that means that any or all of the three required inputs could be left empty with no error message.
How should I write this if-statement so I can get the results I need?
You could, with some fairly simple javascript, cajole the user into completing one section or another by ensuring that the alternative inputs are disabled as soon as input is identified in any single input element. This would not negate the need for validation serverside as it is easy to disable javascript or process a form by other meas ( ie: curl etc) but could be useful as the initial interface.
You can see the effect in the snippet below.
const d=document;
const bttn=d.querySelector('input[type="submit"]');
d.addEventListener('input',e=>{
// fetch the parent node and it's data-id value
let section=e.target.closest('section')
let id=Number( section.dataset.id );
// make sure button is disabled
bttn.disabled=true;
// use the data-id value to find the other section using 1 - x logic
// and disable all inputs within that other section. The user can now
// only complete entries in one or other section at a time.
let alt=d.querySelectorAll(`section[ data-id="${1-id}" ] input`)
alt.forEach(input=>{
input.disabled=true;
});
// find inputs within current section and convert nodelist to an array
let col=[ ...section.querySelectorAll('input') ];
// find the initial number of input elements in the array.
let len=col.length;
// filter the array to remove empty (&/or other criteria) inputs.
col=col.filter( input=>input.value!='' );
// If all inputs are cleared, the other section should be re-enabled.
if( col.length==0 )alt.forEach(input=>{
input.disabled=false;
});
// enable the button if all fields are populated.
if( col.length==len ){
bttn.disabled=false;
}
})
section,label{display:block; box-sizing:border-box; padding:0.25rem}
section{margin:1rem 0}
label{ width:50%; margin:0.1rem 0 }
label input{float:right}
<form method='post'>
<section data-id=0>
<label>Source: <input type="text" name="source" class="task_input" /></label>
<label>Date Earned: <input type="text" name="date_earned" class="task_input" /></label>
<label>Amount Earned: <input type="text" name="earned" class="task_input" /></label>
</section>
<section data-id=1>
<label>Recipient: <input type="text" name="recipient" class="task_input" /></label>
<label>Date Given: <input type="text" name="date_given" class="task_input" /></label>
<label>Amount Given: <input type="text" name="given" class="task_input" /></label>
</section>
<input type='submit' disabled />
</form>
And to process the form data, rather than multiple isset or empty calls where the logic might become overly confusing you could check whether the keys submitted
<?php
if( $_SERVER['REQUEST_METHOD']=='POST' ){
$errors=array();
$sets=array(
array('source','date_earned','earned'),
array('recipient','date_given','given')
);
# filter the POST array to remove empty items.
$_POST=array_filter( $_POST );
# if no elements are populated abandon processing.
if( empty( $_POST ) )echo '<h3>Empty POST - one or other set of inputs must be completed</h3>';
else{
# arbitary but take the first key in the POST array. If other keys are not in the same set there is a problem.
$keys=array_keys( $_POST );
$key=$keys[0];
$set=in_array( $key, $sets[0] ) ? $sets[0] : $sets[1];
# loop through the POST array, if any field is not in the same set as the first array key, it is an error.
foreach( $_POST as $field => $value ){
if( !in_array( $field, $set ) )$errors[ $field ]='Incorrect set';
if( empty( $value ) && !in_array( $field, $set ) )$errors[ $field ]='Incorrect set & also empty';
}
# make sure that all fields from selected set are not empty, otherwise it is an error.
foreach( $set as $field ){
if( empty( $_POST[ $field ] ) )$errors[ $field ]='Cannot be empty';
}
if( !empty( $errors ) ){
#handle errors in some manner.
foreach( $errors as $field => $errmsg )printf('<div>%s: %s</div>', $field, $errmsg );
}else{
#celebrate
echo '<h3>That is acceptable</h3>';
}
}
}
?>

PHP arrays validation

I have a form that gets validated when submit. I make sure some fields are not empty, date fields have a valid format, etc. I have a block of check boxes with a text input next to it.
Option 1
<input type="checkbox" name="jobBonusId[]" value="1" />
Option 2
<input type="checkbox" name="jobBonusId[]" value="2" />
Option 3
<input type="checkbox" name="jobBonusId[]" value="3" />
Amount 1
<input type="number" name="jobBonusAmount[]" step="0.01" value="0.00" />
Amount 2
<input type="number" name="jobBonusAmount[]" step="0.01" value="0.00" />
Amount 3
<input type="number" name="jobBonusAmount[]" step="0.01" value="0.00" />
So, if any of the jobBonusId[] checkbox gets checked it creates an array. Now, I want to validate the jobBonusAmount[] if its -parent- checkbox was checked and make sure is not empty or equals 0.00.
So far, I have the following code:
// Run the script
if (isset($_POST['addJobRecord']) && $_POST['addJobRecord']=='oTzm50xfm') {
// Validate date format
if (!validateDate($jobDateStart) || !empty($jobDateEnd) && !validateDate($jobDateEnd)) {
// Show the form
$displayContent = $displayForm;
// Validate data dates
} else if ($jobTimeIn>$jobTimeOut) {
// Show the form
$displayContent = $displayForm;
// Validate bonus values
} else if (!empty($jobBonusId) && is_array($jobBonusId)) {
// At least one jobBonusId checkbox was checked
// Make sure its child input is not empty
... HERE'S WHERE I'M STUCK ...
} else {
// Everything looks good
// Add record to database
}
}
Any ideas how to accomplish it?
Thank you much!
You can use array key, and check child by jobBonusId key:
foreach ($jobBonusId as $key => $bonusId) {
if (!empty($bonusId)) {
if (!empty($jobBonusAmount[$key])) { // check a child
// if child is filled
} else {
// not filled
}
}
}
It means, that $jobBonusId array is the same to $jobBonusAmount array

PHP - Insert elemens into an array

I'm working on a formular, but for the moment I just want to insert into an array my elements (I have books and authors).
I can display my books with author (name + surname) with the foreach, but I can't add more elements.
Here is the code with the form.
<H1>Exercice 2</H1>
<form method="POST">
<label for"code" >Number :</label>
<input id="code" name="code" type="number" />
<label for"title">Title :</label>
<input id="title" name="title" type="text" />
<label for"author" >Author :</label>
<input id="author" name="author" type="text" />
<button type="input" type="submit">Ok</button>
$title = $_POST['title'];
$code = $_POST['code'];
$author = $_POST['author'];
$book = array();
$book['code'] = 123;
$book['title'] = "Legendes";
$book['author'] = array("David", "Gemmel");
foreach($book as $value){
$book['key'] = $value;
var_dump($book);
if (is_array($value)) {
foreach($value as $otherValue) {
echo($otherValue);
}
} else {
echo($value);
}
}
I did some searcch, but I don't think it works, it's using the array_push() method with the POST, but I don't know where I can manipulate my form into the array.
If you want some details, I'll be happy to do that =) I'm working on it, if i have some news, you will know =)
Have a nice day =)
1) Assignments are in reverse. Correct way:
$myVar = $myValue
2) You need to set the name attribute in your inputs in order to be sent:
<input id="code" type="number" name="code" />
Then you can access them like:
$_POST['code']
3) To add an element by key in an array, use:
$array['key'] = $value;
Your Exercise 2 have some mistakes :
First, your HTML inputs must have the name attribute to be retrieved by post:
<h1>Exercice 2</h1>
<form method="post">
<label>
<input name="code" type="number" />
</label>
<button type="submit">Ok</button>
</form>
With PHP, you can access to any input value using the name:
$code = $_POST['code'];
Now, I think you want to "add" several books using this HTML form without a storage system. The problem is you can not do this if for every a new request since all the elements you have in your array will be deleted each time you run a new post request. To keep this information you need to use some persistent storage system as a database or others.
Since you seem to want to keep the information for each book together, you need to use a multidimensional array - hence, you'll need to redo the whole thing. Here's a suggestion:
Form:
<h2>Exercice 2</h2>
<form method="post">
<label for"code">Number :</label>
<input id="code" name="code" type="number">
<label for"title">Title :</label>
<input id="title" name="title" type="text">
<label for"author-firstname">Author First Name:</label>
<input id="author-firstname" name="author-firstname" type="text">
<label for "author-lastname">Author Last Name:</label>
<input id="author-lastname" name="author-lastname" type="text">
<input type="submit" name="submit_book" value="Ok">
</form>
Fixed the name-problems, changed the heading (you never, ever use H1 for a form, H1 is strictly used for the site-wide heading/logo/name of site). Also changed the button into a simple input type="submit".
$title = $_POST['title'];
$code = $_POST['code'];
$author = $_POST['author'];
$book = []; // changed this to modern PHP version array assignment
$book[0]['code'] = 123;
$book[0]['title'] = "Legendes";
$book[0]['author-firstname'] = "David";
$book[0]['author-lastname'] = "Gemmel"; // no reason to assign a separate array for first and last name, just use two array-keys
for ($c = 0; $c <= count($book); $c++) { //changed this to a for, counting the amount of entries in the $book array
echo 'Title: '.$book[$c]['title'];
echo 'Author: '.$book[$c]['author-firstname'].' '.$book[$c]['author-lastname'];
} // the content should probably be wrapped in a container of some sort, probably a <li> (and then a <ul>-list declared before the for-loop)
Now. None of this has anything to do with putting stuff INTO the array. That would be something like this (there isn't even a point of assigning the $_POST-variables for the code you posted. But, you can do something like this:
if (isset($_POST['submit_book'])) {
$title = $_POST['title'];
$code = $_POST['code'];
$author-firstname = $_POST['author-firstname'];
$author-lastname = $_POST['author-lastname'];
// however, if all you're doing is putting this into the array, no need to assigne the $_POST to variables, you can just do this:
$temp_array = ['code'=>$_POST['code'],'title'=>$_POST['title'],'author-firstname'=>$_POST['author-firstname'],'author-lastname'=>$_POST['author-lastname']];
$book[] = $temp_array;
}
So, that would replace the assigned variables at the beginning of your code.

How to check strlen of multiple input fields with short code

Multiple input fields like
<input type="text" name="row1[]" id="date1">
<input type="text" name="row1[]" id="amount1">
<input type="text" name="row1[]" id="name1">
<input type="text" name="row1[]" id="document1">
Want to check if number of characters in certain fields (not all fields) is at least 1 (in the example do not want to check number of characters in id="document1". Now using this code
if ( (strlen($_POST['row1'][0]) >= 1) or (strlen($_POST['row1'][1]) >= 1) or (strlen($_POST['row1'][2]) >= 1)) ) {
}
Is it possible to shorten code to something like (this is not working code)?
if ( (strlen($_POST['row1']??want_to_check??) >= 1) ) {
}
And input something like (also not working and not real)
<input type="text" name="row1[]??want_to_check??" id="date1">
<input type="text" name="row1[]??want_to_check??" id="amount1">
<input type="text" name="row1[]??want_to_check??" id="name1">
<input type="text" name="row1[]??do_not_want_to_check??" id="document1">
Check number of characters only in certain fields (not all fields)
a tricky shorthand
if (count(array_filter($_POST['row1'],'trim')) != count($_POST['row1'])) {
//not all fields are set
}
but in general, if you see a repetition - you can be sure that a loop can be used. Look:
if ( (
strlen($_POST['row1'][0]) >= 1)
or (strlen($_POST['row1'][1]) >= 1)
or (strlen($_POST['row1'][2]) >= 1)) )
three repeated operators with only counter changing. I am sure you can write a loop for this. Can't you?
Update
Make sensible field names
<input type="text" name="row1[date]" id="date1">
<input type="text" name="row1[amount]" id="amount1">
<input type="text" name="row1[name]" id="name1">
<input type="text" name="row1[document]" id="document1">
Create an array with required field names
$req = array('date1','amount1','name1');
Check your input against this array in a loop
Something like this might work
function checkLength($inputs) {
foreach($inputs as $input) {
if(strlen($input) < 1) return false;
}
return true;
}
if(checkLength(array($_POST['input1'], $_POST['input2'], $_POST['input3']))) {
}
You can loop through fields using foreach
$field_set = false;
if(!empty($_POST['row1'])){
foreach($_POST['row1'] as $key => $row){
//Your code here
if(trim($_POST['row1']))
$field_set = true;
}
}
This will work if you have dynamic number of fields.

Categories