SitePoint Sponsor

User Tag List

Results 1 to 8 of 8
  1. #1
    SitePoint Zealot
    Join Date
    Nov 2005
    Posts
    181
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    equivalent of Python descriptors in PHP?

    Hi all,

    Is there something equivalent of Pythons descriptors in PHP5?

    I'm working on a pretty advanced data abstraction layer in PHP5 that makes heavy uses of the languages OOP to create data models. There's more to it than this but I'm having some problems.

    This code gives me a parser error in the same line as $username is defined.
    PHP Code:
    class User extends Model {
        
    $username stringProperty($verbose_name="Username"$name="username"$validator=checkAvailability$required=True);
        
    $email emailProperty($verbose_name="Email address"$name="email"$required=true);

    }

    $user = new User();
    $user->username="Hannson";
    $user->email "root@localhost";
    $user->put(); // insert to the database


    In other words. $username has an "is a" relationship with stringProperty

    I want the properties (stringProperty, emailProperty, etc...) to define the behavior and requirements for the models attributes.

    The constructor of Model

    I'm thinking, I could probably use __set() in the Model superclass so that it sends the data to holds the value and validates it when changed.

    Any thoughts?
    Is there something equivalent of Pythons descriptors in PHP5?

  2. #2
    SitePoint Wizard silver trophy kyberfabrikken's Avatar
    Join Date
    Jun 2004
    Location
    Copenhagen, Denmark
    Posts
    6,157
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    You can't do that in PHP. Classes must be fully defined at compile time.

    You basically have the choice between code generation and some kind of runtime mechanism (Eg. use __get/__set)

  3. #3
    SitePoint Zealot
    Join Date
    Nov 2005
    Posts
    181
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Damn ...

    Then I must find some other solution....

    Thanks for the reply though!

  4. #4
    PHP/Rails Developer Czaries's Avatar
    Join Date
    May 2004
    Location
    Central USA
    Posts
    806
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by kyberfabrikken View Post
    You can't do that in PHP. Classes must be fully defined at compile time.

    You basically have the choice between code generation and some kind of runtime mechanism (Eg. use __get/__set)
    This is one aspect of PHP that has always annoyed me greatly. Oh well, maybe in PHP6, though very doubtful...

  5. #5
    SitePoint Wizard silver trophy kyberfabrikken's Avatar
    Join Date
    Jun 2004
    Location
    Copenhagen, Denmark
    Posts
    6,157
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Czaries View Post
    This is one aspect of PHP that has always annoyed me greatly. Oh well, maybe in PHP6, though very doubtful...
    Don't hold your breath. And yes, I find it rather weird that PHP - such a dynamic language - has such an inflexible object system.

  6. #6
    SitePoint Addict
    Join Date
    Feb 2007
    Posts
    251
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    An example of the get/set magic approach --

    http://www.sitepoint.com/forums/show...33&postcount=8

  7. #7
    SitePoint Zealot
    Join Date
    Nov 2005
    Posts
    181
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I'm currently working on something similar to the approach posted by cuberoot.

    Here's a pretty raw code that shows how I'll accomplish this requirement. I haven't tried to run this code so far, this is just something I threw up while typing the reply.

    PHP Code:
    class Model
    {
        
    $attributes = Array();

        function 
    __get($property)
        {
             return 
    $this->$property->get();
        }

        function 
    __set($property$value)
        {
              
    $this->$property->set($value);
         }
    }

    class 
    Property {
        
    $owner
     
        
    function Property(&$owner)
        {
          
    $this->owner $owner// Model instance
         // initialize stuff
        
    }
        
        function 
    get()
        {
             
    $attr_name $this->attr_name();
             return 
    $this->owner->attributes[$attr_name];
        }

        function 
    set($value)
        {
           
    $attr_name $this->attr_name()
          
    $this->owner->attributes[$attr_name] = $this->validate($value);
        }
    }




    class 
    User extends Model
    {
       
    $username;
       
    $firstname;

       function 
    User()
       {
         
    $this->username = new StringProperty($owner $this);
         
    $this->firstname = new StringProperty($owner $this);
       }
    }

    $user = new User();
    $user->username "Hannson";
    /* 
    This will invoke the __set method defined in Model

    A simple flowchart of this would be something like:

    $user->username = "Hannson";

    invoke __set('username', 'Hannson') inherited from Model

    invoke the set('Hannson'); method in $username (an instance of StringProperty)

    write the value into the $attributes[] array owned by the User class
    */ 
    Of course there'd be more error checking etc... but that's pretty much the idea...


    Do you think this will work or am I going down an empty street?

  8. #8
    SitePoint Enthusiast
    Join Date
    Feb 2008
    Posts
    33
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Seems like it would work, you'd probably want the model to have an array of allowed parameters and to throw an exception if something else is passed to __get or __set, something like this:

    PHP Code:
    <?php
        
    class Model
        
    {
            protected 
    $props = array();

            public function 
    __get($name)
            {
                if(!isset(
    $this->props[$name]))
                    throw new 
    Exception('Unknown property');

                return 
    $this->props[$name];
            }

            
    //set is similar so I've left it out
        
    }

        class 
    SomeTable extends Model
        
    {
            protected 
    $props = array('email''first_name''last_name');
        }
    you could also implement those "stringProperty" or "emailProperty" functions as member functions of the base model class that help buildup the $params hash (i.e. with validation requirements, data type requirements etc.) and having the sub-class call them from the constructor.


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
  •