Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PHP class public variables are undefined after deserialisation

Tags:

json

php

class

So at some point, an ajax call sends a JSON, which I transform into objects and store in session:

    if ( $deps = json_decode( $raw_json, true ) )
    {   
        $pkgs = array();

        foreach ( $deps['vector'] as $key )
        {
            if ( strcasecmp( $key['package'], $key['component'] ) == 0 )
            {
                $package = new Package();
                $package->name = $key['package'];
                $package->version = $key['version'];
                $package->cxx_include = $key['cxx_inc'];
                $package->cxx_link = $key['cxx_link'];
                $pkgs[] = $package;
            }
            else
            {
                foreach( $pkgs as $package ) 
                {
                    if ( $package->name == $key['package'] )
                    {
                        $component = new Component();
                        $component->name = $key['component'];
                        $component->cxx_link = $key['cxx_link'];
                        $package->components[] = $component;
                    }
                }
            }
        }

        $_SESSION['pkgs'] = serialize( $pkgs );

The actual classes are simply:

class Component
{
    public $name;
    public $cxx_link;
}

class Package
{
    public $name;
    public $version;
    public $cxx_inclue;
    public $cxx_link;
    public $components = array();
}

When at some later point, I deserialise and try to parse them:

    $pkgs = isset( $_SESSION['pkgs'] ) ? unserialize($_SESSION['pkgs']) : array();

    foreach ( $pkgs as $package )
    {
        fwrite( $cmake, "find_package(" . $package->name . " " . $package->version . " " );
        if ( count( $package->components ) > 0 )
        {
            fwrite( $cmake, "COMPONENTS " );
            foreach ( $package->components as $component )
                fwrite( $cmake, $component->name. " " );

            fwrite( $cmake, "REQUIRED )\r\n" );
        }

        if ( isset( $package->cxx_include ) )
            // ERROR here: undefined variable
            fwrite( $cmake, "include_directories(${".$package->cxx_include."})\r\n" );

        if ( isset( $package->cxx_link ) )
            // ERROR here: undefined variable
            fwrite( $cmake, "target_link_libraries($rapp_name ${".$package->cxx_link."})\r\n" );
        foreach ( $package->components as $component )
        {
            if ( isset($component->cxx_link) )
                // ERROR here: undefined variable
                fwrite( $cmake, "target_link_libraries($rapp_name ${".$component->cxx_link."})\r\n" );
        }
    }

What really puzzles me, is NOT that the undefined variable is the $component->cxx_link or $package->cxx_link, but what I am shown, is the actual value from the JSON.

For example, if the JSON is:

{
    "vector": [
        {
            "package": "Boost",
            "version": "1.54",
            "component": "Boost",
            "cxx_inc": "Boost_INCLUDE_DIRS",
            "cxx_link": "Boost_LIBRARIES"
        },
        {
            "package": "Boost",
            "version": "1.54",
            "component": "date_time",
            "cxx_inc": "",
            "cxx_link": "Boost_DATE_TIME_LIBRARY"
        },
        {
            "package": "Boost",
            "version": "1.54",
            "component": "filesystem",
            "cxx_inc": "",
            "cxx_link": "Boost_FILESYSTEM_LIBRARY"
        },
        {
            "package": "Opencv",
            "version": "3.0",
            "component": "OpenCV",
            "cxx_inc": "OpenCV_INCLUDE_DIRS",
            "cxx_link": "OpenCV_LIBS"
        },
        {
            "package": "Eigen3",
            "version": "3.0",
            "component": "Eigen3",
            "cxx_inc": "EIGEN3_INCLUDE_DIR",
            "cxx_link": ""
        }
    ]
}

I get as errors:

PHP Notice:  Undefined variable: .Boost_INCLUDE_DIRS.
PHP Notice:  Undefined variable: .Boost_LIBRARIES.
PHP Notice:  Undefined variable: .OpenCV_INCLUDE_DIRS.

Which are the values to which I've set the class members. If I am understanding this correctly, the assignment operation during the JSON iteration, does some kind of shallow copy?

EDIT According to Barmar's comments, I removed the serialize/unserialize, and moved the class definition at the top of each file that uses these classes. I don't get the autoload error anymore, but I still get exactly the same undefined variable error.

like image 624
Ælex Avatar asked May 19 '15 00:05

Ælex


1 Answers

Corrected:

So the problem is you are using double quotes and not single quotes as strings. PHP has a thing called variable variables and you use that unintended (see http://php.net/manual/en/language.variables.variable.php).

Switch every string that contains something like "${something}" to single quotes (or escape the dollar sign as Alex mentioned) and you'll be fine, i.e.:

fwrite( $cmake, "include_directories(${".$package->cxx_include."})\r\n" );

would be

fwrite( $cmake, 'include_directories(${'.$package->cxx_include.'})'."\r\n" );

(Notice that you can't use \r or \n in single quote strings.)

Old answer:

You got a typo in your Package class.

You assign it to $package->cxx_include but the actual name is missing a "d".

class Package
{
    public $name;
    public $version;
    public $cxx_inclue; // typo
    public $cxx_link;
    public $components = array();
}
like image 98
delbertooo Avatar answered Nov 02 '22 02:11

delbertooo