PHP:checked attribute in array of checkboxes - php

I have an array like this
$current_asset = [
['name'=>'Land,'id'=>1],
['name'=>'Building ,'id'=>2],
['name'=>'Machinery','id'=>3],
];
<?php
foreach($current_asset as $key=>$value){ ?>
<input type="checkbox" name="current_asset[]" value="<?php echo $value['id'] ?>">
<?php } ?>
My question how can I add checked attribute in if one of the value is checked when the form populated with the POST data
I am getting the checkbox array like this on form submit
Here are the current checkboxes on form submit (ie values of current_asset)
Array(
0=>1
1=>1
)

You would need to do some kind of check before printing
$html=‘’;
foreach($current_asset as $asset) {
if($asset[‘hasBeenCheckedBefore’]) {
$checked = ‘checked’;
} else {
$checked = ‘’;
}
$html .= “$asset[‘name’] <input type=‘checkbox’ name=‘current_asset[]’ value=‘$asset[“id”]’ $checked />”;
}

Here is an example of one way to do it. I have changed your data structure to be easier to use. I was confused initially because you didn't mention any way to store data. So this is only good for the one page view.
<?php
// initialize data
/**
* Data structure can make the job easy or hard...
*
* This is doable with array_search() and array_column(),
* but your indexes might get all wonky.
*/
$current_asset = [
['name'=>'Land','id'=>1],
['name'=>'Building' ,'id'=>2],
['name'=>'Machinery','id'=>3],
];
/**
* Could use the key as the ID. Note that it is being
* assigned as a string to make it associative.
*/
$current_asset = [
'1'=>'Land',
'2'=>'Building',
'3'=>'Machinery',
];
/**
* If you have more information, you could include it
* as an array. I am using this setup.
*/
$current_asset = [
'1'=> ['name' => 'Land', 'checked'=>false],
'2'=> ['name' => 'Building', 'checked'=>false],
'3'=> ['name' => 'Machinery', 'checked'=>false],
];
// test for post submission, set checked as appropriate
if(array_key_exists('current_asset', $_POST)) {
foreach($_POST['current_asset'] as $key => $value) {
if(array_key_exists($key,$current_asset)) {
$current_asset[$key]['checked'] = true;
}
}
}
// begin HTML output
?>
<html>
<head>
<title></title>
</head>
<body>
<!-- content .... -->
<form method="post">
<?php foreach($current_asset as $key=>$value): ?>
<?php $checked = $value['checked'] ? ' checked' : ''; ?>
<label>
<input type="checkbox" name="current_asset[<?= $key ?>]" value="<?= $key ?>"<?= $checked ?>>
<?= htmlentities($value['name']) ?>
</label>
<?php endforeach; ?>
</form>
<body>
</html>

Related

Output $_POST Array Values Inside a While Loop For An Input Element (During Form Validation) — PHP

I have a form that submits images and their titles. It is set up to check for errors via PHP validations on the image title form input elements and output any errors inside each image component (i.e. the instance in the while loop that represents a certain image). This all works OK.
What I would like to do is have it so that when one or more title is filled out correctly, but there are errors on one or more other titles, the $_POST value of the incorrect input is echoed out in the input element so the user doesn't have to re-type it. This has been easy to do on other forms on the site because there is no loop involved, e.g. on a sign up form etc. On a singular instance I would just do <?php echo $image_title; ?> inside the HTML value attribute, which is set referencing $image_title = $_POST['image-title'];]
So my question is, how do I have it so the $image_title $_POST value instances that pass the validations are outputted in their respective <input> elements, when other instances of the $image_title variable fail. If all the checks pass and there are no errors the form is then processed with PDO statements. The form submission button is placed outside of the main loop so all images are processed in one go when all the information is correct. I have a hidden input element that outputs the database image ID for each image, which can be used as a key in a foreach loop of some type. The problem of course being I can't get a foreach loop to work as I would like.
NOTE: To make the code simpler I've removed all the code relating to the outputting the images themselves.
<?php
if(isset($_POST['upload-submit'])) {
$image_title = $_POST['image-title'];
$image_id = $_POST['image-id']; // value attribute from hidden form element
// checks for errors that are later outputted on each image component
forEach($image_title as $index => $title) {
$id=$_POST['image-id'][ $index ];
if(empty(trim($title))){
$error[$id] = "Title cannot be empty";
}
}
if (!isset($error)) {
try {
// update MySQL database with PDO statements
header("Location: upload-details.php?username={$username}");
} catch (PDOException $e) {
echo "Error: " . $e->getMessage();
}
}
} else {
// prevents error being thrown before form submission if input elements are empty
$image_title = "";
}
?>
<form method="post" enctype="multipart/form-data">
<!-- IMAGE DETAILS COMPONENT - START -->
<?php
$user_id = $_SESSION['logged_in'];
$stmt = $connection->prepare("SELECT * FROM lj_imageposts WHERE user_id = :user_id");
$stmt->execute([
':user_id' => $user_id
]);
while ($row = $stmt->fetch()) {
$db_image_id = htmlspecialchars($row['image_id']);
$db_image_title = htmlspecialchars($row['image_title']);
?>
<div class="upload-details-component">
<?php
// output error messages from the validation above
if(isset($error)) {
foreach($error as $element_id => $msg) {
if($element_id == $id) {
echo "<p>** ERROR: {$msg}</p>";
}
}
}
?>
<div class="edit-zone">
<div class="form-row">
<!-- ** THIS IS THE INPUT ELEMENT WHERE I WOULD LIKE THE TITLE OUTPUTTED IF IT DOESN'T FAIL THE VALIDATION ** -->
<input value="<?php echo $image_title; ?>" type="text" name="image-title[]">
</div>
<div class="form-row">
<input type="hidden" name="image-id[]" value="<?php echo $db_image_id; ?>">
</div>
</div>
</div>
<?php } ?> <!-- // end of while loop -->
<!-- submit form button is outside of the loop so that it submits all of the images inside the loop in on go -->
<button type="submit" name="upload-submit">COMPLETE UPLOAD</button>
</form>
i think this is what you want:
<input value="<?php echo htmlentities($image_title); ?>" type="text" name="image-title[<?php echo $db_image_id; ?>]">
foreach ($_POST['image-title'] as $key => $value) {
$stmt->execute([
':image_id' => $key,
':image_title' => $value
]);
}
Edit: I have now created a minimized version and was able to test it successfully. I created the mysql table on my test-maschine to try it out. I hope this will help you now.
With <input name="img[id]" value="title"> an array will created with the following structure: $_POST['img'][id] = title. The id as array key and the title as array value. So the title is uniquely assigned to each id. The array can be walk through with a foreach key=>value loop.
Edit2: I added error checking. If the title is empty or is "testfail" for example, the title will not be written to the database. In addition, the input field keeps the last input (restore $_POST string).
<?php
$connection = new PDO(...);
$error = []; // declare empty array
if(isset($_POST['img'])) {
try {
$q = "UPDATE lj_imageposts SET image_title=:image_title
WHERE image_id = :image_id AND user_id = :user_id";
$stmt = $connection->prepare($q);
foreach($_POST['img'] as $key => $value) {
// here the error check, so that the wrong title
// is not written into the database
if(trim($value) === '' || $value === 'testfail') {
echo "Error image id $key title $value <br>";
$error[$key] = TRUE; // set error var with img-id
continue; // skip to next img, do not execute sql-stmt
}
$stmt->execute([
':image_id' => $key,
':image_title' => $value,
':user_id' => $_SESSION['logged_in']
]);
echo "Update image id $key title $value <br>";
}
} catch (PDOException $e) {
echo "Error: " . $e->getMessage();
}
}
?>
<form method="post" enctype="multipart/form-data">
<?php
$q = "SELECT * FROM lj_imageposts WHERE user_id = :user_id";
$stmt = $connection->prepare($q);
$stmt->execute([':user_id' => $_SESSION['logged_in']]);
while ($row = $stmt->fetch()) {
$id = htmlentities($row['image_id']);
// check if error with img-id is set above
if(isset($error[$row['image_id']])) {
// if error, fill in title from previous post
$title = htmlentities($_POST['img'][$row['image_id']]);
} else {
// if no error, fill in title from database
$title = htmlentities($row['image_title']);
}
?>
<input type="text"
name="img[<?php echo $id; ?>]"
value="<?php echo $title; ?>"><br>
<?php
// alternative version
//echo '<input type="text" name="img['.$id.']" value="'.$title.'"><br>';
}
?>
<button type="submit" name="upload-submit">Test</button>
</form>
This is harder than it needs to be, because you can't uniquely identify a particular title input except by the order it appears on the form, with the associated hidden input beside it. You need to do some careful juggling to correlate the IDs from the database with the $index of the $_POST arrays, to make sure your tiles and IDs match. You do have that all working, but this seems fragile and not a good solution IMO. I'd suggest using the database IDs as your form input index values, rather than relying on the order they appear on the form, as I did in my answer to a previous question of yours.
You're already tracking errors with the associated DB ID. So when it comes to displaying the input values, you can just check if there is an error for that DB ID. If there is not, this input passed validation, and you can re-display the value from the current $_POST:
<form method="post" enctype="multipart/form-data">
<!-- ... your code ... -->
while ($row = $stmt->fetch()) {
$db_image_id = htmlspecialchars($row['image_id']);
$db_image_title = htmlspecialchars($row['image_title']);
// Start with the value in the DB, this will display first time
// through.
$value = $db_image_title;
// If there's been a POST, and there is no $error for this ID,
// we know it passed validation.
if (sizeof($_POST) && ! isset($error[$db_image_id])) {
$value = $_POST['image-title'][$db_image_id];
}
?>
<!-- ... your code ... -->
<div class="edit-zone">
<div class="form-row">
<!-- Now we can use whatever value we set above -->
<input value="<?php echo $value; ?>" type="text" name="image-title[]">
</div>
Side Note
There's no need to iterate over all your errors to find the one you want. If you have its ID, you can address it directly. Instead of this:
if(isset($error)) {
foreach($error as $element_id => $msg) {
// Note your code above does not show what $id is here,
// AFAICT it is the same as $row['image_id']
if($element_id == $id) {
echo "<p>** ERROR: {$msg}</p>";
}
}
}
You can simply do:
if (isset($error) && isset($error[$row['image_id']])) {
echo "<p>** ERROR: " . $error[$row['image_id']] . "</p>";
}

Creating zend form element array with same name (ZF3)?

Since i've to position checkboxes in design I'm not using MultiCheckbox and using Checkbox instead in zend. I've seen some zf1 solutions but didnt found any zf2 or zf3 solutions.
My Php Code
$languages = new \Zend\Form\Element\Checkbox('languages[]');
$languages->setLabel('English');
$languages->setValue('1');
This produce the following output
<?php
echo $this->formRow($form->get('languages[]'));
//It produce the following
?>
<input type="checkbox" name="languages[]" value="1" checked="checked">
How can I add more items with name "languages[]" without writing direct HTML code ?
You can use a Form collection for this:
1) In your form:
use Zend\Form\Element\Collection;
...
$languages = new \Zend\Form\Element\Checkbox();
$languages->setLabel('English');
$languages->setValue('1');
$languages->setName('language');
$collection = new Collection();
$collection->setName('languages');
$collection->setLabel('Language Collection');
$collection->setCount(2);
$collection->setTargetElement($languages);
$collection->populateValues(array(
1, 0
));
$this->add($collection);
2) Do not forget to prepare your form in your controller action:
$form->prepare();
3) Finally, in your view, get all elements of the collection and render them separately:
<?php $elements = $form->get('languages')->getElements(); ?>
<?php //echo $this->formCollection($form->get('languages')); ?>
<?php echo $this->formRow($elements[0]); ?>
<?php echo $this->formRow($elements[1]); ?>
You can use MultiChebox
https://framework.zend.com/manual/2.2/en/modules/zend.form.element.multicheckbox.html
It works similar to radio form element. Your example implementation
use Zend\Form\Element;
$languages = new Element\MultiCheckbox('languages');
$languages->setLabel('Used languages');
$languages->setValueOptions([
'en_US' => 'english',
'de_DE' => 'german',
'pl_PL' => 'polish',
]);
$languages->setValue('en_US'); //default value; you can use array
My solution (Method 2)
Method 1:
Give name as "language[1]" instead of "language[]". By using this I can call the elements in view seperately.
Creating form.
$language1 = new \Zend\Form\Element\Checkbox('language[1]');
$language2 = new \Zend\Form\Element\Checkbox('language[2]');
$form = new Form('Set');
$form->add($name)
->add($language1)
->add($language2)
->add($submit);
In view file
<div><?php echo $form->get('language[1]');?></div>
<div><?php echo $form->get('language[2]');?></div>
Edit: Method 2
Using fieldset
//Create form
$languages = [
['id' => 1, 'language' => 'English'],
['id' => 2, 'language' => 'Malayalam'],
] ;
$fieldSet = new \Zend\Form\Fieldset('languages') ;
foreach( $languages as $one ) {
$c = new \Zend\Form\Element\Checkbox($one['id']);
$c->setLabel($one['language']) ;
$fieldSet->add($c) ;
}
//Add collection of checkboxes to form
$form->add($fieldSet) ;
In view file
<?php
$language = $form->get('languages') ;
?>
<div class="form-group row">
<label class="control-label col-sm-2" >Choose Languages</label>
<div class="col-sm-10">
<?php foreach($language as $one ) { ?>
<?php echo $this->formCheckbox($one); ?> <span> <?php echo $this->formLabel( $one ) ; ?> </span>
<?php echo $this->formElementErrors($one); ?>
<?php } ?>
</div>
</div>

Send radio selection to function along with textbox

I've got some code working that takes the text from my input box and moves it across to a function. I'm now trying to change it so I add another form element, a radio button and I want to access the choice within my functions.php file.
This is my current code which works for the post name, but what if I want to also grab the colours boxes that was selected too?
main.php
<?php
if (isset($_POST['submit'])) {
$data = $_POST['name']; // the data from the form input.
}
?>
...
<form action="/" method="post">
<input type="text" name="name" placeholder="Acme Corp"/>
<input name="colour" type="radio" value="red">Red<br>
<input name="colour" type="radio" value="blue">Blue<br>
<input name="colour" type="radio" value="green">Green<br>
<input type="submit" name="submit" value="Submit">
</form>
<img src="pngfile.php?data=<?php print urlencode($data);?>"
alt="png php file">
I guess I confused because currently it is calling this:
pngfile.php
<?php
require_once 'functions.php';
$inputData = urldecode($_GET['data']);
process($inputData);
exit;
?>
Which calls functions.php
<?php
function process($inputdata)
{
...
EDIT: What I have tried:
main.php [Change]
$data = $_POST['name'] && $_POST['colour']
But I'm not really sure how to progress.
Never trust user input. Sanitize and validate your inputs before using them.
This can be arranged better, but the basics are still true.
PHP Manual: filter_input_array()
PHP Manual: filter_var_array()
Small Function Library
function sanitizeArray($filterRules)
{
return filter_input_array(INPUT_POST, $filterRules, true)
}
function validateArray($filteredData, $validationRules)
{
return filter_var_array($filteredData, $validationRules, true);
}
function checkFilterResults(array $testArray, array &$errors)
{
if (!in_array(false, $testArray, true) || !in_array(null, $testArray, true)) {
foreach($testArray as $key => $value)
{
$errors[$key] = '';
}
return true;
}
if ($testArray['name'] !== true) { //You can make a function and do various test.
$errors['name'] = 'That is not a valid name.';
}
if ($testArray['clour'] !== true) { //You can make a function and do many test.
$errors['colour'] = 'That is not a valid colour.';
}
return false;
}
function processUserInput(array &$filteredData, array $filterRulesArray, array $validationRulesArray, array &$cleanData, array &$errors)
{
$filteredInput = null;
$tempData = sanitizeArray($filterRulesArray);
if (!$checkFilterResults($tempData, $errors)){
throw new UnexpectedValueException("An input value was unable to be sanitized.");
//Consider forcing the page to redraw.
}
$filteredData = $tempData;
$validatedData = validateArray($filteredData, $validationRulesArray);
if (!$checkFilterResults($validatedData, $errors)){
return false;
}
$errors['form'] = '';
$cleanData = $validatedData;
return true;
}
function htmlEscapeArray(array &$filteredData)
{
foreach($filteredData as $key => &$value)
{
$value = htmlspecialchars($value, ENT_QUOTES | ENT_HTML5, 'UTF-8', false);
}
return;
}
Basic Main Line
try {
$filterRulesArray = []; //You define this.
$filteredData = []; //A temporary array.
$validationRulesArray = []; //You define this.
$validatedData = null; //Another temporary array.
$results = null; //Input processing results: true or false.
$cleanData = null; //Filtered and validated input array.
$errors = []; //Any errors that have accumulated.
if (isset($_POST, $_POST['submit'], $_POST['colour']) && !empty($_POST)) {
$results = processUserInput($filteredData, $filterRulesArray, $validationRulesArray, $cleanData, $errors);
} else {
$errors['form'] = "You must fill out the form."
}
if ($results === true) {
$name = $cleanData['name']; //You can do what you want.
$colour = $cleanData['colour']; //You can do what you want.
//header("Location: http://url.com/registration/thankYou/")
//exit;
}
//Prepare user input for re-display in browser
htmlEscapeArray($filteredData);
} catch (Exception $e) {
header("Location: http://url.com/samePage/"); //Force a page reload.
}
Let the form redraw if input processing fails.
Use the $errors array to display error messages.
Use the $filteredData array to make the form sticky.
<html>
<head>
<title>Your Webpage</title>
</head>
<body>
<h1>My Form</h1>
<form action="/" method="post">
<!-- Make spots for error messages -->
<input type="text" name="name" placeholder="Acme Corp" value="PUT PHP HERE"/>
<!-- No time to display sticky radios! :-) -->
<input name="colour" type="radio" checked="checked" value="red">Red<br>
<input name="colour" type="radio" value="blue">Blue<br>
<input name="colour" type="radio" value="green">Green<br>
<input type="submit" name="submit" value="Submit">
</form>
</body>
</html>
Tip:
It may be better to submit numbers for radios, as opposed to longer string values like (red, green, blue). Numbers are easier to sanitize and validate. Naturally, then you must translate the input number into its corresponding string. You would do that after validation has finished, but before using the values. Good luck!
you can access this using array like this.
$data[] = $_POST['name'];
$data[] =$_POST['colour'];
Or combine both variable
$data = $_POST['name'].'&'.$_POST['colour'];
Use Array in php for this process as follows:
if (isset($_POST['submit'])) {
$array_val = array(
"name"=> $_POST['name'],
"color"=> $_POST['color']
);
}

PHP while loop dynamic rowspan

Consider a table for example
using these table I just wanted to print a table like these by adding rowspan to item id 1002.
Here is my PHP code
$temp_val = '';
$counter = 1;
$sql_sel = mysqli_query($con,"select * from item_table");
while($res_sel = mysqli_fetch_array($sql_sel)){
if($temp_val == $res_sel['item_id']){
$counter++;
echo "<tr></tr>";
}
else{
echo "<tr><td rowspan='".$counter."'>".$res_sel['item_id']."</td></tr>";
}
$temp_val = $res_sel['item_id'];
}
echo "</table>";
it's not correct, it's adding rowspan to item id 1003
You can't do like this because when you create the first row then you have to decide how much will this column can span so you have to get the count of the similar ids first to achieve it. I am just giving you and idea how it can work with and array like you database provides.
<?php
// Array comming from database
$databaseValues = [
[
'item_id'=>'1001',
'item_color'=>'black',
],
[
'item_id'=>'1002',
'item_color'=>'blue',
],
[
'item_id'=>'1002',
'item_color'=>'green',
],
[
'item_id'=>'1003',
'item_color'=>'red',
]
];
// Creating an array as per the need for the table
$arrayForTable = [];
foreach ($databaseValues as $databaseValue) {
$temp = [];
$temp['item_color'] = $databaseValue['item_color'];
if(!isset($arrayForTable[$databaseValue['item_id']])){
$arrayForTable[$databaseValue['item_id']] = [];
}
$arrayForTable[$databaseValue['item_id']][] = $temp;
}
?>
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<table border="1">
<?php foreach ($arrayForTable as $id=>$values) :
foreach ($values as $key=>$value) :?>
<tr>
<?php if($key == 0) :?>
<td rowspan="<?= count($values)?>"><?= $id?></td>
<?php endif;?>
<td><?= $value['item_color']?></td>
</tr>
<?php endforeach;
endforeach; ?>
</table>
</body>
</html>
Hope this will be helpfull for you
You should switch the code inside else and if statement

How to verify multiple checkboxes using php

I have a list which I am populating from my DB into multiple checkboxes using a foreach loop:
<?php
$sections_arr = listAllForumBoards(0, 1, 100);
$count_board = count($sections_arr);
$ticker = 0;
foreach($sections_arr as $key => $printAllSections){
$ticker = $ticker + 1;
$sectionId = getBoardPart($printAllSections, 'id');
$sectionName = getBoardPart($printAllSections, 'title');
$sectionSlug = getBoardPart($printAllSections, 'slug');
?>
<dd><label for="<?php echo $sectionSlug; ?>">
<input type="checkbox" name="section[]" id="<?php echo $sectionSlug; ?>" value="<?php echo $sectionId; ?>" /> <?php echo $sectionName; ?></label></dd>
<?php } ?>
The list is populating as expected. But I want to be able to check to make sure that a user selects at least one of the checkboxes. I've searched here in SO and I only got the one that was done using JQuery, but I want to be able to do this verification using PHP
In the file, where your form is submitting (action file) add this condition:
if (empty($_POST['section'])) {
// it will go here, if no checkboxes were checked
}
In your action file, you should have the following
if(empty($_POST['section'])) {
//this means that the user hasn't selected any checkbox, redirect to the previous page with error
}

Categories