HTML & PHP input[] <- array ? Limitations - php

It's more of a wether can someone confirm my theory, as for going short ways, when you add another input which shall have similar name ex. myvar_0, myvar_1 you are supposed to use javascript to generate those inputs, but there is input "array" type, where you crate an input with name myvar[], myvar[], myvar[] and this acts as an array and passes values via post to PHP as an array, but recently i've discovered that for some weird reason this array has limitation of 197 values ( or 196 is the maximum capable index value ) as on chrome for now ( didn't text it on other browser ).
So does anyone else encoutered a similar problem ?

If you're using suhosin, that brings a limit to the max_vars sent via POST.
Default is set to 200, so could be your problem.
See: suhosin.post.max_vars

array format got nothing to do with html or browser , for browser square brackets doesn't mean any special thing it will send all the key , value pairs with same key as opt[] e.x
for
<input type="hidden name="opt[]" value="1"/>
<input type="hidden name="opt[]" value="2"/>
<input type="hidden name="opt[]" value="3"/>
browser will send
opt[]=1
opt[] =2
opt[]=3
as a request to the server;
Its the PHP which is smart enough to interpret this as index array with name of "opt" .

I've just done a simple test (See below) which returns (for me) 200 items in a post array.
<form method="post">
<?php
print count($_POST['opt']);
for($i = 0; $i < 200; $i++){
?><input type="hidden" name="opt[]" value="1" /><?php
}
?>
<input type="submit" />
</form>
I get the impression this is more about the data being sent, or the server itself, than a limitation of PHP.

Well the answer was the Suhoshin security module, after some research i found that acually max_post_vars was set to 200, that was kinda blocking the rest of data from being processed, thanks for all your answer :-)

Related

POST-ing HTMLFormElements as Array Keep DOM Order Accross Browser

I am POST-ing three HTML input elements that has the PHP Array naming convention i.e. name="name[]" (the 3 inputs have different names "A[]", "B[]" and "C[]"). The input elements are children of <td> elements of which there are anything from 7 to 1001 <td>'s, meaning for each <td> there is 3 times the input elements i.e. 21 to 3003. The layout is similar to that of a Spreadsheet e.g.
<table>
<--! ... -->
<tbody>
<tr>
<td>
<input type="text" name="A[]" placeholder="A1">
<input type="hidden" name="B[]" value="A1">
<input type="hidden" name="C[]" value="2021-10-03">
</td>
<td>
<input type="text" name="A[]" placeholder="B1">
<input type="hidden" name="B[]" value="B1">
<input type="hidden" name="C[]" value="2021-10-04">
</td>
<--! ... -->
</tr>
<--! ... -->
</tbody>
<--! ... -->
When I POST them I noticed that each input' Array keys on the server side conforms to the order the input element appears within the HTMLFormElement.
What I want to know is the order of array keys true accross browser? I could not find anything in the HTML Spec, but the PHP manual gives the following note when denoting an input name as name[] :
Specifying array keys is optional in HTML. If you do not specify the keys, the array gets filled in the order the elements appear in the form. Our first example will contain keys 0, 1, 2 and 3.
Thanks for your question, quite interesting, however I have problems to answer it specifically. That is because this depends on implementation and it can (or as we can see at least could) be different across browsers.
For the PHP part, this is encoded in PHPs source code and therefore defined, but that is only one side and my educated guess (have not looked into the sources) is that it depends on the input order.
This is how I understand it: Given the browsers build the form data set from successful controls and then encode it. For the PHP array keys (of which order you're interested in) with the HTML form (excerpt) example:
<form method="post">
...
<td>
<input type="text" name="A[]" placeholder="A1">
<input type="hidden" name="B[]" value="A1">
<input type="hidden" name="C[]" value="2021-10-03">
</td>
<td>
<input type="text" name="A[]" placeholder="B1">
<input type="hidden" name="B[]" value="B1">
<input type="hidden" name="C[]" value="2021-10-04">
</td>
...
</form>
I would assume document order of the input elements to build the form data-set from. Problem with that is - IIRC - that in HTML there is no specification of document order. Within the DOM there is but from what I know a browser must not have a DOM. It's perhaps stupid to not have a DOM browser internally (or some structure with similar semantics) but there is no requirement in the HTML specification to have one: From what I know DOM is Javascript specific and a browser must not support any client side scripting.
NOTE: The HTML living standard supports this interpretation (as of today 2021-10-03). It does not relate to the DOM in form data encoding, instead it has tree order which has similar semantics to DOM document order. And it is the tree from which the list of input elements is obtained from that is used to identify the successful controls for building and encoding the forms' data. All lists have ordered sequence (first to last, add appends), are initialized empty and are traversed from start to end. So it is that this sequence is retained including in the encoding serializers' encoding which becomes the input parsed by the PHP SAPI.
This confirms the observation that the input order is always the same. If not (the part you're curious about), you could treat it as a flaw. Your standard form input validation should handle that case thought anyway, as any form data in the request could be composed elsewhere (e.g. different form, there is no same-origin policy for form submits) and therefore needs validation.
Considering there is DOM support and also used internally when creating the forms data-set and considering that the successful inputs are processed in document order when building the data-set, the following data-set in this top-down order (one control-name/current-value pair per line) is created:
A[]: A1
B[]: A1
C[]: 2021-10-03
A[]: B1
B[]: B1
C[]: 2021-10-04
If then the result of the encoding (not further specified for the order in the HTML 4.01 specs) of this data-set. Again it would be kind of counter-intuitive to implement it different to the processing order, but if in processing order this then defines the input-order as the PHP SAPI receives this data (HTTP request body) and forms the $_POST array out of it.
What then follows is the following (at least how I explain it to myself, not verified in the sources):
The $_POST array is initialized empty.
The first control-name is A[].
PHP "realizes" the array access brackets [] and that no index or key is given within those brackets.
Therefore the array is populated similar like in PHP code: $_POST['A'][] = 'A1'; (compare: array_push()).
These steps 2. - 4. are done for each name/value pair.
Now this does not specifically answer your question. However if you're asking because you'd like to set the indexes in stone (apart from any order), it should be possible to provide those within the HTML form control-names and it perhaps is what you're looking for:
<form method="post">
...
<td>
<input type="text" name="A[0]" placeholder="A1">
<input type="hidden" name="B[0]" value="A1">
<input type="hidden" name="C[0]" value="2021-10-03">
</td>
<td>
<input type="text" name="A[1]" placeholder="B1">
<input type="hidden" name="B[1]" value="B1">
<input type="hidden" name="C[1]" value="2021-10-04">
</td>
...
</form>
Then at least on the level of accessing via $_POST the keys are defined as the control-names need to be preserved by the HTML standard. And they have the names you expect, as you can re-create the order via the numerical index.
If you're concerned about rows, all you would need to do is to transpose those "named" parts (as PHP is handling the [...] array part) to their indexes:
// required input
$input = $_POST;
// define structure of result data
$fields = ['A' => null, 'B' => null, 'C' => null];
$count = 2;
// initialize the result
$result = array_fill(0, $count, $fields);
// map $input to $result
foreach (array_keys($result) as $index) {
foreach ($fields as $name => $default) {
$result[$index][$name] = $_POST[$name][$index] ?? $result[$index][$name];
}
}
Such a part is also a good place to verify the input is complete. The resulting $result (pick the name that fits best in your case) are also better to map onto database fields (e.g. use A, B, C, ... within the form when you generate the inputs from a structure and then map them back with the same structure onto database (or your applications internal entity/property names).
This is especially the case if you realized that the order was suddenly brittle - you can make the form creation/submission/data-handling a more distinct transaction even HTTP is stateless. At least more distinct on the data level.
Which brings me to another improvement/variant when writing the HTML of the form to have the data in the processing order already within $_POST. It won't spare the needed validation steps, however this can be done within PHP:
<td>
<input type="text" name="set[0][D]" placeholder="A1">
<input type="hidden" name="set[0][E]" value="A1">
<input type="hidden" name="set[0][F]" value="2021-10-05">
</td>
<td>
<input type="text" name="set[1][D]" placeholder="B1">
<input type="hidden" name="set[1][E]" value="B1">
<input type="hidden" name="set[1][F]" value="2021-10-06">
</td>
Then $_POST['set'] already contains the form-data in an ordered array and the transposition is not necessary and to map the order, ksort may suffice already:
ksort($_POST['set']);
So this can help with the immediate processing for the form data (the numeric indexes can be left out as well if the input elements are in the correct order, no ksort() necessary then, PHP will take care of that).
It would be even possible to leave the first name out but it might not be useful because of other form fields not relating to the set:
<td>
<input type="text" name="0[G]" placeholder="A1">
<input type="hidden" name="0[H]" value="A1">
<input type="hidden" name="0[I]" value="2021-10-07">
</td>
<td>
<input type="text" name="1[G]" placeholder="B1">
<input type="hidden" name="1[H]" value="B1">
<input type="hidden" name="1[I]" value="2021-10-08">
</td>
Makes $_POST a numerically indexed (in undefined order) array of arrays.

convert string with array structure back to array in php

I have <input type="text" name="info"> with the value like this:
array() {
[name]=> 'Tien'
[sex]=> 'male'
[address]=> 'ABC'
[code]=> '888'
}
I submit this input to another site (Note that the input value is a string), all I want is convert that value from string back to array array("name"=>"Tien", "sex"=>"male", "address"=>"ABC", "code"=>888). Is possible to convert the string back to array. If yes please help me solve this. Thanks and sorry because my bad English
What you're asking for is serialisation, i.e. expressing an arbitrarily complex data structure in the lowest common denominator as text. If you simply choose a serialisation format which can easily be serialised and unserialised, this is trivial. I'd suggest to use either serialize and unserialise or json_encode and json_decode. Whatever format you came up with there is simply not easily unserialisable.
I can't completely understand your question, but from my best guess, use this form data:
<input type="text" name="info[name]" value="Tien" />
<input type="text" name="info[sex]" value="male" />
<input type="text" name="info[address]" value="ABC" />
<input type="text" name="info[code]" value="888" />
The other site can then handle it as an array stored within $_POST['info']

HTTP ordering variables in form

given a form like the following
<form action="/page" method="POST>
<input type="hidden" name="input" value="12" />
<input type="hidden" name="input" value="24" />
</form>
Using Google Chrome 31.x and PHP 5.5, /page now has a $_POST variable for input of 24
This happens because when the $_POST array is created, The value is over written in the array. And the latter value is the value which is preserved.
Most browsers Ive tested this is the case, But Is there any HTTP spec / browser spec which says that form inputs should be sent in the order they are defined ? Or could an update in the future (or an old browser) send these updates in the reverse order for example ? or a random order ?
Edit:
to give more context, It will not be used like the above in all cases. only in a certain case.
The first form element is a SELECT box, But depending on the options chosen, Javascript will be able to change the value, Without changing the Select box value
Regardless of the order in which HTTP sends your two values, PHP can only have one value for $_POST['input'].
To solve this, use array notation:
<form action="/page" method="POST>
<input type="hidden" name="input[]" value="12" />
<input type="hidden" name="input[]" value="24" />
</form>
Now you'll have an array $_POST['input'] with both values.
To answer your question about the spec, see this page:
http://www.w3.org/TR/html401/interact/forms.html#h-17.13.4
See the bullets for the application/x-www-form-urlencoded default content type.
The control names/values are listed in the order they appear in the document. The name is separated from the value by '=' and name/value pairs are separated from each other by '&'.
To my knoweledge there is no specification as to the order in which a browser should parse the from before submitting.
But I would say that you can pretty much assume that the form fields will be parsed from top to bottom, because the whole dom is parsed like this.
Here is a little bit additional information as to how a form submit is processed/handled.
http://www.w3.org/TR/html401/interact/forms.html#successful-controls
Steve

PHP - HTML - Get multiple checkbox value without making it become array

I have read through many questions and do my searches for hours, but i still cannot find the solution to what i exactly want.
<form method="POST">
<input type="checkbox" name="fruit" value="0" />No Preference
<input type="checkbox" name="fruit" value="1" />Apple
<input type="checkbox" name="fruit" value="2" />Orange
<input type="checkbox" name="fruit" value="3" />Banana
</form>
print_r($_POST);
I already did validation to checkbox value 0 to 1,2,3 so they will inverse and i did it using looping javascript search for the element name. The problem is, i have to use the element name without changing it become array name. (e.g Fruit => Fruit[] ). So i need to use this element name to retrieve all checked information inputted by the customer. I've seen this can be done in ASP, but i could not figure how they do as it's long time ago already.
My question is, could any one figure how to do this without changing the element name into array format (e.g Fruit => Fruit[] ) ? T.T
Any help will be appreciated. Thank you..
As you already figured, when you submit the same name multiple times, the latest one will overwrite former ones. A solution is to set up a hidden field
<input type="hidden" value="" name="foobar_as_array">
and use jQuery or plain JS to concat your values into that field on submit
<form ... onSubmit=$('#foobar_as_array').value(...concatenate them...);">
I changed the validation using this line :
var GenBox = eval("document.forms['SubmitSearchAll']['" + oCheckBox+"[]']");
and it helps me alot. Now it is solved.
Thanks everyone for contributing.

Remove %5B%5D from URL when submitting form

When I submit a form with multiple checkboxes that have the same name I get a URL that looks something like this:
www.mysite.com/search.php?myvalue%5B%5D=value1&myvalue%5B%5D=value2
Is there someway that I can remove the %5B%5D to make the URL "pretty", with something like htaccess?
Code:
<form>
<input type="checkbox" name="myvalue[]" value="value1">
<input type="checkbox" name="myvalue[]" value="value2">
</form>
Is there someway that I can remove the %5B%5D to make the URL "pretty", with something like htaccess?
No. The [] are reserved characters in URLs, so they definitely need to be URL-encoded.
If using POST is not an option, which makes sense given that it's a search form, your best bet is to just give them each a different name with a value of 1 or so.
<form>
<input type="checkbox" name="option1" value="1" />
<input type="checkbox" name="option2" value="1" />
</form>
Or, if you really insist in them having the same name, then you should be extracting the query string yourself instead of relying on the PHP specific feature of returning an array when obtaining a parameter with a [] suffix in the name.
$params = explode('&', $_SERVER['QUERY_STRING']);
foreach ($params as $param) {
$name_value = explode('=', $param);
$name = $name_value[0];
$value = $name_value[1];
// ... Collect them yourself.
}
This way you can just keep using the braceless name.
<form>
<input type="checkbox" name="option" value="option1" />
<input type="checkbox" name="option" value="option2" />
</form>
[ and ] are reserved characters in a URL, so the browser must encode them in order for the URL to work correctly. You cannot have these characters in a URL. Nor can you have any other reserved characters such as spaces, ampersands, etc. They will all be encoded automatically for you (in many cases, even if you type the URL into the browser manually).
If you need a "pretty URL" you can:
Not use a form at all; provide a link to a known "pretty" URL.
Accept the ugly URL, but redirect it immediately to the pretty URL in point 1 above.
Avoid using angle brackets at all in your field names (but this would mean a lot of changes to your back-end code too)
Use a POST method on the form, so that the field data doesn't show up on the URL at all (but this would mean you don't have a link the user can bookmark).
If you must "prettify" this URL, my suggestion would be option 2 above.
Frankly, though, I wouldn't worry about it. People get waaaay to stressed about "pretty" URLs. I don't really get why.
Very few people I know ever actually type in a URL longer than just a domain name.
If you're worried about SEO for this, don't -- the search engine bots know what ULR encoding is and can look past it.
The only other reason for wanting a "pretty" URL is so that it looks good if users share it via an email link or something. To be honest, if you're worried about URL prettyness for that and it's got form fields in it then it's already too ugly, with just the & and = signs all over the place. The encoded brackets really don't make it any worse.
So my honest answer is: don't sweat it. It's normal; ignore it; get on with more important parts of your web development work.
If that is really a problem for you, how about "merging" everything into a single param using some kind of separator like , (or whatever you want).
So, instead of having a URI like myvalue%5B%5D=value1&myvalue%5B%5D=value2, you would end up with a URI like myvalue=value1,value2.
This is just an idea, don't have the code right now, but you will need to do it with JS, and parse the param value on your backend (in order to have an array).

Categories