I always assumed that cookies may only hold strings, but the way PHP handles cookies, it is also possible to store an array in a cookie (and I'm not talking about serialized array, but a native array). All you need to do is this:
setcookie('a[1]', 'a');
setcookie('a[2]', 'b');
var_dump($_COOKIE);
The above will produce the following (remember to execute it twice):
array(1) {
["a"]=>
array(2) {
[1]=>
string(1) "a"
[2]=>
string(1) "b"
}
}
What's going on here? Clearly we managed to store an array to a cookie, which is supposed to hold strings only. Is this a bug?
It is certainly not a bug. As a matter of fact it is documented in PHP Documentation
You may also set array cookies by using array notation in the cookie name. This has the effect of setting as many cookies as you have array elements, but when the cookie is received by your script, the values are all placed in an array with the cookie's name:
A cookie value can only be a string.
When PHP parses the cookies into $_COOKIE, certain naming conventions (i.e. cookies with names that end in [] or [something]) will cause it to represent them as an array.
Related
When sending an HTTP POST array of text data, for example from a web page with an HTML form and text fields, if we use as the name property of the fields the following array url_alias[id] with id being a positive integer, we receive with PHP:
[url_alias] => Array
(
[2644] => url-of-product-ref-123
[1] => url-of-product-ref-224
)
how will the server (Apache Linux, for example) handle the POST data? Will it internally prepare an array with 2645 indexes, with a null pointer to all indexes except the index: 1 and the index: 2644, or will it do in other, optimized way? Is the format above correct in terms of efficiency - it is very comfortable for PHP programming, but I am afraid of memory leakages or something.
From PHP manual:
An array in PHP is actually an ordered map. A map is a type that associates values to keys. This type is optimized for several different uses; it can be treated as an array, list (vector), hash table (an implementation of a map), dictionary, collection, stack, queue, and probably more. As array values can be other arrays, trees and multidimensional arrays are also possible.
In your example it holds only two keys with one value assigned to each.
The manual has examples on how arrays in PHP behave. For example, if you set up the following array:
$array = array(
"a",
"b",
6 => "c",
"d",
);
They keys assigned will be 0, 1, 6 and 7:
array(4) {
[0]=>
string(1) "a"
[1]=>
string(1) "b"
[6]=>
string(1) "c"
[7]=>
string(1) "d"
}
Please read the manual to learn more.
UPDATE
You are also asking how arrays are sent over HTTP. They (arrays) are not. According to W3C specification defined here:
The form data set is then encoded according to the content type specified by the enctype attribute of the FORM element.
Each enctype has it's own rules too long and extensive to be listed here. Read it there if you wish. The thing is, when PHP receives the encoded data, it automatically decodes indexed form variable names.
So, to wrap it up, the form data is encoded, sent to PHP and the decoding process is on PHP side.
In other programming languages the definition of arrays is something which can hold similar kind of elements. For example if I declare something like int i[] it will store integers, but in PHP a single array seems to be holding strings and numbers together.
Will the number/integer be treated as string in such type of array in PHP?
According to the PHP manual you can indeed store heterogeneous types inside a PHP "array" - scroll down to example 3.
Note that even though the example is about keys being ints or strings, the values assigned in the example are also both ints and strings, demonstrating that it is possible to store heterogeneous types.
Be aware that in the case of different-typed keys there is automatic casting involved so you may have surprising results in the case where e.g. a string contains a valid decimal representation.
Yes. A PHP array can have multiple data types in it.
Also, you should note that arrays in PHP actually are represented in the form of key-value pairs, where the elements you will input into the array are values.
You can explicitly define keys too, when entering elements into the array, but when you don't, PHP will use indices starting from 0.
Example:
<?php
$array = array(
"foo" => "bar",
"bar" => "foo",
100 => -100,
-100 => 100,
);
var_dump($array);
?>
PHP will interpret as
array(4) {
["foo"]=>
string(3) "bar"
["bar"]=>
string(3) "foo"
[100]=>
int(-100)
[-100]=>
int(100)
}
Reference- http://php.net/manual/en/language.types.array.php
You can store anything you want in an array.
Will the number/integer be treated as string in such type of array in PHP?
Not upon storing it. However, when you use a value as such, PHP will convert it. The usage of a value determines its interpretation. (Attention, the key is converted upon storing, however, if it is considered numerical)
Not going to put oil on the fire of the PHP Arrays are no arrays here…
But yes, you can put different variable types (string, int, …) together in a PHP thing called Array.
This question already has answers here:
Storing PHP arrays in cookies
(9 answers)
Closed 1 year ago.
I got an array like this
$value = {array('id'=>$id, 'email'=>$email, 'token'=>$token)}
I want to stringify the array then encode then store it in cookie "login". How do you do that ? Also please tell me how to decode and read the stored value.
Edit:
I've been trying serialize/unserialize, but it didn't work as expected. for example,
$value = serialize(array('id'=>33, 'email'=>'big#gmail.com', 'token'=>'e9aa0966773d68e0fbf9cb21fc2877b4'));
echo $value; //a:3:{s:2:"id";i:33;s:5:"email";s:20:"big#gmail.com";s:5:"token";s:32:"e9aa0966773d68e0fbf9cb21fc2877b4";}
But when the value go to cookie, it looks like this
a%3A3%3A%7Bs%3A2%3A%22id%22%3Bs%3A1%3A%226%22%3Bs%3A5%3A%22email%22%3Bs%3A20%3A%22craigcosmo%40gmail.com%22%3Bs%3A5%3A%22token%22%3Bs%3A32%3A%22e9aa0966773d68e0fbf9cb21fc2877b4%22%3B%7D
json_encode/json_decode
$_COOKIE['login'] = json_encode($array);
$array = json_decode($_COOKIE['login']);
Can also use serialize/unserialize:
$_COOKIE['login'] = serialize($array);
$array = unserialize($_COOKIE['login']);
Perhaps.
UPDATE
With this code:
<html><body><pre><?php
$array = Array(
'id' => 1234,
'email' => 'example#example.com',
'token' => base64_encode('abcDEF1234')
);
echo "Var Dump (initial):\r\n";
var_dump($array);
$serialized = serialize($array);
echo "Serialized:\r\n".$serialized."\r\n";
$unserialized = unserialize($serialized);
echo "Unserialized:\r\n".$unserailized."\r\n";
var_dump($unserialized);
?></pre></body></html>
You would generate the following:
Var Dump (initial):
array(3) {
["id"]=>
int(1234)
["email"]=>
string(19) "example#example.com"
["token"]=>
string(16) "YWJjREVGMTIzNA=="
}
Serialized:
a:3:{s:2:"id";i:1234;s:5:"email";s:19:"example#example.com";s:5:"token";s:16:"YWJjREVGMTIzNA==";}
Unserialized:
array(3) {
["id"]=>
int(1234)
["email"]=>
string(19) "example#example.com"
["token"]=>
string(16) "YWJjREVGMTIzNA=="
}
EDIT2
You're seeing the encoded value based on how the HTTP protocol transfers cookies. There are two headers in a cookie transfer: Set-Cookie & Cookie. One is server->client, other other is client->server, respectfully.
When PHP sets the cookie (using setcookie e.g.) PHP is really just short-handing the following:
setcookie('login',$serialized);
which, in PHP translates to:
header('Set-Cookie: login='.urlencode($serialized).'; '
.'expires=Wed, 12-Jan-2011 13:15:00 GMT; '
.'path=/; domain=.mydomain.com');
If you had characters like : or a SPACE, the browser wouldn't know where the cookie's properties began and ended.
NEVER EVER USE serialize with User input! serialize calls __wakeup and is a big security vulnerability, because you can execute code on the server. (Now the rules before you break 'em)
there is a serialize/unserialize function to convert an array to a string and back.
Edit:
When you store a string to cookie (setcookie), php needs to do a url encode on the string. This prevents any characters in the string saved to cookie interfering with any other headers. When the page is loaded next, php gets the cookie and automatically does a url decode on the cookie value to return it to it's previous value. As far as what is stored in the cookie, this shouldn't matter within php because php will do the url encode/decode automatically. Now if you are getting the cookie in another language such as javascript, then yes, you will get the raw string back. In this case you can use something like decodeURI in JS to get the original value back.
I'm using the SimpleViewer flash image gallery on a site, and it uses an XML file for information about the images it displays.
For the site, I need to dynamically generate the XML, so I'm using a PHP file with a text/xml Content-type declared. However, for some reason when I access one of the GET variables in the $_GET array SimpleViewer tells me that there are no images in the gallery, even though when I view the source it looks the exact same and is well-formed.
Here's the code:
$photos = array(
"1" => array("house1_1.JPG")
);
foreach($photos[$_GET["hid"]] as $p){
echo '';
}
If I replace $_GET["hid"] with "1" then it works fine, but when I make the reference to $_GET it returns the error.
Is there some reason as to why accessing a GET variable would cause scripts linking to the XML (the SimpleViewer flash) to malfunction, and is there a way to get around this?
*Note: The "hid" GET variable is 100% sure set to "1", and there is no PHP error.
Also, the output looks exactly the same for when I use $_GET["hid"] versus "1", the only difference is the SimpleViewer script refuses to see that the images are there.
Also, the stuff in the empty quotes is some XML, but I don't know how to get it to appear in the tags...
Var dump of $photos and $_GET, respectively:
array(1) {
[1]=>
array(1) {
[0]=>
string(12) "house1_1.JPG"
}
}
array(1) {
["hid"]=>
string(1) "1"
}
I would first check and make sure $_GET["hid"] is returning "1". If it's possible that it is not returning "1" then it should throw an error accessing a bad index of $photos.
Is the $_GET hid variable set in your request? If not this will trigger a PHP warning.
var_dump($_GET['hid']); to see the value of the $_GET variable and ensure it as you expect.
Also please ensure that you have error reporting set to at least E_ALL and display errors is set to yes/true to make your debugging easier.
I think you're probably having an issue with the difference between "1" and 1. When you use a get with something like ?hid=1, it's not coming through as a string, that's being converted to a number, whereas your actual array is using the string "1" as the key.
Either change your key to 1 instead of "1" or cast the hid to string.
Issue was never resolved -- I ended up having to just move on and go for a longer and less elegant solution. Oh well.
On stream.get, I try to
echo $feeds["posts"][$i]["attachment"]["href"];
It return the URL, but, in the same array scope where "type" is located (which returns string: video, etc), trying $feeds["posts"][$i]["attachment"]["type"] returns nothing at all!
Here's an array through PHP's var_dump: http://pastie.org/930475
So, from testing I suppose this is protected by Facebook? Does that makes sense at all?
Here it's full: http://pastie.org/930490, but not all attachment/media/types has values.
It's also strange, because I can't access through [attachment][media][href] or [attachment][media][type], and if I try [attachment][media][0][type] or href, it gives me a string offset error.
["attachment"]=> array(8) {
["media"]=> array(1) {
[0]=> array(5) {
["href"]=> string(55) "http://www.facebook.com/video/video.php?v=1392999461587"
["alt"]=> string(13) "IN THE STUDIO"
["type"]=> string(5) "video"
My question is, is this protected by Facebook? Or we can actually access this array position?
Well, once the data is returned to you, it can no longer be protected by Facebook. You have full access to everything in that result as a regular data structure.
From the looks of it, there are multiple href properties throughout, so you'll want to be careful which one you're going for. $feeds["posts"][$i]["attachment"]["href"] is a valid element for some items, but $feeds["posts"][$i]["attachment"]["media"][0]["href"] is also a valid element.
There doesn't appear to be a $feeds["posts"][$i]["attachment"]["type"] element though, so that's why you're getting nothing for that particular item. There is a type inside ["attachment"]["media"][0] however, which is probably what you want.
If you are getting a string offset error when using array syntax, you've probably mixed up an element somewhere. Strings can be accessed via array syntax. For example:
$str = "string";
echo $str[1]; //echos 't'
You would get an offset warning if you tried to access an index that was larger than the string. In any case, from the looks of that output, $feeds["posts"][$i]["attachment"]["media"][0]["type"] should work.