Symfony2 comes with an ACL mechanism that can help you whenever you need to add some permissions in your system. Some typical use cases could be to determine if a user has the permission to edit a blog post, if he can add a comment to it or if he can delete it or simply view it. In such cases ACL system seem to be the way to go in order to implement all these rules and future existing ones in a flexible manner.

Unfortunately we came across a situation where we had to do this kind of permission check on a very long list of items. Think of a page listing all your blog posts for instance. If you have a couple of it them all is fine. As soon as you start having hundreds or more of them on one simple page, then you will sooner or later hit the wall. Performance will go bad (or very bad in our case) and as the system keep storing more and more of the same kind of data it become slower and slower.

The normal way an ACL check is performed is to issue a sql statement to the database and them observe the return value to figure out if the permission is granted or not. When you start doing this kind of verification on large amount of objects you will inevitably generate a large amount of query to your database. Even worse than that. You will at the same time generate as many round-trips between your application and the database. Just in case you wanted to add insult to injury.

Luckily for us Sf2Ā  ACL system provides a way out of this. You can in a small amount of query load all the ACLs that are related to some given objects. Once this ACL data are loaded the system keeps them (for the time of the request) and use (or reuse them) whenever it needs them. Here is how to implement it.

private function loadBlogPostsAcls($blogPostRepository)
{
    $oids = array();

    foreach ($blogPostRepository->findBy(array(), array('date' => 'asc')) as $blogPost) {
        $oids[] = ObjectIdentity::fromDomainObject($blogPost);
    }

    $this->aclProvider->findAcls($oids);
}

This function is quite trivial to understand. It builds an array of object identities($oids) by looping over all the blog posts found in the database. Once we have this [potentially long] list of object identities we just have to call the method findAcls from the ACL provider. This one will batch load all ACL relative to these objects.

The findAcls is quite smart in its way to fetch the ACL data. It doesn't build just one gigantic query to load everything in one go but rather walk its way through the $oids fetching data by packet (for example, 50 items at a time).

When this is done you will have all ACL data about those blog posts loaded in the system and you can later on perform any kind of check you fancy. It will be fast and it won't go to the database any more to figure out if your user has permission to edit/view/delete your object.