What is the best way to handle sessions with ADR?

Right before Christmas, I reached out to Paul Jones asking:

I’ve reached a point with a couple of my Radar projects where I need to add a login and set permissions. I’m trying to figure out the best way to handle this, especially with PSR-7 and ADR.

This led to discussing how to do sessions properly in Radar. I had read Paul’s post PSR-7 and Session Cookies which discussed how to tweak PHP Sessions to work better in a PSR-7 architecture. You don’t really want PHP automatically sending and reading cookies outside of the Request object.

Paul responded:

Finally, the more I work with separated domain layer, the more I dislike the built-in PHP session system. Lately, I have started to consider avoiding it entirely, in favor of something like a custom DomainSession. Attached are my very rough notes-in-code; maybe they’ll be useful to you.

Needless to say, they have been very useful. Paul has been incredibly generous with his time and after going back and forth through several rounds of refactoring and revising I’m ready to officially announce Cadre.DomainSession. The current version as of this post is 0.4.0.

Why DomainSession?

The reason for this package is that as Paul had said: “Anything that touches storage should be considered domain-layer work.” so it’s ok to read the session cookie in an Input class, and it’s ok to write the cookie in a Responder class, but pretty much everything else should be in the Domain layer.

For more information about Radar see Radar Under the Hood.

What does it do?

Cadre.DomainSession takes a session id (or generates one) and loads session data from storage. It’s smart enough to handle regenerating session ids and cleaning up expired sessions.

Demo

I’ve put together a small demo app using Radar and Cadre.DomainSession at radar-domain-session.

Loading the Session ID From a Cookie

Reading the session ID from a cookie is handled in the Input of your route. I used the excellent library dflydev-fig-cookies to simplify getting and setting cookies in PSR-7.

In Application\Delivery\DefaultInput I read from the SESSION_ID cookie, returning null if it doesn’t exist.

Starting, Using and Finishing the Session

In Application\Domain\Home I first inject the Cadre\DomainSession\SessionManager. Then I start the session with the session ID I passed in from the Input. I check to see if there is a timestamp session value (Unknown if not present) and assign it with the current timestamp. Finally, I finish the session which is what persists the data to storage. In this case, it’s just to the filesystem. One important thing to note is that I have to return the session object in the payload for the final step.

If you want to regenerate the session ID you can do so by calling $session->getId()->regenerate().

Persisting the Session ID in a Cookie

In Application\Delivery\DefaultResponder I check to see if there was a session in the payload. If there is, I check to see if the session ID has been updated (new or regenerated session id). If it’s been updated I persist the session ID value to the session cookie I’m reading from in the Input and that’s all there is to it.

Concerns

I have some concerns with this library. The built-in session handling has withstood the test of time. It’s been looked at and I assume many security concerns have been fixed. I’m not a security expert, so I worry that there are vulnerabilities in my code.

In particular, I’m using what I consider to be a fairly naive method for generating session IDs.

I need to do some research and find if session_create_id would be a better method to use. I’m not sure if it just generates an ID or if it depends on the storage implementation.

Summary

When you’re using ADR, it’s important to be absolutely clear what is and isn’t part of your domain. Paul considers anything that touches storage as domain-layer work. Reading and writing cookies is an implementation detail that is part of the delivery mechanism. Imagine using the same domain objects in a command line application. You wouldn’t use cookies, but perhaps you would pass a session ID in as a command line argument.

What am I missing? Do you find this implementation useful? Let me know in the comments.

UPDATE: There is also an interesting conversation going over on Reddit.

Symfony Forms and Radar – Part 2

I refactor my code from Part One and integrate Aura.Filter.

In Part 1 I talked about the difficulties in getting Symfony Forms to play nicely with Aura.Di and Radars ADR model.

Today I’m picking up where I left off. My goal is to figure out what I need to do differently to achieve the clean separation I desire.

All of my issues with Aura.Di have been resolved and my LazyArray class is currently being reviewed for inclusion in Aura.Di.

Removing Validation

The first thing I did was remove Symfony Validator from the form (and my app). I did this for several reasons.

First, my initial attempts to validate independently from the Form showed that Validator is fairly complex. There also seems to be very little documentation for using outside of Symfony. The few examples I found didn’t seem like the sort of validation I’d like to use in my projects.

Second, the point of this series is to integrate Symfony Forms, not Validator. No sense going down another rabbit hole. If you’re interested in me figuring out Symfony Validator, please contact me and let me know.

Isolating Form to the Responder

The second thing I did was move all use of the Form object to the Responder. Since I’d like to handle the Request manually and validate separately in the domain, the form can be moved to the Responder.

You can follow along with my commits here.

How I’m handling things in Input and the Domain right now are just placeholders until I get the form figured out.

I’m still calling handleRequest at this point because I haven’t figured out how to pass in the payload from the domain. I’ll do that next.

Handling Request from Payload

This was far easier than I expected. Since I’m not doing anything crazy with file uploads or anything I was simply able to submit the form directly.

Validating and Showing Validation Errors

Now that the basics are working, I can implement validation and display the validation errors with the form.

I decided to use Aura.Filter for my validation. It integrates easily with Aura.Di and fits my idea of a clean validation library.

The first step is to create a filter. This is easily done by extending Aura\Filter\SubjectFilter and overriding the init method.

Next, since I’ll need this filter in my post domain, I convert my closure into an invokable class.

I then configure the container to instantiate this filter and pass it into RegistrationPost.

Next, I apply this filter on the data I get from RegistrationInput.

Finally, I consume the payload in RegistrationResponder going through the failure messages and adding FormError objects to the correct elements.

You can see the result of this in the 2.x branch of the project repo.

Conclusion

This exercise left me with a greater understanding of Symfony Forms and Aura.Filter. I think the solution is pretty good. If I was using this in production, I’d probably refactor some of this to be more reusable, especially if I plan on defining a lot of forms. I probably wouldn’t use arrays as the data transfer mechanism. I’d also probably create a factory that takes a generic definition and generates the form, validation and entity objects that I’d be using.

I’m very interested in hearing from you. I will be creating new content over the coming weeks and I want to customize the content for YOU and help you overcome any obstacles you might be experiencing. Send me a message!

Symfony Forms and Radar – Part 1

I explore how to integrate the Symfony Form Component with Radar.

I have several projects I’d like to build soon. One thing they have in common is there will be a lot of data entry via forms. Back in the day I used to use HTML_QuickForm but I haven’t used it for a long time.

For my projects at work, one uses a custom solution I built and the other uses AngularJS. I figured it was time to look around and find a current solution.

The two I came across was Symfony Form Component and Zend\Form. I’ve used many Symfony components so I figured I’d start with theirs.

I really dig Radar but I know that not everything easily fits in the Action-Domain-Responder model.

I leveraged the Symfony Forms documentation and webmozart/standalone-forms to create my proof of concept.

Configuring a Symfony Form

I managed to get it to work but it’s not ideal (yet). To see my first proof of concept check out futureproofphp/symfony-forms-radar.

The first caveat that I want to express is that I wanted to leverage as much of what Symfony Forms has to offer much of which is optional. My final solution may omit parts of this.

The first issue I found was with having to use multiple setters to build objects.

Symfony Translation Component uses addLoader and addResource to be configured correctly. FormFactoryBuilder and Twig_Environment use addExtension.

Aura.Di doesn’t really handle this use case. You can define a single parameter to be passed to the setter method. The was around this is with the two pass system. In a ContainerConfig you have two methods, define and modify. The first part define is where you define all of your dependencies. You should not be instantiating anything in this method other than LazyInterface objects. The second part modify actually takes an instantiated object from the container and further modifies it. Ideally, you’d do as much as possible in define so you’re not instantiating objects that you’re not actually using.

I was able to work around this using two strategies.

The first was to find or create setters that can take an array of objects instead of having to call the single method multiple times in the container. FormFactoryBuilder already has addExtensions that I can use, but Translator needed to be extended so I could have addLoaders and addResources methods. Twig_Extension has setExtensions but I was unable to use that (I’ll explain why later).

The only issue with this strategy was that if I included LazyInterface objects in an array, they didn’t get resolved when the setter was called.

This leads to my second strategy which was the creation of a new LazyInterface class LazyArray which takes an array as a parameter and resolves any LazyInterface objects within it, returning an array with the resolved objects.

Now, why wasn’t I able to use the setExtensions method from Twig_Environment? Circular dependencies.

The Twig_Environment extension FormExtension requires a TwigRenderer which requires a TwigRendererEngine which requires the Twig_Environment. Aura.di can’t resolve this.

The way around it is either to not use that extension, or to configure the Twig_Environment extensions in modify. I chose the second option.

Update!

After more digging, I found that calling setEnvironment on the TwigRendererEngine is not required. I had done it because that’s how it was done in the webmozart tutorial but then I noticed that setEnvironment is called from FormExtension::initRuntime. This makes sense because since it’s a Twig extension, shouldn’t it already know the Twig_Environment?

Once I removed this setter from the container, I was able to move the configuration of Twig extensions back into define.

Using the Form

Now that I got everything configured in the ContainerConfig I need to use the form I created. The issue I quickly ran into is that a single form does a whole lot of stuff.

First, the form handles the request. By default, it pulls data out of $_POST but can be configured via an extension to take an HTTP Foundation Request object.

Then, the form validates this input and will return the filtered/sanitized output via the getData method.

Lastly, through the Twig the form is rendered, prepopulated with data and any validation errors.

If you’re not familiar with Radar check out my post Radar Under the Hood where it talked in depth how it works.

The problem here is that the whole point of Radar is to separate your concerns.

For my form to work, I create the form in the input and call handleRequest. I return the form so it’s passed on to the domain.

In the domain, I’d check if the form was valid and potentially do something with the data. I return the form as the payload for the responder.

In the responder, I render the form in twig template and return the PSR-7 Response.

I don’t like that I need to have a single form object that’s passed through all three layers just to render a form.

Ideally, it would work more like this.

In the input, I’d pull out the values from the PSR-7 Request and return an array or domain request object with the data.

In the domain, I’d validate the data from the input and do something with the data if valid. I’d return a domain response to the responder that contained the filtered/sanitized data and any validation error messages I generated.

In the responder, I’d take the domain response and feed it into a form object that is then passed into a twig template for rendering. I’d return the PSR-7 Response.

Conclusion

I haven’t given up on this yet (hence the “Part 1” in the title of this post).

My next step is to look at the components and extensions being used in my proof of concept and see what they are doing and if there are ways to pull them apart.

For instance, I’m creating a Validation object that gets passed into the form via the ValidationExtension. I’m assuming I can define my validation separately, but I’ll have to research how to assign validation error messages to the form externally.

If validation is separate, I can probably pass in an array of data to be validated, instead of having the validator pull data directly from the request.

However, this post is already very long, so I’ll save the rest for Part 2.

Radar Under the Hood

I explain what Radar and Action-Domain-Responder are and how they work.

Radar is a project that I really like.

Radar is a PSR-7 compliant Action-Domain-Responder (ADR) system. While it may look like a micro-framework, it is more like a wrapper around the real core of your application domain.

Have your eyes glossed over yet? Don’t worry. Radar is actually very simple to use, especially once you understand what’s happening under the hood.

Today, I’d like to give you a quick tour under the hood to explain the libraries that Radar glues together and what that whole Action-Domain-Responder thing is.

Action-Domain-Responder (ADR)

Action-Domain-Responder or ADR is a pattern defined by Paul M. Jones as a refinement of Model-View-Controller or MVC which you may have heard of.

Action

In MVC frameworks you’re typically calling “Actions” within a “Controller”. If you look at the examples on the Symfony page for Controller you’ll see that you have a method numberAction within LuckyController. In ADR the action is the minimal glue that holds your application requests together.

Domain

The domain is the core code in your application that actually does the work. The idea is that this code is specific to your application. If you’re familiar with Clean Architecture from Uncle Bob, the domain entails the Use Cases (Application Business Rules) and Entities (Enterprise Business Rules) in your application. The domain shouldn’t know or care how its response is being presented to the user. It could be an HTML web page, a REST API, a command line tool, or unit test.

Responder

The responder takes a response from your domain and formats the actual response to the user. This could be done via a template system like Twig or JSON encoder.

How Radar does ADR

When you first go through the Radar documentation (which is very nice). The first question I asked myself is “Where’s the Action?”

You direct routes to Domain objects, and per route, you can define Inputs and Responders. If this is Action-Domain-Responder shouldn’t I be creating Actions?

Radar (or more specifically Arbiter) actually creates the Action for you. Remember where I mentioned that Actions are minimal glue? Radar takes that seriously.

An Arbiter\Action is simply a data object that contains three callables the Input, Domain, and Responder.

Then there is an Arbiter\ActionHandler which does the work.

First, a PSR-7 Request is passed into the Input and it returns the parameters for the Domain.

Then, the parameters are passed into the Domain and a payload is returned.

Finally, the responder is passed the payload along with the PSR-7 Request and Response.

Here is the actual code:

So What Does Radar Do?

It bootstraps the application using Aura.Di, dependency injection container.

It exposes Aura.Router to actually map paths to Arbiter Actions.

The whole thing is delivered as Relay (a PSR-7 middleware dispatcher) middlewares that do a lot of the work.

RoutingHandler takes the Input, Domain, and Responder values from the route and creates the Action.

ActionHandler then takes the Action created by RoutingHandler and handles it with the Arbiter\ActionHandler.

What Next?

If you’re interested in watching me demo Radar, you can watch my video FutureProof Your Code where I talk about Clean Architecture and how to use Radar.

I’m also very interested in hearing from you. I will be creating new content over the coming weeks and I want to customize the content for YOU and help you overcome any obstacles you might be experiencing. Send me a message!

FutureProof Your Code

A presentation I have at Milwaukee PHP on how to architect your code so it will withstand the tests of time.

Frameworks, libraries, and components are great. They can greatly simplify the process of writing applications. There is no need to reinvent the wheel. However what happens when the landscape changes? Your favorite library is no longer supported. The framework you’ve built your application on is no longer receiving updates. How you react to this news greatly depends on how you’ve built your application.

In this talk, Andrew Shell will cover how to architect your applications to allow you to leverage all the power from these tools without exposing your application to unnecessary risk. He’ll also demo how you can use Radar, a library that can make it easier to build your application in a future-proof way.

Code available: github.com/andrewshell/radar-fig-demo

This talk was recorded at Milwaukee PHP on 3/8/2016.