Reviewing my first Symfony2 project
History
In 2012 I built my first Symfony2 project. The most recent version
back then was 2.0.12 which I figured out from the now deprecated /deps
file.
1 | [symfony] |
This project was part of my internship where I was given a LAMP stack to deploy
on. I chose Symfony because of the resemblance with ASP.NET MVC which I used
on a previous project and enjoyed working with.
Deployment
I used SVN before but I wasn’t familiar with GIT. The project was under version
control but the only version I found is the zip file I handed over at the
end of my internship.
If this project requires further development, it would be a good idea to put
it under version control. The vendor folder can be excluded together with
the nbproject that somehow snuck into the zip file. Because 2.0 lacks
composer, the command to install vendors is different from what I’m used to
but the workflow stays the same: php bin/vendors install
I had to download the missing .gitignore file from the symfony-standard
repository. After running git init; git add .
in the root of the project,
further changes can be tracked.
After changing the /app/config/parameters.ini file, creating the database
and running php app/console doctrine:schema:update --force
, the project is
available in my local development environment. The Apache and PHP config that I
use for more recent projects seems to do the job, no tweaking required. Just to
be sure, I checked /web/config.php, it did not complain.
The Application
Missing data
Clicking through the website I ran into the following errors:
- There are no questions!
- Can’t find any question catergories!
Other pages just show a blank area where a list of options should appear. For
example: when starting an assessment you should be able to pick an opleiding
but none are presented.
There are 2 measures we can take to counter these issues.
First of all, showing sensible messages when data is missing to properly render
views. Depending on the role of the user and their ability to add content, you
can point them in the right direction and guide them through their first
encounter with the application.
A second solution is seeding the project with the help of Doctrine fixtures.
These fixtures can be run on command so they are extremely helpful if you mess
up your data or you quickly need the dummy content.
Bulky controllers
The controllers in this project ended up being quite bulky. Looking back, they
provide plenty of examples where improvements can be made.
Form classes
Instead of defining forms inside the controller they can be defined in separate
form classes that can directly map to existing model entities or view models.
This way we can consolidate duplicate code in controllers and compose more
elaborate forms by combining different form classes.
Repositories
Another way of keeping controllers dry is creating custom repository classes to
persist and retrieve entities.
The following controller action code looks for all assessments created between
a begin and end date.
1 |
|
This Query can be moved to a repository class where we define it as a function.
1 |
|
We can then replace the query in the controller action with the repository
function.
1 |
|
Keep domain logic inside the model
The following controller action code takes a list of category groups, which
can contain overlapping categories, matches them against a list of all the
existing categories and builds a set with unique categories to create an
assessment.
1 |
|
You don’t want the repository call and http request logic to end up in the model.
The following code will match the requested group IDs against existing
category groups.
1 |
|
Further down in the action, the category groups are added after the assessment
object is created. Instead of just passing the groups to the constructor, all
their categories were reduced to a set to use as parameter.
1 |
|
You should be able to create an assessment by passing the groups and let
the constructor deal with them. The model should decide if duplicate categories
are allowed without involving the controller for any domain logic.
1 |
|
Managing Dependencies
Back-end
Switching to Composer would make it easier to manage security updates. This
requires updating Symfony to at least v2.1. Going for v2.3 will get you
long-term support and makes sure you are only running stable versions of external
dependencies. This project does not rely heavily on third-party bundles so upgrading
should not be that hard by following the Symfony upgrade guide.
Front-end
Javascript libraries are stored in the OAT bundle. This creates unneeded bloat
in the repository and requires you to downloaded and add them manually.
For more recent projects I’m using Bower and it makes
developing with small javascript libraries so much easier. You can copy over a
list of dependencies from existing projects and running bower install
will
get the locally cached files or download them when needed. Assetic can still be
used to minify everything to a single file.