|
darrenbeige
|
 |
« on: November 01, 2009, 01:41:22 AM » |
|
Have any of you any idea how I can produce a form that will resemble the hieratic structure of a typical, multiple-level array, which will then result in the same array structure when POST'ed back to the server? For example, I have an array("Item 1" => true, "Item 2" => array("This", "That") I'm trying to find a method that will easily output a form like this: <form>Item 1<input type="text" value="true" name="array[Item 1]"><br /> Item 2 <ol><li><input type="text" name="array[Item 2][0]" value="This"></li><li><input type="text" name="array[Item 2][1]" value="That"></li></ol><br /></form> I take it it's gonna require some foreach magic, but I can't quite figure it out, especially a method of population the name's of the form elements. Any help, direction or sample code is welcomed and appreciated. Thanks,
|
|
|
|
|
Logged
|
|
|
|
|
Richard F
|
 |
« Reply #1 on: November 02, 2009, 07:17:42 AM » |
|
my instinct would tell me you want a recursive function, which you pass an array, and it prints out for all keys. That way, when you come across an array as a value, you just call the function again.
As to actually implementing it, my brain's not working properly at the moment, but I'll have another look in the morning if I get the chance!
|
|
|
|
|
Logged
|
|
|
|
|
Confuser
|
 |
« Reply #2 on: November 07, 2009, 05:05:29 AM » |
|
Well I dont think you can do name="array[Item 2][1]" i know you can do name="array[Item 2]" from previous experience. If it does work (then i will have learned something new XD) you can do something like <?php $array = array("Item 1" => true, "Item 2" => array("This", "That"); echo '<form>'; foreach($array as $key => $value) { if(!is_array($value)) { //basically only does this if the array value is not another array echo '<input type="text" value="'.$value.'" name="array['.$key.']" />'; } else { //it is an array $value, lets start the <ol> list echo '<br /> '.$key.' <ol>'; $i = 0; //this outputs the number inside the array[key][number here] foreach($value as $stuff) { //go through each of the $stuff and output the input inside an <li> echo '<li><input type="text" name="array['.$key.']['.$i.']" value="'.$stuff.'" /></li>'; $i++; } echo '</ol><br />'; } } echo '</form>'; ?> not tested it btw
|
|
|
|
|
Logged
|
|
|
|
|
darrenbeige
|
 |
« Reply #3 on: November 07, 2009, 07:56:39 PM » |
|
I'll have to try that Confuser, and thanks. I thought it would be something like that. The only thing is the array might have an infinite level, but I can easily integrate a little recursion to handle that. Checked the code. It's definitely on the right lines. Apart from a silly typo on line 2, the code will work down to two levels. Unfortunately, I am in need of an infinite level iterator, so I changed it a bit  After a bit of bugtesting, I'll post it here. If I could be bothered, this would be better off in a class, but I can't. <?php $FormArrayNameGenerator_data = array(); $FormArrayNameGenerator_postName = "array";
function FormArrayNameGenerator($a) { global $FormArrayNameGenerator_data, $FormArrayNameGenerator_postName; $FormArrayNameGenerator_data = array_merge($FormArrayNameGenerator_data, array($a)); $c = $FormArrayNameGenerator_postName; foreach ($FormArrayNameGenerator_data as $b) { $c .= '['. $b. ']'; } return $c; } function recursiveLine($a, $b) { return '<li><input type="text" name="'. FormArrayNameGenerator($a). '" style="width:'. strlen($b) * 12 . 'px;" value="'. htmlspecialchars($b, ENT_QUOTES). '"/></li>'; } function recursiveEcho ($array) { foreach ($array as $a => $b) { if (is_array($b)) { recursiveEcho($b); } else { echo recursiveLine($a, $b), "\n"; } } }
echo '<form>'; recursiveEcho($array); echo '</form>'; ?>
Heres the bad news: It's not working properly. It's fine, until I try and 'retreat' the array. So, it handles doing one stream of an array, but as soon as it tries to end the current stream, and start a new 'branch', the contents simply get appended. I thought this would be quite easy, but it doesn't look like it is ... any help?
|
|
|
|
« Last Edit: November 07, 2009, 10:59:43 PM by darrenbeige »
|
Logged
|
|
|
|
|
thefluffball
|
 |
« Reply #4 on: November 07, 2009, 10:51:36 PM » |
|
<?php function looparray($array){ foreach($array as $key => $value) { if(!is_array($value)) { if($arraylevel > 0){ echo '<li><input type="text" value="'.$value.'" name="array['.$key.']"></li>'; } else { echo $key.' <input type="text" value="'.$value.'" name="array['.$key.']"><br />'; } } else { $arraylevel = $arraylevel + 1; echo $key.' <ol>'; looparray($value); } } if($arraylevel != 0){ $arraylevel = $arraylevel - 1; echo '</ol><br />'; } } $arraylevel = 0; $array = array("Item 1" => true, "Item 2" => array("This", "That")); echo '<form>'; looparray($array); echo '</form>'; ?> Would that not work? And handle however you want to output your form by checking what array level it is inside looparray() and outputting the array differently depending? Haven't coded in PHP for ages so might have done something stupid. This is untested btw. Edit: Updated to give what I think the structure you want. Still untested though. 
|
|
|
|
« Last Edit: November 07, 2009, 11:23:01 PM by thefluffball »
|
Logged
|
|
|
|
|
darrenbeige
|
 |
« Reply #5 on: November 07, 2009, 11:03:48 PM » |
|
<?php function looparray($array){ foreach($array as $key => $value) { if(!is_array($value)) { echo $key.' <input type="text" value="'.$value.'" name="'.$array[$key].'"><br />'; } else { $arraylevel = $arraylevel + 1; looparray($value); } } if($arraylevel != 0){ $arraylevel = $arraylevel - 1; } } $arraylevel = 0; $array = array("Item 1" => true, "Item 2" => array("This", "That"); echo '<form>'; looparray($array); echo '</form>'; ?> Would that not work? And handle however you want to output your form by checking what array level it is inside looparray() and outputting the array differently depending? Haven't coded in PHP for ages so might have done something stupid. That echo's all the variables but the part I am struggling with ATM is keeping the name correct. The desired end result is to echo the entire (custom-formatted so it works in HTML) 'breadcrumb' trail of the current variable into the name value, and be able to do that infinitely for any size of array. Your code will echo all the values, but the name value is incorrectly populated, exactly the same problem my code has.
|
|
|
|
|
Logged
|
|
|
|
|
thefluffball
|
 |
« Reply #6 on: November 07, 2009, 11:14:36 PM » |
|
I don't see why. Try it now.
Edit: Didn't see Richard suggest a recursive function. lol.
|
|
|
|
« Last Edit: November 07, 2009, 11:16:53 PM by thefluffball »
|
Logged
|
|
|
|
|
darrenbeige
|
 |
« Reply #7 on: November 07, 2009, 11:21:39 PM » |
|
Thats the output. <form>Item 1 <input type="text" value="1" name="1"><br /> 0 <input type="text" value="This" name="This"><br /> 1 <input type="text" value="That" name="That"><br /> As you can see, the name values are very wrong indeed. The expected output should be <form>Item 1 <input type="text" value="1" name="array[0]"><br /> 0 <input type="text" value="This" name="array[Item 2][0]"><br /> 1 <input type="text" value="That" name="array[Item 2][1]"><br /> This is turning out to be very difficult indeed.
|
|
|
|
|
Logged
|
|
|
|
|
thefluffball
|
 |
« Reply #8 on: November 07, 2009, 11:24:53 PM » |
|
Sorry, I didn't look at what you wanted in HTML properly. It would be much easier to ignore the names altogether and loop through the HTML, making the array; or store the array you want to send back to the server in a hidden input.
|
|
|
|
|
Logged
|
|
|
|
|
darrenbeige
|
 |
« Reply #9 on: November 07, 2009, 11:30:27 PM » |
|
The closest I've got so far is this: <li><input type="text" name="array[entries][0]" style="width:24px;" value="31"/></li> <li><input type="text" name="array[1]" style="width:24px;" value="33"/></li> <li><input type="text" name="array[2]" style="width:24px;" value="36"/></li>
Here, the tree structure is maintained for the first iteration, but is lost afterwards. If only I could make it stay. Sorry, I didn't look at what you wanted in HTML properly. It would be much easier to ignore the names altogether and loop through the HTML, making the array; or store the array you want to send back to the server in a hidden input.
If that's the case, then what do you suggest? The other methods I tried to send a multidimensional array like that through a HTML form all failed completely. It became just too difficult to iterate over and work out where it should go. Of course, I am more than happy for you to enlighten me. NOTE: I can't put the array in a hidden input, as I want the user to be able to edit it in the textboxes.
|
|
|
|
|
Logged
|
|
|
|
|
thefluffball
|
 |
« Reply #10 on: November 07, 2009, 11:33:07 PM » |
|
Are you willing to use Javascript?
|
|
|
|
|
Logged
|
|
|
|
|
darrenbeige
|
 |
« Reply #11 on: November 07, 2009, 11:37:08 PM » |
|
Are you willing to use Javascript?
ATM, Javascript is fine, as this particular code is for an admin section and I can require the use of JS there. It's the main area that cannot have JS. Thanks,
|
|
|
|
|
Logged
|
|
|
|
|
thefluffball
|
 |
« Reply #12 on: November 08, 2009, 12:21:44 AM » |
|
Then either parse the body innerHTML with JS, or pass it to PHP to parse via JS. Alternately, you could use hidden input and edit it's value dynamically from JS. You can take it from here, right?
|
|
|
|
« Last Edit: November 08, 2009, 12:26:09 AM by thefluffball »
|
Logged
|
|
|
|
|
darrenbeige
|
 |
« Reply #13 on: November 08, 2009, 12:41:27 AM » |
|
Then either parse the body innerHTML with JS, or pass it to PHP to parse via JS. Alternately, you could use hidden input and edit it's value dynamically from JS. You can take it from here, right?
I don't have a clue what you mean. What am I parsing? Why am I parsing it?
|
|
|
|
|
Logged
|
|
|
|
|
thefluffball
|
 |
« Reply #14 on: November 08, 2009, 12:54:11 AM » |
|
So if PHP outputted something like: <form name="whatever">Item 1 <input type="text" value="1" name="array[0]"><br /> Item 2 <ol><li>0 <input type="text" value="This"><br /></li> <li>1 <input type="text" value="That"></li></ol><br /></form> Find the innerHTML of the form called "whatever". Then use a regex to split it up into arrays, so: Item 1 <input type="text" value="1" name="array[0]"> - Item 2 <ol><li>0 <input type="text" value="This"><br /></li> <li>1 <input type="text" value="That"></li> Then use another regex to find text not within <...>. Item 1 - Item 2 Then find text within <li>...</li> but not within <input...> within each <ol>...</ol>, and within the same <li>...</li>, value="...". Item 1 - Item 2 0 = This - 1 = That Etc. That wasn't really thought about, so don't go by that, but hopefully it should explain to you what I mean. Parse it.
|
|
|
|
|
Logged
|
|
|
|
|
darrenbeige
|
 |
« Reply #15 on: November 08, 2009, 12:55:26 AM » |
|
Oh, I get ya now.
|
|
|
|
|
Logged
|
|
|
|
|