Multidimensional arrays in class with __set and __

2019-08-18 23:53发布

问题:

I'm trying to write a simple class that wrap $_SESSION. The idea is that I'll be able to set and get values from the class that will refer to the $_SESSION variable, having the __set and __get execute some other stuff I need.

What I currently have, which is nowhere near complete:

class Session 
{
    // Property declarations
    public $data = array();

    /**
     * Class initialization
     */
    public function __construct() 
    {       
        if (!session_id()) {
            ini_set('session.cookie_lifetime', 0);
            ini_set('session.gc-maxlifetime', 0);

            session_start();
        }

        $this->data =& $_SESSION;
    }

    /**
     * Get session ID
     * @return string 
     */
    public function getId() 
    {
        return session_id();
    }
}

I'm trying to make it work as follows:

$session->images['directory'] = 1;

will be the same as

$_SESSION['images']['directory'] = 1;

and

echo $session->images['directory'];

should in turn output: 1

The catch is, I want to use multidimensional arrays, like so:

$session->images['foo']['bar'] = 'works';

With regular __set and __get functions provided in many examples around SO and php.net, this doesn't work.

Ofcourse, after a page reload/navigation, I'll be able to access the same variables with their respective values.

What I've tried is search Google and Stackoverflow, I keep landing on "ArrayAcces", but cannot seem to figure out how to use that with my problem.

Anyone point me in the right direction?

回答1:

I know this has been here for quite a while - but here is your answer.

Originally I thought you had to use recursion. But then I remembered that PHP does a reference pointer. So I went and looked up the information in the PHP online documentation at:

http://php.net/manual/en/language.references.php

This led me to try some things out and I came up with the following. Now, I used in() and out() because I wasn't testing this with __set and __get. I just wanted it to work. So here are the two functions:

public function in( $v, $d )
{
    $v = $this->get_id( $v );
    $a = explode( ".", $v );
    $b = &$this->info;
    foreach( $a as $k=>$v ){
        if( !isset($b[$v]) ){ $b[$v] = array(); $b = &$b[$v]; }
           else { $b = &$b[$v]; }
        }

    $b = $d;
    return true;
}
public function out( $v )
{
    $v = $this->get_id( $v );
    $a = explode( ".", $v );
    $b = &$this->info;
    foreach( $a as $k=>$v ){
        if( isset($b[$v]) ){ $b = &$b[$v]; }
            else { return false; }
        }

    return $b;
}

I tested the above code with in("this.is.a.test", 5) and out("this.is.a.test"). Which produced the following output:

In: 1
Out: 5
Array
(
    [cleric] => Array
        (
            [this] => Array
                (
                    [is] => Array
                        (
                            [a] => Array
                                (
                                    [test] => 5
                                )

                        )

                )

        )

)

(Yes - I'm working on a D&D program to keep track of characters for me.)

I had set a prefix of "cleric" above where I did the IN and OUT functions. So the first line (the "cleric") is from the prefix. :-)

Anyway, this is a LOT faster than using recursion to do this. I hope this helps. :-) Or if you've already got your answer out of CakePHP - that's great too! :-)