72

How is proper way to store an array in a cookie? in PHP Code example:

$number_ticket=2;
$info[7][5]=1;
$info[8][5]=1;
miken32
  • 42,008
  • 16
  • 111
  • 154
Paul Barrios
  • 757
  • 1
  • 6
  • 8

9 Answers9

137

To store the array values in cookie, first you need to convert them to string, so here is some options.

Storing cookies as JSON

Storing code

setcookie('your_cookie_name', json_encode($info), time()+3600);

Reading code

$data = json_decode($_COOKIE['your_cookie_name'], true);

JSON can be good choose also if you need read cookie in front end with JavaScript.

Actually you can use any encrypt_array_to_string/decrypt_array_from_string methods group that will convert array to string and convert string back to same array. For example you can also use explode/implode for array of integers.

Warning: Do not use serialize/unserialize

From PHP.net

enter image description here

Do not pass untrusted user input to unserialize(). - Anything that coming by HTTP including cookies is untrusted!

References related to security

As an alternative solution, you can do it also without converting array to string.

setcookie('my_array[0]', 'value1' , time()+3600);
setcookie('my_array[1]', 'value2' , time()+3600);
setcookie('my_array[2]', 'value3' , time()+3600);

And after if you will print $_COOKIE variable, you will see the following

echo '<pre>';
print_r( $_COOKIE );
die();
Array
(   
    [my_array] => Array
        (
            [0] => value1
            [1] => value2
            [2] => value3
        )

)

This is documented PHP feature.

From PHP.net

Cookies names can be set as array names and will be available to your PHP scripts as arrays but separate cookies are stored on the user's system.

Community
  • 1
  • 1
Marty Aghajanyan
  • 12,651
  • 8
  • 35
  • 37
  • 4
    This should be the right answer. Thanks for considering security and for the reference. +1 – acarito Sep 20 '16 at 17:17
  • 3
    Great answer, thanks. I found you needed to `stripslashes()` the cookie value before `json_decode()` though. – hobailey Jul 06 '17 at 16:23
  • 2
    @hobailey Great comment! I have been working for hours why my code doesn't work with json encoded cookies while it works on the PHP variables!?! The reason is you really need to add stripslashes() before json_decode(). Example code to get the json encoded cookie in a PHP array: json_decode(stripslashes($_COOKIE['mycookie']), true); – Tarik Jul 07 '17 at 18:41
  • You need stripslashes only if you have Magic Quotes turned on. fyl magic Quotes has been DEPRECATED as of PHP 5.3.0 and REMOVED as of PHP 5.4.0. – Marty Aghajanyan Jul 13 '17 at 18:58
  • explode/implode helped me to solve my issue. Thank you This should be accepted as the correct answer, since it covers probably all possible solutions. – Sharpey Feb 16 '18 at 15:37
74

Serialize data:

setcookie('cookie', serialize($info), time()+3600);

Then unserialize data:

$data = unserialize($_COOKIE['cookie'], ["allowed_classes" => false]);

After data, $info and $data will have the same content.

mario
  • 144,265
  • 20
  • 237
  • 291
Narcis Radu
  • 2,519
  • 22
  • 33
  • 35
    Using serialize is not recommended because there are possible security holes. (http://php.net/manual/en/function.setcookie.php -> notes) – marcovtwout Jun 26 '12 at 08:56
  • 31
    Indeed, please do not use `unserialize` on user-submitted data. This is easily exploitable with object injection using PHP's __wakeup and __destruct methods. You can use `json_encode/json_decode` instead of `serialize/unserialize`. https://www.owasp.org/index.php/PHP_Object_Injection – Quinn Comendant May 02 '14 at 23:53
  • Does not work for me, i tried it with an post request to a file and tried to returned the outputted array as response, and nothing came back. – Black Mar 21 '16 at 14:47
  • @Black I added answer that working for large amount of data. – Yura Kosyak Jul 03 '21 at 11:27
19

Using serialize and unserialize on cookies is a security risk. Users (or attackers) can alter cookie data, then when you unserialize it, it could run PHP code on your server. Cookie data should not be trusted. Use JSON instead!

From PHP's site:

Do not pass untrusted user input to unserialize() regardless of the options value of allowed_classes. Unserialization can result in code being loaded and executed due to object instantiation and autoloading, and a malicious user may be able to exploit this. Use a safe, standard data interchange format such as JSON (via json_decode() and json_encode()) if you need to pass serialized data to the user.

Pang
  • 9,564
  • 146
  • 81
  • 122
Nathan
  • 458
  • 4
  • 10
8

Try serialize(). It converts an array into a string format, you can then use unserialize() to convert it back to an array. Scripts like WordPress use this to save multiple values to a single database field.

You can also use json_encode() as Rob said, which maybe useful if you want to read the cookie in javascript.

Dunhamzzz
  • 14,682
  • 4
  • 50
  • 74
7

Cookies are basically text, so you can store an array by encoding it as a JSON string (see json_encode). Be aware that there is a limit on the length of the string you can store though.

Rob Agar
  • 12,337
  • 5
  • 48
  • 63
3

You can also try to write different elements in different cookies. Cookies names can be set as array names and will be available to your PHP scripts as arrays but separate cookies are stored on the user's system. Consider explode() to set one cookie with multiple names and values. It is not recommended to use serialize() for this purpose, because it can result in security holes. Look at setcookie PHP function for more details

johnny
  • 19,272
  • 52
  • 157
  • 259
Elzo Valugi
  • 27,240
  • 15
  • 95
  • 114
1

Just found the thing needed. Now, I can store products visited on cookies and show them later when they get back to the site.

// set the cookies
setcookie("product[cookiethree]", "cookiethree");
setcookie("product[cookietwo]", "cookietwo");
setcookie("product[cookieone]", "cookieone");

// after the page reloads, print them out
if (isset($_COOKIE['product'])) {
    foreach ($_COOKIE['product'] as $name => $value) {
        $name = htmlspecialchars($name);
        $value = htmlspecialchars($value);
        echo "$name : $value <br />\n";
    }
}
Võ Minh
  • 155
  • 2
  • 12
0

Only this decision helped me to store large amount of data type array in cookie. Works like a charm. Thank you Eric you saved my day.

define( 'COOKIE_PORTIONS' , '_piece_' );

function clearpieces( $inKey , $inFirst ) {
    $expire = time()-3600;
   
    for ( $index = $inFirst ; array_key_exists( $inKey.COOKIE_PORTIONS.$index , $_COOKIE ) ; $index += 1 ) {
        setcookie( $inKey.COOKIE_PORTIONS.$index , '' , $expire , '/' , '' , 0 );
        unset( $_COOKIE[$inKey.COOKIE_PORTIONS.$index] );
    }
}

function clearcookie( $inKey ) {
    clearpieces( $inKey , 1 );
    setcookie( $inKey , '' , time()-3600 , '/' , '' , 0 );
    unset( $_COOKIE[$inKey] );
}

function storecookie( $inKey , $inValue , $inExpire ) {
    $decode = serialize( $inValue );
    $decode = gzcompress( $decode );
    $decode = base64_encode( $decode );
   
    $split = str_split( $decode , 4000 );//4k pieces
    $count = count( $split );
   
    for ( $index = 0 ; $index < $count ; $index += 1 ) {
        $result = setcookie( ( $index > 0 ) ? $inKey.COOKIE_PORTIONS.$index : $inKey , $split[$index] , $inExpire , '/' , '' , 0 );
    }
   
    clearpieces( $inKey , $count );
}

function fetchcookie( $inKey ) {
    $decode = $_COOKIE[$inKey];
   
    for ( $index = 1 ; array_key_exists( $inKey.COOKIE_PORTIONS.$index , $_COOKIE ) ; $index += 1 ) {
        $decode .= $_COOKIE[$inKey.COOKIE_PORTIONS.$index];
    }
   
    $decode = base64_decode( $decode );
    $decode = gzuncompress( $decode );
   
    return unserialize( $decode );
}
Yura Kosyak
  • 401
  • 3
  • 16
-1

recently i've created this code for my client, i'm using array for cookie in this code, actually this code gets recently viewed pages by user using cookies, hope it helps you...!

function curPageURL() { // get url
return 'http' . ((
!empty($_SERVER['HTTPS']) &&
$_SERVER['HTTPS'] !== 'off' ||
$_SERVER['SERVER_PORT'] == 443
) ? 's' : '') . '://' . $_SERVER['SERVER_NAME'] . (
$_SERVER['SERVER_PORT'] == 80 ? '' :  $_SERVER['SERVER_PORT']
) . $_SERVER['REQUEST_URI'];
}

$currentPage = curPageURL(); // call function
$counter = $_COOKIE['_counter']; // set counter variable

if(!$_COOKIE['_PAGES']){ // if _Pages cookie
$default = 1; // set default value to 1
setcookie("_counter",$default,time()+7200); // set counter cookie
setcookie("_PAGES[$default]",$currentPage, time()+3600); // set cookie  
}
else{ // if ! _Pages cookie 
$default = $counter+1; // set default value to +1
setcookie("_counter",$default,time()+7200); // set counter cookie
}


if(@in_array($currentPage, @$_COOKIE['_PAGES'])){ // if same url found
}
else{ // if new url found
setcookie("_PAGES[$default]",$currentPage, time()+3600); // set cookie  
}


if($_COOKIE['_PAGES']){
foreach ($_COOKIE['_PAGES'] as $value){
    echo "<a href='{$value}'>{$value}</a>";
} 
}