0

I have a really GIANT array in legacy code. like 500k+ from db entries. It gets populatet once on user login. The global user array so to speak.

Now I got the unthankfull quest to refacture thisbad boy.

the array is a 1 dimensional assighned array like

 $data['username'] = 'idiots'; ( and tons of other values)

Now i want to refacture this in a object wich would call the value from the DB only when i really need it. My idea was to replace the array assighnment part with an object.

So where $user = array(); I want user $user = new user();

Is there any known way to acess a class function so i can acess its propertys via the $user['name'] so it gets passed to the __get method?

I know it is a tall order, and it is probably imposible. But il ask anyway :)

3 Answers 3

2

One way is to make a class that implements ArrayAccess and put your lazy loading logic into offsetGet:

class User implements ArrayAccess {
    private $cache = array();

    public function offsetSet($key, $value) {
        throw new Exception("Read-only!");
    }

    public function offsetUnset($key) {
        throw new Exception("Read-only!");
    }

    public function offsetExists($key) {
        // consult the DB schema and return true if the `key` makes sense
    }

    public function offsetGet($key) {
        if(!isset($this->cache[$key])) {
            // load stuff from the DB
            $this->cache[$key] = ...;
        }
        return $this->cache[$key];
    }
}

$u = new User();
print $u['name'];
Sign up to request clarification or add additional context in comments.

Comments

1

There are two alternatives to this. The first being the traditional :

<?php

/**
 * @see http://php.net/manual/en/language.oop5.overloading.php#object.call
 */
class User
{
    protected $data = array();

    /**
     * @see http://php.net/manual/en/language.oop5.overloading.php#object.get
     */
    public function __get( $name )
    {
        echo "Getting $name " . PHP_EOL;
        return $this->data[ $name ];
    }

    /**
     * @see http://php.net/manual/en/language.oop5.overloading.php#object.set
     */
    public function __set( $name, $value )
    {
        echo "Setting $name to $value " . PHP_EOL;
        $this->data[ $name ] = $value;
    }
}

$user = new User();
$user->a = 'Example';

echo $user->a;

The second is using the PHP SPL interface ArrayAccess which allows an object to get and set like a PHP Assocative Array :

<?php

/**
 * @see http://php.net/manual/en/class.arrayaccess.php
 */
class User implements ArrayAccess
{
    protected $data = array();

    /**
     * @see http://php.net/manual/en/arrayaccess.offsetexists.php
     */
    public function offsetSet( $key, $value )
    {
        echo "Setting $name to $value " . PHP_EOL;
        if( empty( $offset ) )
        {
            $this->data []= $value;
        }
        else
        {
            $this->data[ $key ] = $value;
        }
    }

    /**
     * @see http://php.net/manual/en/arrayaccess.offsetget.php
     */
    public function offsetExists( $key )
    {
        return isset( $this->container[ $key ] );
    }

    /**
     * @see http://php.net/manual/en/arrayaccess.offsetunset.php
     */
    public function offsetUnset( $key )
    {
        unset( $this->data[ $key ] );
    }

    /**
     * @see http://php.net/manual/en/arrayaccess.offsetset.php
     */
    public function offsetGet($offset)
    {
        echo "Getting $name " . PHP_EOL;

        if( $this->offsetExists( $key ) )
        {
            return $this->data[ $key ];
        }

        return null;
    }
}

$user = new User();
$user->[ 'a' ] = 'Example';

echo $user->[ 'a' ];

Comments

0
$data['username'] = 'idiots';
$data = (object) $data;
echo $data->username; // prints 'idiots'

2 Comments

wrong way around dude :) i have in legacy code in over milions acessors via $data['username'] that is my problem.
This requires that you still retrieve 500k values first.

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.