1

I'm trying to build a function that will apply html_entity_decode to objects and arrays. Since I don't know the structure beforehand, and the child properties can also be objects or arrays, a simple recursive function seemed to be the way to go. I'm unable to figure out why the following does not work:

function decode($data){  
    if(is_object($data) || is_array($data)){
        foreach($data as &$value)
            $value = $this->decode($value);
    }
    else $data = html_entity_decode($data);

    return $data;
}

I have also tried the following, which doesn't work either:

function decode($data){
    if(is_object($data))
        $data = get_object_vars($data);

    $data = is_array($data) ? array_map(array('MyClassName', 'decode'), $data) : html_entity_decode($data);

    return $data;
}

Neither function has any affect on the data. What am I doing wrong?

Mark Brown
  • 10,386
  • 8
  • 24
  • 32

3 Answers3

9

The main issue is that you are trying to work with object like array is_object($data) || is_array($data) would not really work except you convert the object to array

Other Issues are base on incorrect variable name and not returning the proper variable You can try

$std = new stdClass();
$std->title = array("x" => "<a>XXX</a>","y" => "<b>YYY</b>");
$std->body = "<p> THis is the Body </p>";

$var = array(
        "a" => "I'll \"walk\" the <b>dog</b> now",
        "b" => array("<b>Hello World</b>",array(array("Yes am <strong> baba </strong>"))),
        "c" => $std

);

$class = new MyClassName();
$encode = $class->encode($var); // encode 
$decode = $class->decode($encode);  // decode it back

print_r($encode);
print_r($decode);

Encoded Array

Array
(
    [a] => I'll &quot;walk&quot; the &lt;b&gt;dog&lt;/b&gt; now
    [b] => Array
        (
            [0] => &lt;b&gt;Hello World&lt;/b&gt;
            [1] => Array
                (
                    [0] => Array
                        (
                            [0] => Yes am &lt;strong&gt; baba &lt;/strong&gt;
                        )

                )

        )

    [c] => stdClass Object
        (
            [title] => Array
                (
                    [x] => &lt;a&gt;XXX&lt;/a&gt;
                    [y] => &lt;b&gt;YYY&lt;/b&gt;
                )

            [body] => &lt;p&gt; THis is the Body &lt;/p&gt;
        )

)

Decoded Array

Array
(
    [a] => I'll "walk" the <b>dog</b> now
    [b] => Array
        (
            [0] => <b>Hello World</b>
            [1] => Array
                (
                    [0] => Array
                        (
                            [0] => Yes am <strong> baba </strong>
                        )

                )

        )

    [c] => stdClass Object
        (
            [title] => Array
                (
                    [x] => <a>XXX</a>
                    [y] => <b>YYY</b>
                )

            [body] => <p> THis is the Body </p>
        )

)

See Live Demo

class MyClassName {
    function encode($data) {
        if (is_array($data)) {
            return array_map(array($this,'encode'), $data);
        }
        if (is_object($data)) {
            $tmp = clone $data; // avoid modifing original object
            foreach ( $data as $k => $var )
                $tmp->{$k} = $this->encode($var);
            return $tmp;
        }
        return htmlentities($data);
    }

    function decode($data) {
        if (is_array($data)) {
            return array_map(array($this,'decode'), $data);
        }
        if (is_object($data)) {
            $tmp = clone $data; // avoid modifing original object
            foreach ( $data as $k => $var )
                $tmp->{$k} = $this->decode($var);
            return $tmp;
        }
        return html_entity_decode($data);
    }
}
Baba
  • 89,415
  • 27
  • 158
  • 212
  • 1
    this works well! I came across it and decided to use it in my own project. Thank you! – Ty Bailey Mar 02 '13 at 05:54
  • @TyBailey you can also look at http://stackoverflow.com/a/15034807/1226894 it uses different filters not just `htmlentities` – Baba Mar 02 '13 at 09:48
  • Thank you. This works well. Coincidentally, so do both of my original functions (at least for my purposes). The problem seems to be with my jquery ajax request. Somehow it's encoding the entities even though the php script is sending a decoded response. Of course I'll accept your answer because it's 100% correct for the original question. Thanks again. – Mark Brown Mar 07 '13 at 06:22
  • 1
    I am working with SOAP Response Objects and Twig/Symfony . You just saved me a lot of time ! thnx ! – Diego Favero Nov 27 '13 at 15:31
  • I know this is a somewhat old answer, but I just want to point out that `html_entitity_decode` converts `NULL` values to strings`""`. Not really desirable when you're, for example, trying to insert values into your database. Suggest you add `is_null($var)` in there. – YTZ Jul 22 '19 at 13:16
1

What exactly do you want to do: replace existing values with html entity decoded values or make a copy of the whole data structure with encoded values?

If you want to replace then you should pass function argument by reference:

function decode( &$data ){

If you want to make a copy -- it should work the way it is (or please explain what exactly do you mean by "the following does not work").

eyevan
  • 1,442
  • 8
  • 20
0

What about array-walk-recursive: http://php.net/manual/en/function.array-walk-recursive.php perhaps something like this:

function decode($data){  
    $data = html_entity_decode($data);
}
function decode_data($data){
    if(is_object($data) || is_array($data)){
       array_walk_recursive($data, 'decode');
    }else{
       $data = html_entity_decode($data);
    }
    return $data;
}
Iesus Sonesson
  • 854
  • 6
  • 12