Developing a Doctrine-backed ACL helper TDD-style, part 2

2009 June 20

In this second part, we will integrate Doctrine into our AccessManager helper. The database will be hit at least thrice per request: once for the rules for the requested resource, once for the global rules and at least once for the user roles. No additional tests here since I’m not sure how to approach mocking or stubbing with Doctrine and databases.
read more…

Developing a Doctrine-backed ACL helper TDD-style, part 1

2009 June 14

I figured my admin module needed to be unit tested since the code changes a lot and I’m constantly worried about breaking things in certain places while I add new features or factor out some common code. Writing tests at this point though does not follow the TDD way. I’m trying to get into this philosophy, so I’m gonna rebuild the ACL helper, this time guided by unit tests right from the start. All those code I have now aren’t fully trashed yet as I’m sure I’m going to copy-pasta a lot of those back in.

Note that I’m no expert on TDD. I’m a newbie, in fact. Don’t take anything in this post as a guideline on unit testing. I’m probably not even doing it properly. If you’re not interested in the TDD walkthrough, jump to the end and grab the (half-working) package containing a sample project.
read more…

Modular applications in ZF 1.8

2009 June 8

Modular applications are applications where big chunks of functionalities are encapsulated in module packages which can be easily shared between applications with minimal fuss. Although modules have existed in ZF for a long time, it is not really possible to reuse modules without adding a lot of glue to integrate the module with the application. The new autoloader and module bootstraps make this task easier.
read more…

Snap alpha, a ZF wrapper for PHP 5.3

2009 June 4
by monzee

Snap is a mini-framework on top of ZF inspired by the Sinatra framework. It makes heavy use of the new PHP 5.3 features to allow one to write concise code similar to Sinatra and Juno while taking full advantage of the well-tested ZF components.
read more…

New magic methods are awesome

2009 June 1
by monzee

The past couple days, I worked again on the little Sinatra-like DSL thing I mentioned before. It makes use of the new PHP 5.3 features. The ones I really love are the new magic functions __invoke and __callStatic. Invoke allows you to call an object instance like a function, e.g.


$front = Front::getInstance();
$front('/')->get(function () { echo 'hello world!'; });
// this is how my little DSL project is invoked at the moment.

and __callStatic allows you to catch all undefined static method calls, which is very handy for singletons.


class Front {
    // this is a singleton
    static public function __callStatic($method, $args)
    {
        return call_user_func_array(array(static::getInstance(), $method), $args);
    }
}
Front::setParam('foo', 'bar'); // this is the same as Front::getInstance()->setParam('foo', 'bar');

(Update: meh, I spoke too soon. The example above doesn’t pass through __callStatic if there is an instance method setParam. It works because PHP allows instance methods to be called non-statically along with a strict notice. Note to self: test first before making claims.)

In addition to singletons, __callStatic could be used in ORM or table gateway finder methods.


$user = User::findByEmail('foo@example.com');
// would return a row object
// whereas before you need to instantiate a User first before finding.

But you know what would really be nice? A combination of the two.


class Hello {
    static public function __invokeStatic($name)
    {
        echo 'Hello, ' . $name . '!';
    }
}
Hello('mon'); // Hello, mon!

It might look retarded because you could just define a Hello($name) function and accomplish the same. The reason I think this feature is reasonable is the inability to import and alias namespace functions with the use keyword. For example,


namespace greet {

class Hello {
    static public function __invokeStatic($name) {
        echo 'Hello, ' . $name . '!';
    }
}

function hi($name) {
    echo 'Hi, ' . $name . '!';
}

}

namespace somethingElse {
    use greet\Hello as hey; // you cant use greet\hi

    hey('mon'); // Hello, mon!
    \greet\hi('mon'); // Hi, mon!
}

How I wish this were possible. I dislike the namespace separator (although a lot less now than before) and I’d like to limit the use of it in the use and namespace declaration only. Also, it is easier to maintain state with a static class function rather than a namespace function because namespace variables are actually globals. These two reasons really make namespace functions undesirable for me, and I imagine others would find the same once 5.3 becomes prevalent.

Migrating applications to 1.8

2009 May 21
by monzee

Old applications should still work in 1.8 but some might want to update their applications to use the new 1.8 features such as Zend_Application and Zend_Loader_Autoloader. The reference manual describes how to write a bootstrap for Zend_Application, so head that way for a detailed description of the inner workings of Zend_Application. In this post, I’ll show how one might go about converting their old bootstraps into something usable by Zend_Application.
read more…

Access control: Why not a helper?

2009 May 17
by monzee

Every single ACL tutorial I’ve seen (not that I’ve seen many) uses controller plugins to check access to pages. People seem to be forgetting that action helpers have a preDispatch() method too, and in some ways it really makes sense to stuff ACL checking in there rather than in a plugin.

Since we’re controlling access to a controller action, doesn’t it make sense to know if the controller or action exists in the first place? Plugins are not controller-aware. In fact, the controller object doesn’t exist yet during plugin preDispatch()! If your ACL plugin happens to use a database backend, an invalid request means unnecessary database hits. Sure, you can invoke the dispatcher’s isDispatchable() method, but why do that in the plugin when the dispatcher does exactly the same shortly after the plugin preDispatch()? Since most of your requests are indeed valid, querying the dispatcher in the plugin preDispatch means an additional superfluous file stat per request. Not that I advocate micro-optimizations like these, but still… I think it’s just better to fit your code into the framework than altering the flow of events in the framework to fit your code.

It is desirable sometimes to manipulate the ACL checker at a per-controller basis. For example, one might want to disable access control on a certain controller if the user comes from a specific IP. You could probably write a permission for that special case, but it’s much simpler to just disable checking when the request hits that controller and the conditions are satisfied. The controller init() method is the perfect place to add these exemptions since it is executed right before the helper preDispatch(). In addition, you could do stuff like adding access rules to the ACL object or embed the access rules as public properties of the controller, like I do in my ACL implementation (see below). Again, you can’t do this in a plugin naturally since the controller object hasn’t been instantiated yet during the plugin preDispatch().

And finally, action helpers are easily invokable inside controller actions. It is very likely that you would want to query the ACL object inside controller actions. Your ACL object doesn’t necessarily have to be limited to permissions for controller actions. You can also set permissions for your model objects. With a helper, you can very easily pull out the ACL object and ask if the user is allowed access to a certain object. With a plugin, you probably have to assign the object to the evil registry first in order to access it in the controller.

I have put my ACL/auth implementation up in googlecode. Visit the project page and hit source->browse or download the package for an example on how to implement an action helper ACL checker.

Variables in namespaces are global!

2009 April 11
tags:
by monzee

This surprised me:


namespace foo
{
    $foo = 'foo';
}

namespace bar
{
    echo $foo; // foo
}

I was looking for a way to import a namespace variable inside a function in the same namespace and the only way I found was to use global $foo; inside the function, which I thought was defeating the whole purpose of namespaces. Then I found out that there’s no such thing as namespace variables! That makes me feel less guilty about using global, but that’s still retarded.

Extending classes via lambdas

2009 April 10
by monzee

In Javascript, you could compose an object piecemeal. For example, you can start with:

var foo = {};

Then extend this empty object by assigning lambdas to its properties.

foo.bar = function () { alert('bar'); }
foo.bar(); // bar

You can even pull a method from another object and assign it to this property.

var goo = {
    gar: function () { alert('gar'); }
};
foo.bar = goo.gar;
foo.bar(); // gar

Or a privileged method defined in a constructor:

function Xoo(x) {
    this.xar = function () { alert(x + 'ar'); }
}
moo = new Xoo('m');
foo.bar = moo.xar;
foo.bar(); // mar

This is so easy and natural because Javascript makes no distinction between methods and properties. Javascript objects can be likened to an associative array in PHP. If the array member is callable, then it is a method which can be called via its key. Otherwise, it’s just a property.

PHP isn’t quite like that, but it is possible to simulate that behavior with a bit of magic. With the new lambda syntax, it becomes even closer to the Javascript way of extending objects.
read more…

$this in closures; what gives?

2009 April 7
by monzee

This article (among others) states that it is possible to use the $this variable in a closure defined in a class method even without importing it via use(). I also read the RFC from the PHP wiki and it says the same thing. Why then does this code fail?


class foo
{
    public $bat;
    public function __construct($bat)
    {
        $this->bat = $bat;
    }

    public function bar()
    {
        return function() {
            return $this->bat;
        };
    }

    public function baz()
    {
        return $this->bar();
    }
}

Using 5.3RC1/win32, it dies when bar() is called outside or inside (via baz()) the class, saying $this is used in a non-object context. It doesn’t allow ... function() use($this) { ... either, saying that $this cannot be used as a lexical variable. What’s happening?

To work around this, right now I’m assigning $this to $self above the closure definition and appending use($self). Seems to work as expected, except that I can’t access private members (which is probably intentional and exactly the thing I was exploring when I made this test). Why can’t I just import $this directly then? And whatever happened to the auto-import they promised?

Update: Man, I totally missed this. This page is linked in the closure RFC. They should have removed that entire section in the RFC instead, like they did to the lexical keyword (I can’t seem to find it anymore, or maybe I just imagined it). I just skimmed through it (since I’ve read it before) and missed the link entirely. So $this really cannot be imported at the moment, but it appears that they might be in the future.