A collection of more than 250 articles about Software Design & Development Best Practices.
With code samples for PHP/Symfony and Fortran applications.
Symfony2 & MongoDB ODM: Creating custom types with dependencies
With Doctrine MongoDB ODM it is possible to add custom field types and define how its values should be converted from and to the database. But type management in the MongoDB ODM currently suffers from several design flaws. This makes it non-trivial to create a custom type, especially when your type conversion has any dependencies. This is how it works:
use Doctrine\ODM\MongoDB\Mapping\Types\Type;
Type::registerType('custom', 'Matthias\CustomTypeBundle\MongoDB\Type\CustomType');
$type = Type::getType('custom');
// $type is an instance of Matthias\CustomTypeBundle\MongoDB\Type\CustomType
As you will understand, the Type class is both a Registry and a Factory. Yet, it only allows you to define a type as a class, not as an object. This means: no constructor arguments can be passed. When using Symfony2, this implies that types can not be services, and you can use neither constructor nor setter injection.
Symfony2: Introduction to the Security Component part III
Please note: I have revised this article to become part of the official documentation of the Security Component.
Authorization
When any of the authentication providers has verified the still unauthenticated token, an authenticated token will be returned. The authentication listener should set this token directly in the SecurityContext using its setToken() method.
From then on, the user is authenticated, i.e. means identified. Now, other parts of the application can use the token to decide whether or not the user may request a certain URI, or modify a certain object. This decision will be made by an instance of AccessDecisionManagerInterface.
Symfony2: Introduction to the Security Component part II
Please note: I have revised this article to become part of the official documentation of the Security Component.
Authentication
When a request points to a secured area, and one of the listeners from the firewall map is able to extract the user’s credentials from the current Request object, it should create a token, containing these credentials. The next thing the listener should do is ask the authentication manager to validate the given token, and return an authenticated token when the supplied credentials were found to be valid. The listener should then store the authenticated token in the security context:
Symfony2: Introduction to the Security Component part I
Please note: I have revised this article to become part of the official documentation of the Security Component.
The Security Context
Central to the Security Component is the security context, which is an instance of SecurityContext. When all steps in the process of authenticating the user have been taken successfully, the security context may be asked if the authenticated user has access to a certain action or resource of the application.
use Symfony\Component\Security\SecurityContext;
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
$context = new SecurityContext();
// authenticate the user...
if (!$context->isGranted('ROLE_ADMIN')) {
throw new AccessDeniedException();
}
A firewall for HTTP requests
Authenticating a user is done by the firewall. An application may have multiple secured areas, so the firewall is configured using a map of these secured areas. For each of these areas, the map contains a request matcher and a collection of listeners. The request matcher gives the firewall the ability to find out if the current request points to a secured area. The listeners are then asked if the current request can be used to authenticate the user.
Symfony2 Security: Using advanced Request matchers to activate firewalls
In the Symfony2 security documentation both the firewalls and the access control rules are demonstrated using the “path” option, which is used to determine if a firewall or rule is applicable to the current URL. Also the “ip” option is demonstrated. The fact of the matter is, the string based configuration options in security.yml are transformed into objects of class RequestMatcher. This is a curious class in the HttpFoundation component which allows you to match a given Request object. The Security component uses it to determine if it should activate a certain firewall for the current request (usually only by checking the request’s path info).
Symfony Security Component & Silex: Adding a security voter for domain names
The Symfony Security Component has an AccessDecisionManager which decides whether or not the currently authenticated user has a right to be in some place (or for that matter, use a certain service from the service container, or even call a certain method). The decision manager looks at the current user’s roles, and compares them to the attributes that are required. It relies on dedicated voters to make it’s verdict.
The component itself ships with an AuthenticatedVoter. It supports the “IS_AUTHENTICATED_FULLY”, “IS_AUTHENTICATED_REMEMBERED” and “IS_AUTHENTICATED_ANONYMOUSLY” attributes, which allow you to differentiate between users who are authenticated in the normal way, via a “remember me” cookie, or anonymously (which means: no credentials were supplied, but the user still gets a security context).
Symfony2 Security: Creating dynamic roles (using RoleInterface)
The Symfony Security Component provides a two-layer security system: first it authenticates a user, then is authorizes him for the current request. Authentication means “identify yourself”. Authorization means: “let’s see if you have the right to be here”.
The deciding authority in this case will be the AccessDecisionManager. It has a number of voters (which you may create yourself too). Each voter will be asked if the authenticated user has the right “roles” for the current URL.
Silex: Using HttpFoundation and Doctrine DBAL in a Legacy PHP Application
In my previous post, I wrote about wrapping a legacy application in Silex, using output buffering and Twig. Finally, to allow for better decoupling as well as lazy loading of services, we passed the actual Silex\Application instance as the first argument of legacy controllers.
The first and quite easy way we can enhance our legacy application, is to make use of the request service (which contains all the details about the current request, wrapped inside the Symfony HttpFoundation’s Request class). So, instead of reading directly from $_GET and $_POST, we can change the edit_category() controller into the following:
Let Silex Wrap Your Legacy PHP Application (and add Twig for templating)
Ever since I am using the Symfony Framework (be it version 1 or 2), I tend to describe every other project I’ve done (including those that were built on top of some third party “framework” like Joomla or WordPress) as a “legacy project”. Though this has sometimes felt like treason, I still keep doing it: the quality of applications written using Symfony is usually so much higher in terms of maintainability, security and code cleanliness, that even a project done last year using “only PHP” looks like a mess and seems to be no good software at all. So I feel the strong urge to rebuild everything I have in portfolio (as do many other developers), but “this time, I will do it the right way”.
Symfony2: Testing Your Controllers
Apparently not everyone agrees on how to unit test their Symfony2 controllers. Some treat controller code as the application’s “glue”: a controller does the real job of transforming a request to a response. Thus it should be tested by making a request and check the received response for the right contents. Others treat controller code just like any other code - which means that every path the interpreter may take, should be tested.