I think you'll have gathered by now that on this blog we're particularly fond of Symfony. 😛
The robustness and versatility of this framework (I should almost say ecosystem, by the way), we've already talked about here Well, I suppose for this time that the principle I'm going to present also exists in other frameworks, but again, it's really simple to use in Symfony.
This principle is workflow. If you're used to working in an English-speaking context, a workflow is simply a set of steps on a given project or task, with a precise, defined order.
It's exactly the same thing here: we're going to look at how to define predetermined steps in the flow of a system.
Let me give you a concrete example:
You're working on an e-commerce business and your orders are sent by parcel to the four corners of the world (what? That's an example, we might as well be ambitious 😛 ).
It goes without saying that your parcels are all in several different "states". Those in preparation, those ready to be taken away, those being delivered and those delivered.
This is where workflow comes into its own. Your main constraint in terms of code is simple: a package cannot skip a step, nor can it go backwards.
In a standard scenario, you'd have to manage this with a whole bunch of conditions, to check that each time a package is modified, its state is always consistent with the previous one.
Those of you who can see what I'm talking about must have a multitude of "ifs" flashing before your eyes. 😛
Symfony's Workflow is going to be a great help!
Well, before I explain in detail, I'm going to refer you to the Symfony documentation, which is very well done on this subject:
Workflow is a Symfony component that can be installed and configured like any other package/library via Composer and a yaml file.
As presented in the doc, we'll define "places" that will correspond to our different package states, then we'll also need to create "transitions" which, as the name suggests, will allow us to move from one state to another. 🙂
What happens next? Well, thanks to the interactions between your entity's getters/setters and the previously defined configuration, Symfony will automatically check that what you (or your system) are trying to do is actually possible and authorized.
It will therefore reject a change of state from "in preparation" to "delivered". You'll first have to go through the "ready for shipment" and then the "delivery" stages.
By going even further in the configuration, you can also add a notion of user rights. Can only a site administrator say that a parcel has been delivered? Then only those with this role will be able to pass this stage of the workflow.
Obviously, like many of the tools offered by Symfony, the main benefit is time saving. As I said in the introduction, there are no more ifs or nested ifs to manage this or that use case. A simple configuration file and a notion of event listeners now suffice to manage all basic security.
This also adds a certain robustness to your application and your entire system. If the rules change during your project's lifecycle, it will be easy to readapt your workflow. Likewise, if new user types are created, their rights can be easily assigned on a point-by-point basis. But you should already know this, because it's the heart of the security component in Symfony 😛.