Converting a multi-dimensional array into HTML form fields - how? - php

I'm trying to take a multidimensional array and convert it into HTML form fields, like this:
<input type="hidden" name="c_record[contact][0][name]" value="First Last">
<input type="hidden" name="c_record[contact][0][date_submitted][date]" value="2010-01-01">
<input type="hidden" name="c_record[contact][0][date_submitted][hour]" value="10">
<input type="hidden" name="c_record[contact][0][date_submitted][min]" value="08">
<input type="hidden" name="c_record[contact][0][date_submitted][sec]" value="16">
<input type="hidden" name="c_record[contact][0][ip_address]" value="192.168.1.1">
Here is what I have so far:
$fields = array(
'c_record' => array(
'contact' => array(
0 => array(
'name' => 'First Last',
'date_submitted' => array(
'date' => '2010-01-01',
'hour' => '10',
'min' => '08',
'sec' => '16',
),
'ip_address' => '192.168.1.1',
),
),
),
);
$form_html = array_to_fields($fields);
function array_to_fields($fields, $prefix = '') {
$form_html = '';
foreach ($fields as $name => $value) {
if ( ! is_array($value)) {
if ( ! empty($prefix)) {
$name = $prefix . '[' . $name . ']';
}
// generate the hidden field
$form_html .= Form::hidden($name, $value) . EOL;
} else {
if ( ! empty($prefix)) {
$prefix .= '[' . $name . ']';
} else {
$prefix = $name;
}
$form_html .= array_to_fields($value, $prefix);
}
}
return $form_html;
}
This works fine until ip_address, which results in:
<input type="hidden" name="c_record[contact][0][date_submitted][ip_address]" value="192.168.1.1">
And any additional fields after ip_address keep having the previous field names added to them.
How can I make this work?

You could manhandle http_build_query into service for this purpose, since it naturally creates the scrunched-together keys you're looking for. If you wait until the end to urldecode your keys and values, it's easy to explode the output, since any = or & in a key or value will be safely encoded.
function array_to_fields($array) {
$html = '';
$entries = explode('&', http_build_query($array));
foreach ($entries as $entry) {
list($key, $value) = explode('=', $entry);
$html .= Form::hidden(urldecode($key), urldecode($value)) . EOL;
}
return $html;
}

You are updating $prefix in the current scope before you pass it into the recursive function. You don't want to do that. For multi-valued arrays it means that in the next iteration of the current function the prefix is going to contain the name of the previoust array. You can work around this by passing an updated prefix to the recursive function independent of $prefix.
function array_to_fields($fields, $prefix = '') {
$form_html = '';
foreach ($fields as $name => $value) {
if ( ! is_array($value)) {
if ( ! empty($prefix)) {
$name = $prefix . '[' . $name . ']';
}
// generate the hidden field
$form_html .= Form::hidden($name, $value) . EOL;
} else {
if ( ! empty($prefix)) {
$subprefix = $prefix . '[' . $name . ']';
} else {
$subprefix = $name;
}
$form_html .= array_to_fields($value, $subprefix);
}
}
return $form_html;
}
Try that.

As a hack and temporary solution, I did the following, although it's damn ugly and not flexible:
foreach ($fields as $name1 => $value1) {
if ( ! is_array($value1)) {
$form_html .= Form::hidden($name1, $value1) . EOL;
} else {
foreach ($value1 as $name2 => $value2) {
if ( ! is_array($value2)) {
$form_html .= Form::hidden($name1 . '[' . $name2 . ']', $value2) . EOL;
} else {
foreach ($value2 as $name3 => $value3) {
if ( ! is_array($value3)) {
$form_html .= Form::hidden($name1 . '[' . $name2 . '][' . $name3 . ']', $value3) . EOL;
} else {
foreach ($value3 as $name4 => $value4) {
if ( ! is_array($value4)) {
$form_html .= Form::hidden($name1 . '[' . $name2 . '][' . $name3 . '][' . $name4 . ']', $value4) . EOL;
} else {
foreach ($value4 as $name5 => $value5) {
if ( ! is_array($value5)) {
$form_html .= Form::hidden($name1 . '[' . $name2 . '][' . $name3 . '][' . $name4 . '][' . $name5 . ']', $value5) . EOL;
} else {
foreach ($value5 as $name6 => $value6) {
if ( ! is_array($value6)) {
$form_html .= Form::hidden($name1 . '[' . $name2 . '][' . $name3 . '][' . $name4 . '][' . $name5 . '][' . $name6 . ']', $value6) . EOL;
} else {
throw new Kohana_Exception('There are no levels than are supported by array_to_fields . Ending entire loop');
}
}
}
}
}
}
}
}
}
}
}
}

Related

I have some problem with send and write array in database (Codeingniter 3)

I have a form that sends customer data to the database, I added a choice of another category of customers through the input, and instead of sending the data in text, a number is sent.
db
In View
<?php echo render_select('sellers',get_sellers(),array('articleid','subject'),''); ?>
echo render_select helper:
function render_select($name, $options, $option_attrs = [], $label = '', $selected = '', $select_attrs = [], $form_group_attr = [], $form_group_class = '', $select_class = '', $include_blank = true)
{
$callback_translate = '';
if (isset($options['callback_translate'])) {
$callback_translate = $options['callback_translate'];
unset($options['callback_translate']);
}
$select = '';
$_form_group_attr = '';
$_select_attrs = '';
if (!isset($select_attrs['data-width'])) {
$select_attrs['data-width'] = '100%';
}
if (!isset($select_attrs['data-none-selected-text'])) {
$select_attrs['data-none-selected-text'] = _l('dropdown_non_selected_tex');
}
foreach ($select_attrs as $key => $val) {
// tooltips
if ($key == 'title') {
$val = _l($val);
}
$_select_attrs .= $key . '=' . '"' . $val . '" ';
}
$_select_attrs = rtrim($_select_attrs);
$form_group_attr['app-field-wrapper'] = $name;
foreach ($form_group_attr as $key => $val) {
// tooltips
if ($key == 'title') {
$val = _l($val);
}
$_form_group_attr .= $key . '=' . '"' . $val . '" ';
}
$_form_group_attr = rtrim($_form_group_attr);
if (!empty($select_class)) {
$select_class = ' ' . $select_class;
}
if (!empty($form_group_class)) {
$form_group_class = ' ' . $form_group_class;
}
$select .= '<div class="select-placeholder form-group' . $form_group_class . '" ' . $_form_group_attr . '>';
if ($label != '') {
$select .= '<label for="' . $name . '" class="control-label">' . _l($label, '', false) . '</label>';
}
$select .= '<select id="' . $name . '" name="' . $name . '" class="selectpicker' . $select_class . '" ' . $_select_attrs . ' data-live-search="true">';
if ($include_blank == true) {
$select .= '<option value=""></option>';
}
foreach ($options as $option) {
$val = '';
$_selected = '';
$key = '';
if (isset($option[$option_attrs[0]]) && !empty($option[$option_attrs[0]])) {
$key = $option[$option_attrs[0]];
}
if (!is_array($option_attrs[1])) {
$val = $option[$option_attrs[1]];
} else {
foreach ($option_attrs[1] as $_val) {
$val .= $option[$_val] . ' ';
}
}
$val = trim($val);
if ($callback_translate != '') {
if (function_exists($callback_translate) && is_callable($callback_translate)) {
$val = call_user_func($callback_translate, $key);
}
}
$data_sub_text = '';
if (!is_array($selected)) {
if ($selected != '') {
if ($selected == $key) {
$_selected = ' selected';
}
}
} else {
foreach ($selected as $id) {
if ($key == $id) {
$_selected = ' selected';
}
}
}
if (isset($option_attrs[2])) {
if (strpos($option_attrs[2], ',') !== false) {
$sub_text = '';
$_temp = explode(',', $option_attrs[2]);
foreach ($_temp as $t) {
if (isset($option[$t])) {
$sub_text .= $option[$t] . ' ';
}
}
} else {
if (isset($option[$option_attrs[2]])) {
$sub_text = $option[$option_attrs[2]];
} else {
$sub_text = $option_attrs[2];
}
}
$data_sub_text = ' data-subtext=' . '"' . $sub_text . '"';
}
$data_content = '';
if (isset($option['option_attributes'])) {
foreach ($option['option_attributes'] as $_opt_attr_key => $_opt_attr_val) {
$data_content .= $_opt_attr_key . '=' . '"' . $_opt_attr_val . '"';
}
if ($data_content != '') {
$data_content = ' ' . $data_content;
}
}
$select .= '<option value="' . $key . '"' . $_selected . $data_content . $data_sub_text . '>' . $val . '</option>';
}
$select .= '</select>';
$select .= '</div>';
return $select;
}
get sellers arrays in db functions
function get_sellers()
{
$CI = & get_instance();
return $CI->db->get(db_prefix() . 'sellers')->result_array();
}
I have created a column "sellers" in my table but it sends numbers and not text.
I need it so that when the form is saved it will submit the title and display it in the selection.
Thanks you
View form:
click

Is it possible to parse an INI file with comments and edit it?

I have created a form,I read from a INI file and show its values in the form.
Now I want to edit that file.
So I show values in text box and let the user edit the file.
Now I am using INI Library to write my files, but my code changes the structure of INI file, also it remove the comments.
Is it possible that when I write to the file only those value is changed and other things like comments and Section remain as it is ?
This is my code:
$CFG_file = $this->data['file_data'] = parse_ini_file("CFG/fms.cfg" ,true);
if (isset($_POST['submit']))
{
//var_dump($_POST);
$data_file = $this->parameter_m->array_from_post(array('VAL1','VAL2','InMedia','VAL','VAL','VAL5','VAL3'));
$this->load->helper('file');
$file = "CFG/fms.cfg";
$this->load->library('ini');
$ini = new INI($file);
$ini->write($file, $data_file );
}
And the library code that writes file :
function write($file = NULL, $file_content = array(), $sections = FALSE) {
$this->file_content = (!empty($file_content)) ? $file_content : $this->file_content;
$this->file = ($file) ? $file : $this->file;
$this->sections = $sections;
$content = NULL;
if ($this->sections) {
foreach ($this->file_content as $section => $file_content) {
$content .= '[' . $section . ']' . PHP_EOL;
foreach ($file_content as $key => $val) {
if (is_array($val)) {
foreach ($val as $v) {
$content .= $key . '[]=' . (is_numeric($v) ? $v : $v ) . PHP_EOL;
}
} elseif (empty($val)) {
$content .= $key . '=' . PHP_EOL;
} else {
$content .= $key . '=' . (is_numeric($val) ? $val : $val ) . PHP_EOL;
}
}
$content .= PHP_EOL;
}
} else {
foreach ($this->file_content as $key => $val) {
if (is_array($val)) {
foreach ($val as $v) {
$content .= $key . '[] = ' . (is_numeric($v) ? $v : '"' . $v . '"') . PHP_EOL;
}
} elseif (empty($val)) {
$content .= $key . ' = ' . PHP_EOL;
} else {
$content .= $key . ' = ' . (is_numeric($val) ? $val : '"' . $val . '"') . PHP_EOL;
}
}
}
return (($handle = fopen($this->file, 'w+')) && fwrite($handle, trim($content)) && fclose($handle)) ? TRUE : FALSE;
}
And this is my file :
[]
VAL1= 0.0.0.0
VAL2= 5070
;media settings
;ON/OFF/AUTO
VAL3= OFF
VAL4= 8000
VAL5= 4000
VAL6= 360
;Transport settings
;ON/OFF
VAL7= OFF
When i execute my code this becomes :
VAL1= "0.0.0.0"
VAL2 = 5071
VAL3 =
VAL4 = 8000
VAL5 = 4000
VAL6 = 360
VAL7 = "ON"

Constructing repeated functions

I've created the following function to print HTML tags in PHP.
function div($attr = [], $child = []) {
$div = "<div";
if (is_array($attr)) {
foreach ($attr as $key => $value) {
$div .= " " . $key . '="' . $value . '"';
}
}
$div .= ">";
if (is_array($child)) {
foreach ($child as $value) {
$div .= $value;
}
}
$div .= "</div>";
return $div;
}
echo div(["class" => "container"], [
div(["class" => "title"], ["Lorem Ipsum"]])
]);
Now, I use this function with multiple tags; div, table, tr, td, etc.
For each tag, I declare the function over and over again with little modification in the body. This seems redundant. I want to create a main function which will return the actual function. For example,
$div = construct("div");
$tr = construct("div");
Of course, PHP is different than JS. In JS, this would work:
function construct(tagName) {
var elm = tagName;
return function(value) {
console.log(elm + ": " + value);
}
}
var div = construct("div");
var tr = construct("tr");
div("test"); // div: test
tr("test"); // tr: test
How should I proceed?
Similar actually as in js:
Just use the first argument of the function to pass the element type as a string.
function construct($elem, $attr = [], $child = []) {
$out = "<".$elem;
if (is_array($attr)) {
foreach ($attr as $key => $value) {
$out .= " " . $key . '="' . $value . '"';
}
}
$out .= ">";
if (is_array($child)) {
foreach ($child as $value) {
$out .= $value;
}
}
$out .= "</".$elem.">";
return $out;
}
echo construct("div",["class" => "container"], [
div(["class" => "title"], ["Lorem Ipsum"]])
]);
You could pass the type of tag through a parameter of the function.
function ConstrucElement($tag, $attr, $body)
{
$output = '<' . $tag;
....
$output .= '</' . $tag . '>';
}
This is how I would solve the problem at hand:
function element($elementName, $attr = [], $child = []) {
$element = "<" . $elementName;
...
return $element;
}
function div($attr = [], $child = []) {
return element("div", $attr, $child);
}
This has the additional benefit of enabling element specific validations etc.: (pseudocode)
function a($attr = [], $child = []) {
if(attr contains no href) return ERROR;
return element("div", $attr, $child);
}
Doing some more digging, I figured out a way to make it work the JS way. The use of use in the examples in PHP: Closure - Manual did the job.
function construct($tag_name = "") {
return function($attr = [], $child = []) use ($tag_name) {
$element = "<$tag_name";
if (is_array($attr)) {
foreach ($attr as $key => $value) {
$element .= " " . $key . '="' . $value . '"';
}
}
$element .= ">";
if (is_string($child)) {
$element .= $child;
}
if (is_array($child)) {
foreach ($child as $value) {
$element .= $value;
}
}
$element .= "</$tag_name>";
return $element;
};
}
$h2 = construct("h2");
$span = construct("span");
$div = construct("div");
$table = construct("table");
$tr = construct("tr");
$td = construct("td");
Using a generic function to print the tags seems like a more practical approach, but not that desirable, because the code gets harder to read. Compare the following blocks.
while ($row = $albums->fetch_assoc()) {
echo $div(["class" => "album"], [
$h2([], [$row["album"] . " (" . $row["year"] . ")"]),
$div(["class" => "album-cover"], [
img(["src" => "covers/" . $row["cover"]]),
]),
$div(["class" => "songs"], [
$table([], [
loop_songs($row["album"]),
]),
]),
]);
}
while ($row = $albums->fetch_assoc()) {
echo construct("div", ["class" => "album"], [
construct("h2", [], [$row["album"] . " (" . $row["year"] . ")"]),
construct("div", ["class" => "album-cover"], [
construct("img", ["src" => "covers/" . $row["cover"]]),
]),
construct("div", ["class" => "songs"], [
construct("table", [], [
loop_songs($row["album"]),
]),
]),
]);
}
First one seems more readable to me.
Here's another approach using __callStatic:
So now you can build your HTML with these:
Build::div(...)
Build::span(...)
Build::table(...)
Like this:
<?php
class Build {
public static function __callStatic($name, $arguments) {
$attr = $arguments[0];
$child = $arguments[1];
$div = "<" . $name;
if (is_array($attr))
foreach ($attr as $key => $value)
$div .= " " . $key . '="' . $value . '"';
$div .= ">";
if (is_array($child))
foreach ($child as $value)
$div .= $value;
$div .= "</" . $name . ">";
return $div;
}
}
echo Build::div(["class" => "container"], [
Build::span(["class" => "title"], ["Lorem Ipsum"])
]);
Output:
<div class="container"><span class="title">Lorem Ipsum</span></div>

Show existing content of file when editing it PHP

I open a .ini, then write some add some values to its parameters and then i saved it back.
My writing the content works perfectly fine, but when i open the file the previous content of that file is cleared.[Maybe due to my write mode].
What change should i do in my code to let user see what the previous content was when he edits a file.
file_get_contents($path.$filename);
/*Get All The datas from that file*/
$this->data['params'] = $this->parameter_m->get();
/*Getting the parameters to display on view*/
$this->data['parameters'] = parse_ini_file($path.$filename,true);
while (current($this->data['parameters']) )
{
$param_set = current($this->data['parameters']);
$param_type = key($this->data['parameters']);
foreach ($param_set as $key =>$value)
{
$this->data['parameters'][$param_type][$key] = $this->input->post($key);
}
next($this->data['parameters']);
}
$this->load->helper('file');
$this->load->library('ini');
$file = $path.$filename;
$ini = new INI($file);
$ini->read($file);
$ini->write($file, $this->data['parameters']);
My Write Function
function write($file = NULL, $data_file = array(), $sections = TRUE) {
$this->data_file = (!empty($data_file)) ? $data_file : $this->data_file;
$this->file = ($file) ? $file : $this->file;
$this->sections = $sections;
$content = NULL;
if ($this->sections) {
foreach ($this->data_file as $section => $data_file) {
$content .= '[' . $section . ']' . PHP_EOL;
foreach ($data_file as $key => $val) {
if (is_array($val)) {
foreach ($val as $v) {
$content .= $key . '[] = ' . (is_numeric($v) ? $v : $v ) . PHP_EOL;
}
} elseif (empty($val)) {
$content .= $key . ' = ' . PHP_EOL;
} else {
$content .= $key . ' = ' . (is_numeric($val) ? $val : $val ) . PHP_EOL;
}
}
$content .= PHP_EOL;
}
} else {
foreach ($this->data_file as $key => $val) {
if (is_array($val)) {
foreach ($val as $v) {
$content .= $key . '[] = ' . (is_numeric($v) ? $v : '"' . $v . '"') . PHP_EOL;
}
} elseif (empty($val)) {
$content .= $key . ' = ' . PHP_EOL;
} else {
$content .= $key . ' = ' . (is_numeric($val) ? $val : '"' . $val . '"') . PHP_EOL;
}
}
}
return (($handle = fopen($this->file, 'w+')) && fwrite($handle, trim($content)) && fclose($handle)) ? TRUE : FALSE;
}

output columns as an array for inarray checking

The following code works. However I was wondering if there was a way to clean up the top part where the columns are outputted as an array.
I didn't include the full script because it is too long, but basically I have three different queries and I want to match the values from the table (resultInput...textarea...images) with the editable values I defined.
In order for me to do this I need to have the columns outputted as an array.
I was wondering if there was a cleaner way of doing this? (top-part until //end output as array)?
$ArrayResultInput = array();
while ($row = mysql_fetch_array($resultInput)) {
$ArrayResultInput[] = $row['Field'];
}
$inArrayResultInput = $ArrayResultInput;
//
$ArrayResultTextarea = array();
while ($row = mysql_fetch_array($resultTextarea)) {
$ArrayResultTextarea[] = $row['Field'];
}
$inArrayResultTextarea = $ArrayResultTextarea;
//
$ArrayResultImages = array();
while ($row = mysql_fetch_array($resultImages)) {
$ArrayResultImages[] = $row['Field'];
}
$inArrayResultImages = $ArrayResultImages;
// end output as array
while ($row = mysql_fetch_assoc($resultUpdate)) {
foreach ($row as $fieldname => $value) {
if (in_array($fieldname, $inArrayResultInput)) {
echo '<div class="wrapper"><label>' . ucfirst(str_replace('_', ' ', $fieldname)) . '<br><input name="' . $fieldname . '" type="text" class="input" value="' . $value . '"><br></label></div>';
}
}
foreach ($row as $fieldname => $value) {
if (in_array($fieldname, $inArrayResultTextarea)) {
echo '<div class="wrapper"><label>' . ucfirst(str_replace('_', ' ', $fieldname)) . '<br><textarea name="' . $fieldname . '">' . $value . '</textarea><br></label></div><script type="text/javascript">CKEDITOR.replace(\'' . $fieldname . '\',{toolbar:\'Basic\'});</script>';
}
}
foreach ($row as $fieldname => $value) {
if (in_array($fieldname, $inArrayResultImages)) {
echo '<div class="wrapper"><span class="form-file">' . ucfirst(str_replace('_', ' ', $fieldname)) . '</span><input id="' . $fieldname . '" name="' . $fieldname . '" type="input" class="input" value="' . $value . '"><input type="button" value="Browse" onclick="CKFinder.popup(\'../\', null, null, SetFileField_' . $fieldname . ');" class="button browsebttn medium"><br></div><script type="text/javascript">function SetFileField_' . $fieldname . '(fileUrl){document.getElementById(\'' . $fieldname . '\').value=fileUrl;}</script>';
}
}
}

Categories