21

How do I run the PHP function htmlspecialchars() on an array of array objects?

I have the following code:

$result_set = Array
(
    [0] => Array
        (
            [home_id] => 1
            [address] => 4225 Nasmyth Dr
            [city] => Plano
            [state] => TX
            [zip] => 76798
        )

    [1] => Array
        (
            [home_id] => 8
            [address] => 4229 Nasmyth Dr
            [city] => Plano
            [state] => TX
            [zip] => 75093
        )
);

// this doesn't work since $result_set is an array of arrays and htmlspecialchars is expecting a string
htmlspecialchars($result_set, ENT_QUOTES, 'UTF-8')); 

UPDATE:

Please note that even though there are quite a few answers below, none of them work for an array-of-arrays. The answers below only work for simple arrays.

I've tried the following, but it doesn't work:

array_walk_recursive($result_set, "htmlspecialchars", array(ENT_QUOTES,'UTF-8'))

I get the following error: htmlspecialchars() expects parameter 2 to be long, string given


UPDATE 2

When I try:

function cleanOutput(&$value) {
    return htmlspecialchars($value, ENT_QUOTES, 'UTF-8');
}
print_r($result_set);
print('-------');
print_r(array_walk_recursive($result_set, "cleanOutput"));

I get the following, undesired, output:

Array
(
    [0] => Array
        (
            [home_id] => 1
            [address] => 4225 Nasmyth Dr
            [city] => Plano
            [state] => TX
            [zip] => 76798
        )
    [1] => Array
        (
            [home_id] => 8
            [address] => 4229 Nasmyth Dr
            [city] => Plano
            [state] => TX
            [zip] => 75093
        )
)
-------1

UPDATE 3

When I try:

function cleanOutput(&$value) {
    return htmlspecialchars($value, ENT_QUOTES, 'UTF-8');
}
$result_set = Array
    (
        [0] => Array
            (
                [home_id] => 1
                [address] => 4225 Nasmyth Dr
                [city] => Plano
                [state] => TX
                [zip] => 76798
            )

        [1] => Array
            (
                [home_id] => 8
                [address] => 4229 Nasmyth Dr
                [city] => Plano
                [state] => TX
                [zip] => 75093
            )
    );

$cleanedOutput = array();
foreach ($result_set as $rs) {
    $cleaned[] = array_map("cleanOutput", $rs);
}
print_r($cleanedOutput);

I get the following, undesired, results:

{'homes' : []}
6
  • What does $result_set contain? Commented Jan 4, 2010 at 22:25
  • $result_set is an array from the database of the results I queried for Commented Jan 4, 2010 at 22:26
  • What happened when you did a array_map('htmlspecialchars', $result_set, array(ENT_QUOTES, 'UTF-8')) ? Is the error with htmlspecialchars or array_map? Commented Jan 4, 2010 at 23:03
  • What does one of the elements of $result_set look like? All solutions provided thus far assume $result_set is an array of strings. Given the second line of your script, I'm guessing $result_set is an array of hashes. Commented Jan 4, 2010 at 23:19
  • @bish, I've updated the original post Commented Jan 4, 2010 at 23:35

10 Answers 10

29

You can use array_map() to run that method on each entry.

$cleaned = array_map("htmlspecialchars", $myArray);

If you need to pass arguments to htmlspecialchars(), you can substitute it for your own custom function:

function myFunc($a) {
  return htmlspecialchars($a, ENT_QUOES);
}

$cleaned = array_map("myFunc", $myArray);

Considering the fact that you're dealing with an array of arrays, and not an array of strings, you would need to cycle through the outer-array to get to your strings:

$cleaned = array();
foreach ($result_set as $rs) {
  foreach ($rs as $r) {
    $cleaned[] = array_map("htmlspecialchars", $r);
  }
}

Or, you could use array_walk_recursive():

array_walk_recursive($myArray, "htmlspecialchars");

Note that this method changes the $myArray object by reference, so there's no need to assign the output to a new variable.

Sign up to request clarification or add additional context in comments.

22 Comments

How do I use array_map() if I want to pass agruments to htmlspecialchars? Meaning, how do I pass the arguements of ENT_QUOTES, 'UTF-8'" to htmlspecialchars?
Meaning, 'array_map("htmlspecialchars", $result_set)' does not allows me to pass in the argument of ENT_QUOTES and UTF-8
TeddyR, make your own function that calls htmlspecialchars with those arguments, and call your function instead.
Why wouldn't this work --> array_map('htmlspecialchars', $result_set, array(ENT_QUOTES, 'UTF-8')) ???
I receive the following error, "htmlspecialchars() expects parameter 2 to be long, string given" when using rray_map('htmlspecialchars', $result_set, array(ENT_QUOTES, 'UTF-8'))
|
23
function filter(&$value) {
  $value = htmlspecialchars($value, ENT_QUOTES, 'UTF-8');
}
array_walk_recursive($result_set, "filter");
print_r($result_set);

12 Comments

Shouldn't this work ---> array_walk_recursive("htmlspecialchars", $result_set, array(ENT_QUOTES,'UTF-8')) ... but it doesn't. I get the error: "Only variables can be passed by reference"
Looks like I have the ordering wrong on my parameters. It should be: array_walk_recursive("htmlspecialchars", $result_set, array(ENT_QUOTES,'UTF-8')) ... but now I get a new error: "htmlspecialchars() expects parameter 2 to be long, string given"
You still have the order wrong. I updated my example to include the additional arguments that you wanted. Also, you need to define your own function, as I do above, rather than just passing "htmlspecialchars". This is because array_walk_recursive doesn't normally modify the array itself; it just calls the function on each element. So if you want the function to change the array, you need to make its first argument a reference, as in my &$value above.
In UPDATE 2, you're still printing the return value of array_walk_recursive, which is not what you want. Just print $result_set. Slow down a second and read the manual page for array_walk_recursive ... you'll see how it works. I modified my example above to print the array.
REAL PERFECT ANSWER
|
6

A lot of the answers on this page are either insufficient, outdated, or use the wrong parameters for array_map or array_walk_recursive. Here's a function that will fix all scalar values in an array recursively.

htmlspecialchars_recursive()

<?php

function htmlspecialchars_recursive ($input, $flags = ENT_COMPAT | ENT_HTML401, $encoding = 'UTF-8', $double_encode = false) {
    static $flags, $encoding, $double_encode;
    if (is_array($input)) {
        return array_map('htmlspecialchars_recursive', $input);
    }
    else if (is_scalar($input)) {
        return htmlspecialchars($input, $flags, $encoding, $double_encode);
    }
    else {
        return $input;
    }
}

$test = array(
    0 => array(
        'test-1' => 'testing <p>html tag</p> will be fixed',
        'test-2' => '&reg; valid and will be left intact',
        'test-3' =>  '© 2080 kept intact'
    ),
    1 => array(
        'test-4' => array(
            'test-5' => 'deeper fix on <p>html tag</p> test',
            'test-6' => '&reg; will be left intact',
            'test-7' =>  '© 2080 kept intact'
        )
    )
);

print_r(htmlspecialchars_recursive($test));

?>

Output

Array
(
    [0] => Array
        (
            [test-1] => testing &lt;p&gt;html tag&lt;/p&gt; will be fixed
            [test-2] => &reg; valid and will be left intact
            [test-3] => © 2080 kept intact
        )

    [1] => Array
        (
            [test-4] => Array
                (
                    [test-5] => deeper fix on &lt;p&gt;html tag&lt;/p&gt; test
                    [test-6] => &reg; will be left intact
                    [test-7] => © 2080 kept intact
                )

        )

)

Comments

4

You may wish to use array_map as Jonathon Sampson suggested, another alternative is array_walk

The difference is that array_map returns a copy of the array with the function applied to each element, while array_walk operates directly on the array you supply.

Comments

4

Made way to make it work for multi-dimensional arrays:

function secure($val) {
    return (is_array($val))?array_map('secure',$val):htmlspecialchars($val, ENT_QUOTES, 'UTF-8');
}

It works, that it calls its-self on array without last used array and if its not an array, it passes it to htmlspecialchars function.

Input: Array ( [0] => test< [1] => Array ( [test>] => <test?> ) [2] => Array ( [0] => test [1] => > [2] => Array ( [0] => bigtest<> ) ) )

Output: Array ( [0] => test&lt; [1] => Array ( [test>] => &lt;test?&gt; ) [2] => Array ( [0] => test [1] => &gt; [2] => Array ( [0] => bigtest&lt;&gt; ) ) )

Comments

2

You don't need to create your own function if you are passing multiple arguments to the called back function.

According to php.net:

array array_map ( callback $callback , array $arr1 [, array $... ] )

So that means if you want to pass multiple arguments you should just pass:

$clean_array = array_map("htmlspecialchars", $myArray, array(ENT_QUOTES, 'UTF-8'));

but for some reason this doesn't work for me.

But this seems to does, don't ask me why.

$clean_array = array_map("htmlspecialchars", $myArray, array(ENT_QUOTES), array('UTF-8'));

6 Comments

This does not work. I receive the error: array_map() [<a href='function.array-map'>function.array-map</a>]: Argument #3 should be an array
So, I'm stumped. Because neither your way nor Jonathan's way works. Both generate errors, see my comments for the exact errors.
I have revised it, it seems to work for me, but test it and see if it outputs properly for you. For some reason if I put both arguments in the same array it stated that "htmlspecialchars() expects parameter 2 to be long". You got me.
@travover, In your second example, I receive the following error: "htmlspecialchars() expects parameter 1 to be string, array given"
@tvanover This would only work for the first element of the array. Look at Example #3 in the documentation and the comment immediately after it as to why.
|
0

If you want to use array_map and pass the function arguments, you can create your own function and use that as the callback:

 function cleanhtml($dirtyhtml) {
       return htmlspecialchars($dirtyhtml, UTF-8);
  }

  $cleaned = array_map("cleanhtml", $myArray);

3 Comments

you don't really need your own function, array_map can pass multiple arguments to the target callback function. array array_map ( callback $callback , array $arr1 [, array $... ] ) The only time you would want to create your own is if you are doing more than one thing to every object in the array.
I noticed that from the comment above. But the php documentation does NOT make it very clear. One simple example would really be helpful. All of their examples assume user-written functions.
This generates the following error: "htmlspecialchars() expects parameter 1 to be string" when I use the following code: function cleanhtml($dirtyhtml) { return htmlspecialchars($dirtyhtml, ENT_QUOTES,'UTF-8'); } $cleaned = array_map("cleanhtml", $myArray);
0
function htmlspecialchars_array_modify (&$arr){
        array_walk_recursive($arr,function(&$value){
            $value=htmlspecialchars($value);
        });
        return $arr;
    }

// this will alter the source

Comments

0

Validation Class function

function htmlspecialchars_recursive ($input, $flags = ENT_COMPAT | ENT_HTML401, $encoding = 'UTF-8', $double_encode = false) {
    static $flags, $encoding, $double_encode;
    if (is_array($input)) {
        return array_map(array($this, 'htmlspecialchars_recursive'), $input);
    }
    else if (is_scalar($input)) {
        return htmlspecialchars($input, $flags, $encoding, $double_encode);
    }
    else {
        return $input;
    }
}

Details:

$input = your input array() or scalar types like integer, float, string or boolean.

$flags = PHP Available flags constant description here

$encoding = encoding type default: UTF-8

$double_encode = based on your needs, you can used. TURE or FALSE

Function call

 //It will convert htmlentities
$param =  $this->htmlspecialchars_recursive($_REQUEST);
// print_r($param);

Output:

/*
        array(
            [whyiitgnq] => &lt;ul&gt;&lt;li&gt;&lt;b&gt;teste&lt;/b&gt;&lt;/li&gt;&lt;li&gt;&lt;b&gt;tetst&lt;/b&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;&lt;i&gt;&lt;u&gt;tets&lt;/u&gt;&lt;/i&gt;&lt;/div&gt;&lt;div&gt;tets&lt;/div&gt;&lt;ol&gt;&lt;li&gt;&lt;b&gt;tetst&lt;/b&gt;&lt;/li&gt;&lt;li&gt;&lt;b&gt;tetst&lt;/b&gt;&lt;/li&gt;&lt;li&gt;&lt;b&gt;test&lt;/b&gt;&lt;/li&gt;&lt;/ol&gt;
            [_wysihtml5_mode] => 1
            [aid] => 12695
        )
        */

Comments

0

Here's another generic version that uses array_walk and behaves in the way that htmlspecialchars does with respect to parameters.

function htmlspecialchars_r($string, 
    int $flags = ENT_COMPAT | ENT_HTML401, 
    string $encoding = null,
    bool $double_encode = true )
{
    if ($encoding === null)
    {
        $encoding =  ini_get("default_charset");
    }

    $filter = function(&$value, $flags, $params) {
        $value = htmlspecialchars($value, $params['flags'], $params['encoding'], $params['double_encode']);
    };

    array_walk_recursive($string, $filter,
        array(
            'flags' => $flags,
            'encoding' => $encoding,
            'double_encode' => $double_encode,
        )
    );

    return $string;
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.