Things I miss in PHP: Function decorators


The problem:

I want to build a set of classes accessible via REST interface. One example here with ZF. My idea is allow users to access via REST to my set of classes. It’s no so difficult. But the problem appears when I want to set an authorization engine to my REST web service. Public functions can be called but sometimes user must be authenticated (with a trusted cookie).

I have my class:

class Lib_Myclass
{
    public function publicFunction($var1)
    {
        return "Hello {$var1}";
    }

    public function privateFunction($var1)
    {
        return "private Hello {$var1}";
    }
}

publicFunction can be called without login but privateFunction only after login

I have done similar with python and Google App Engine. With python I use decorators and its very clean and easy

class Myclass:
    def publicFunction(self, var1):
        return "Hello %s" % var1

    @private
    def privateFunction(self, var1):
        return "private Hello %s" % var1

And I define my decorator ‘private':

def private(funcion):
    def _private(*list_args):
        if isValidUser():
            valor = funcion(*list_args)
        else:
            value = ('You must be logged')
        return value
    return _private

Really simple and clean. But in PHP I don’t know how to do it in a simple way. I don’t want to do reflections in every call and check if the function is allowed or not.

My solution:

Instead of having one class with public and private functions I divide it in two classes: one for the public function and another one for the private (private here means logged sessions not private keyword in PHP).
I also create two empty Interfaces PublicAccess and PrivateAccess and using PHP’s instanceof I can throw an exception if user without login tries to call any function in a class with the interface PrivateAccess

interface PublicAccess{}
interface PrivateAccess{}

class Lib_Myclass1 implements PublicAccess
{
    public function publicFunction($var1)
    {
        return "Hello {$var1}";
    }
}

class Lib_Myclass2 implements PrivateAccess
{

    public function privateFunction($var1)
    {
        return "private Hello {$var1}";
    }
}

I prefer the python’s solution

About these ads

About Gonzalo Ayuso

Web Architect specialized in Open Source technologies. PHP, Python, JQuery, Dojo, PostgreSQL, CouchDB and node.js but always learning.

Posted on December 9, 2009, in php. Bookmark the permalink. 7 Comments.

  1. Have you ever tried looking at these PHP functions?

    http://php.net/func_get_args

    and

    http://php.net/func_num_args

    Using these two functions you can easily simulate argv/argc variable lists in PHP. I hope this helps.

    • with those functions I can have functions with n arguments I cannot get the python’s decorators (at least as I know)

  2. Yeah, PHP definitely doesn’t have decorators or annotations; however, I have been playing around with the idea of using phpdoc comments to add decorators. phpdoc comments are accesible via the getDocBlock() method in the ReflectionMethod class. You would have to do some parsing, but it’s not to hard to setup a system like that.

    • Yes. The only problem I see with this method is you cannot call directly to the functions. Each time you call one function you must use reflection. I don’t know the performance of that solution. ZF uses something similar to build XMLRpc servers and Zend studio uses phpdoc to allow autogenerate WSDL files from a class.

  3. I usually solve this problem in a higher level of the application than the class itself. I have some common ‘dispatch’ function that I pass the module name, function, and params to. It then checks an access control list to see if that user has access to execute that function on that module. If not, an authentication exception is thrown. It’s really the only way to do it without an extra function call for checking authentication in each function you want to protect.

    • Internally python’s decorators are the “extra function call” that you said but with a elegant interface.
      As you said create a higher level to dispatch functions is other possibility. I also use it sometimes but last days I prefer things as simple as I can (less code, less mistakes ;) ). Those kind of wrappers in classes turn my classes into something different than a simple plain class. Maybe it’s difficult to explain. I want to create classes with ‘new’ or maybe with a simple factory or singleton and call then as the examples in chapter 1 of PHP’s OO. Something that don’t need any documentation.

  1. Pingback: Inject dependencies via PhpDoc « Gonzalo Ayuso | Web Architect

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

Join 992 other followers

%d bloggers like this: