SitePoint Sponsor

User Tag List

Results 1 to 5 of 5

Hybrid View

  1. #1
    SitePoint Zealot Amenthes's Avatar
    Join Date
    Oct 2006
    Location
    Bucharest, Romania
    Posts
    143
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Lightbulb Javascript style PHP with PHP 5.3.0

    Hi guys, as you probably know, PHP 5.3.0 has great chances of bringing anonymous functions and closures to PHP. So I decided to play a little bit with this and inspired by the Javascript language I've tried to implement some kind of prototypal functionality. Although on the RFC page it is listed as a misconception the thing that I've done, I felt that I should try it.

    So here's what I've done so far:

    Code PHP:
    <?php
     
    class Object
    {
        /**
         * Holds functions assigned to PROTOTYPE
         */
        protected static $_classMethods    = array();
     
        /**
         * Holds properties assigned to PROTOTYPE
         */
        protected static $_classProperties = array();
     
        /**
         * Holds functions assigned to THIS instance
         */
        protected $_instanceMethods        = array();
     
        /**
         * Holds properties assigned to THIS instance
         */
        protected $_instanceProperties     = array();
     
        /**
         * Flag that tells whether to assign to PROTOTYPE or to INSTANCE
         */
        protected $_usePrototype = false;
     
     
        public function __get($property)
        {
            if ($property === 'prototype') {
                $this->_usePrototype = true;
                return $this;
            } else {
                if (array_key_exists($property, $this->_instanceMethods)) {
                    return $this->_instanceMethods[$property];
                }
                if (array_key_exists($property, $this->_instanceProperties)) {
                    return $this->_instanceProperties[$property];
                }
                if (array_key_exists($property, self::$_classMethods)) {
                    return self::$_classMethods[$property];
                }
                if (array_key_exists($property, self::$_classProperties)) {
                    return self::$_classProperties[$property];
                }
     
                return $this->$property;
            }
        }
     
        public function __set($property, $value)
        {
            if ($property === 'prototype') {
                throw new Exception('Cannot assign to prototype');
            }
     
            if ($this->_usePrototype) {
                if ($value instanceof Closure) {
                    self::$_classMethods[$property] = $value;
                } else {
                    self::$_classProperties[$property] = $value;
                }
     
                $this->_usePrototype = false;
            } else {
                if ($value instanceof Closure) {
                    $this->_instanceMethods[$property] = $value;
                } else {
                    $this->_instanceProperties[$property] = $value;
                }
            }
        }
     
        public function __unset($property)
        {
            unset($this->_instanceMethods[$property]);
            unset($this->_instanceProperties[$property]);
            unset(self::$_classMethods[$property]);
            unset(self::$_classProperties[$property]);
        }
     
        public function __call($method, $args)
        {
            $args = array($this) + $args;
     
            if (array_key_exists($method, $this->_instanceMethods)) {
                return call_user_func_array($this->_instanceMethods[$method], $args);
            }
            if (array_key_exists($method, self::$_classMethods)) {
                return call_user_func_array(self::$_classMethods[$method], $args);
            }
     
            return call_user_func_array(array($this, $method), $args);
        }
    }

    Examples:

    Code PHP:
    <?php
     
    $A = new Object;
    $A->prototype->foo = function($this) {
        return 'foo in prototype';
    };
     
    $A->prototype->bar = 'bar in prototype';
     
    $A->foo = function($this) {
        return 'This should only be in $A';
    };
     
    echo $A->foo();
    echo '<br>';
    echo $A->bar;
    echo '<br><br><br>';
     
     
    $B = new Object;
    echo $B->foo();
    echo '<br>';
    echo $B->bar;
    echo '<br>';
    $B->foo = function() {
        return '<b>foo of instance B</b>';
    };
    $B->bar = '<b>bar of instance B</b>';
    echo $B->bar;
    echo '<br>';
    echo $B->foo();
     
     
    echo '<br><br><br>';
    echo $A->foo();
    echo '<br>';
    print_r($A->foo);
     
     
    $B->prototype->baz = function() {
        return 'Hello, I\'m baz';
    };
     
    $A->foo;
     
    echo '<br><br><br>';
    echo $A->baz();
    echo '<br>';
    echo $B->baz();

    One WTF factor of the above is that the instance variable "$this" is passed as a first argument to the functions and not already available. It's a little bit Pythonic I think.

    So, what do you think? I hope you have a snapshot of PHP 5.3.0 from http://spans.php/net so that you can play a bit with these, they're great and we may provide some valuable feedback to the devs. I can't wait for this version to go mainstream. Closures + namespaces + phar will totally change the way we do PHP. Yet, one question bothers me... who needs the dollar anymore?!
    I'm under construction | http://igstan.ro/

  2. #2
    . shoooo... silver trophy logic_earth's Avatar
    Join Date
    Oct 2005
    Location
    CA
    Posts
    9,013
    Mentioned
    8 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Amenthes View Post
    ...Yet, one question bothers me... who needs the dollar anymore?!
    Having a dollar symbol "$" to distinguish variables from everything else is a good thing! (IMO) There would be a lot more overhead and restrictive naming schemes you could use, for instance. How would you tell constants (not always case-sensitive btw) apart from vars? :P

    Phar is already available in PHP < 5.3 too, I made a thread a bit ago just about that too
    Logic without the fatal effects.
    All code snippets are licensed under WTFPL.


  3. #3
    SitePoint Zealot Amenthes's Avatar
    Join Date
    Oct 2006
    Location
    Bucharest, Romania
    Posts
    143
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    logic_earth, actually I was aware of what you said, and you are right, in PHP it would probably be hard to tell them apart. Javascript though allows the same naming scheme for variables and constants (I'm talking about the Mozilla implementation of constants), yet it doesn't have classes...

    Anyway, I think it may appear naming conventions for lambdas.
    I'm under construction | http://igstan.ro/

  4. #4
    . shoooo... silver trophy logic_earth's Avatar
    Join Date
    Oct 2005
    Location
    CA
    Posts
    9,013
    Mentioned
    8 Post(s)
    Tagged
    0 Thread(s)
    Also! Having the $ makes it easier for editor to do syntax coloring :3

    I'm currently working on a few things to to rewrite PHP's internal functions to standardize the naming conventions and argument ordering. Also integrating UTF-8 support into them. (Thank you namespaces!) I'm wanting to find a use for "__invoke" too.
    Logic without the fatal effects.
    All code snippets are licensed under WTFPL.


  5. #5
    SitePoint Wizard bronze trophy
    Join Date
    Jul 2008
    Posts
    5,757
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Slick.


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •