PHP不可变对象效率

时间:2014-03-26 22:20:22

标签: php arrays multidimensional-array

我一直在研究用于PHP的 immutable 对象。人们可以通过调整单身模式并轻松地使用魔术方法来做到这一点,但我在这里有一些特定的需求。

1。在任何情况下,引用都不会返回包含的值。

2。如果包含的数据是一个数组(很可能是json_decode()加载的大型树),那么必须能够使用搜索字符串搜索密钥

例如:

  $thing = $foo->get( 'go.get.the.thingy.at.this.level' );

......将返回:

   $foo->_data['go']['get']['the']['thingy']['at']['this']['level']

第3。沿着包含数组寻找键的步骤,使用引用 - 副本。

  • 这意味着我会尽量避免使用foreach()来电。如果你不明白我的意思(或理解为什么)这是一个问题),在PHP中:

    • foreach() 不会处理您正在迭代的对象。
    • foreach() 适用于正在迭代的对象的副本

我的问题

我在这里有一些shell(除了一些小的语法问题),但我想看看是否可以提高效率,或者是否有更好的技巧来完成相同的任务

class   ProperlyProtectedObject {

    // PUBLIC STUFF

    /// Initializes the singelton and returns a reference -- or cowardly returns a null.
    public  static  function    init( $value )  {
        if( true === empty( self::$_self ) )    {   // empty returns true if 0, false, null, or not set
            if( false === isset( $value ) )  {      // isset returns true if not set or null.
                return  null;   // ...you idjit!
            }
            self::$_data    = new ProperlyProtectedObject( $value );
        }
        return  & self::$_self;
    }

    /// invoke ( php > =5.3 ): default
    public function __invoke( $var )    {
        return $this->get( $var );
    }

    public function     __call( $f, $args ) {
        return $this->get( $args );
    }

    public function  __callStatic( $f, $args ) {
        return null;  // idjit.
    }  

    /// get: NEAT TRICK:
    /// if you know that you are storing an array here, then you can pass a dot syntax
    /// string (e.g.: foo.bar.soemthing_else.foo.0 ) and 
    /// -- provided that your keys don't contain dots (:-P) --you can get the value of a
    /// nested array key!
    /// \return <Mixed> Any value **except** NULL is the value at the depth you are looking for.
    /// \return NULL    this means that   you.have.a.BAD.Key.string.SomeWhere 
    public function get( $val )   {
        $copyOfThing = null;

        if( true === is_array( self::$_data ) ) {
            if( true === is_string( $val ) )    {
                $keys   = explode( '.', $val );
                if( 0 < count( $keys ) {
                    $copyOfThing    = walk( self::$_data, $keys );
                }
            }
        }
        else    {
            $copyOfThing    = self::$_data;
        }

        return  $copyOfThing;
    }


    /// set: DOES NOTHING. This object is meant to take an act of congress to delete data.
    public function __set( $objProp, $value )   {
        // do nothing.
        // echo '<pre>DIE IN A FIRE!!!! ' . var_export( $objProp, true ) . '</pre>';
    }

    /// isset: 
    public function __isset( $objProp ) {
        return  ( null !== $this->get( $objProp ) ) ? true  : false;
    }

    /// unset: DOES NOTHING.This object is meant to take an act of congress to delete data
    public function __unset( $objProp ) {
        // do nothing.
        // echo '<pre>DIE IN A FIRE!!!! ' . var_export( $objProp, true ) . '</pre>';
    }


    // 
    // PRIVATE STUFF
    // 
    private $_self;             ///< the singleton instance
    private $_data  = Array();  ///< this is the data.  Just the data, and only the data.

    ///  CTOR: Singleton!
    private function     __construct( $value )  {
        self::$_data    = $value;            
    }

    /// CCTOR: Singletons have have no need to copy themselves
    private function     __clone()   {
        // do nothing
    }

    /// fetches the value from WAAAY down in the array
    private function    walk( Array &$arr, Array $keystack )   {
        $key    = array_pop( $keystack );
        if( false === array_key_exists( $key, $arr ) )   {
            return  null;
        }
        if( 0 count( $keystack ) )  {
            return  $arr[$key];
        }
        else    {
            return  walk( $arr[$key], $keystack );
        }
    }

}

0 个答案:

没有答案