So a few weeks ago I started in on a ground-up rewrite of an existing project. Its currently using a framework that based around my CWFC libraries. It works very well, but its starting to show its age. As more and more features got added to the project, things have gotten more and more cumbersome to maintain in a clean way. I started off by ripping out all of the backend code and migrating it to C++ (see my posts on Protocol Buffers here and here), leaving only the front-facing code left to work with.
The motivation behind the project rewrite is twofold. First, modernize the UI and make it more consistent. As more and more features got added, both the code and the interface became a bit disjointed, and not at all uniform. There are “edit” icons in some places, and other places you have to click on a slug, some libraries are class based, while others are flat collections of functions. While it all works, its far from ideal. Its also feels like an older site. While that doesn’t have any impact on functionality, its a perception issue from those using it. So the first objective is to make everything consistent and modern. It also needs to be easily themed since this is both a multi-user and multi-tenant application. It needs to have a different branding and potentially an entirely different look-and-feel based on the host name that was requested. Second is to clean up the code and make it a bit more modular and maintainable. The idea behind that is that as features are added again in the future, that they will still have a consistent look and feel. Changing a single widget or style sheet will ripple through the entire application. Having more consistent code will garner a more consistent experience for users.
So, with those two requirements, I decided to look at different frameworks to build the new version off of. I really only had two on my list, Symfony2 and Yii2. I’ve spent the last week and a half working with both of them before making my final decision on which framework will serve as the base for this project.
To evaluate each framework, I wanted to accomplish just a few tasks:
- Get it installed and running
- Add Bootstrap 3 Widgets and style sheets
- Get a base layout for a front page
- Be able to login as a user
I already have a database that I’ll be using from the current version. I’d like to keep schema changes to a minimum if possible, since writing efficient migrations is both a royal pain to do, and adds a lot of complexity to the project. If something goes wrong during the upgrade to this, I need a fast transition back to the current running version. The production database is on the order of 60Gb, and has millions of records in it. Restoring from a snapshot takes too long except in the event of a critical outage. So I’m trying to keep schema changes to a minimum that can easily be written to migrate back down with no data loss.
I last looked at Symfony2 last year. Symfony2 is a solid framework with a lot of available modules (bundles) and is well documented. It was my first choice for this project.
I followed the Symfony Book for the install and it was quick and easy. All dependencies installed without any issue. Getting the default controller up and running, changing menu options and content was very straightforward.
Getting Bootstrap 3 was a bit more problematic in that I had a few choices as to which bundle to install. I ended up using the Braincrafted Bootstrap Bundle and the recommended twbs/bootstrap and jquery/jquery bundles. In addition to that, I had to install a few other things to get things working. This includes a LESS compiler, and a node.js compiler. This took the better part of an afternoon getting things installed, compiled, tested, and finally working. Since there are generally two or more options for each component, there isn’t a single set of installation documents to follow. Choices are good, though, so this wasn’t necessarily a bad thing. The downside I see is for a team, and getting started on a new project, two different bundles or packages may have different subtle differences. For a team project, I would suggest selecting one set of packages and writing up some documentation that all developers can follow to get the same packages installed.
Getting a base layout for the front page wasn’t too bad. Its all basic HTML and Symfony2 and the Brancrafted bundle come with pretty solid starting points as far as CSS and structure goes. Using Twig requires you to think a little backwards though. When you extend a template, the template you’re extending is still the primary, template, and by extending it the template you are working with becomes a “child” template, but it controls the contents of the parent. Once you get used to Twig, its pretty clean and easy to use, though. It provides a very good separation of code, content and presentation logic. Twig is a very solid alternative to Smarty, each having methods to accomplish just about anything you would like. I would suggest using Twig over Smarty with Symfony2, though, as it has some helpers that better integrate it with the rest of the framework.
The next step for me was to get a breadcrumb style navbar working. I ended up using nielskrijger/breadcrumbs-bundle as it fit my needs. It wasn’t my first choice, though. My first choice was the xi-project/xi-bundle-breadcrumbs as it is a more automatic method of generating them. It uses the controller routes to auto generate a breadcrumbs trail instead of manually including them in each and every controller or view. In my opinion this is a perfect solution as it builds off of the routes that are already required. Manual breadcrumbs can be a bit messy and require a pretty high amount of maintenance. I wasn’t able to use it, though, as Symfony2 kept throwing exceptions when I tried to configure it. The latest version of Symonfy2 is not compatible with the xi-bundle-breadcrumbs. A shame, too.
Finally, with the default Authentication/Authorization within Symfony2, I was able to login as a user and test rights to different menu sections and controller actions. It was pretty simple to understand, but I was just using basic configurations.
Overall Symfony2 is a solid framework that anyone should consider when starting a new project. It is well documented and has lots of bundles to extend it. Another piece that I didn’t mention as it wasn’t part of my testing was the close integration with the Doctrine ORM. I’ve been using Doctrine for quite a few years now, and it is outstanding.
There are a few downsides I see to using Symfony2. First, there is a lot of overhead and manual intervention required. Between cleaning caches, flipping back and forth between 3 and 8 different directories to accomplish a single thing, and the rather vague configuration layout it can be difficult to learn and maintain. When I talk about three and 8 different directories, I’m talking about the default project structure. While logical, its a bit of pain to navigate through, especially if you’re using the command line. There will be so many “cd ../../views/”, make a quick edit, then “cd ../../controllers” another quick edit, it will make you crazy. I had 6 terminal windows up at one point to do my testing, and that wasn’t even in a real project. It wouldn’t be as bad in an IDE such as PhpStorm, Eclipse or NetBeans, but from the command line I can see it getting very tedious very quickly.
There is also a big problem for me, and that is the extensive use of annotations. I’ve written about this before, and I’ll just add that I’ve seen various “solutions” on a few forum boards and StackExchange that would make project maintenance a complete nightmare. The main use I’ve seen of annotations have the result of scattering the core configuration of the project into each source file. This has the potential for serious abuse and sloppy code. A lot of people are suggesting putting routes directly into controllers via annotations instead of a centralized route configuration. This to me is bad form. In a single configuration file, you can control routes precisely. When they’re scattered into the controllers, it becomes too far abstracted with no actual gain, either in readability or performance. While annotations are not strictly required to use Symfony2, they are a large part of the culture with Symfony2 developers, so this needs to be taken into consideration.
Yii2 is still in beta, but it is complete enough that if you’re going to start a new project with it that won’t be done for several months, it is stable enough to start using now. If you need something done rapidly and stable, then Yii2 isn’t a good choice just yet. Over the last few weeks, I’ve seen several interfaces change that broke application level code. They’ve been easy enough to fix, but as I said, the API is still changing pretty rapidly.
Getting started with Yii2 was just as easy as it was with Symfony2. There are several application templates to choose from, all installable with composer. Simply select the layout that most closely resembles your project’s requirements and install the relevant package. As with Symfony2, you can be up and running with a new template within a few minutes and start writing code. For my test, I chose the advanced application template. It has frontend, backend, and common application hierarchy built in and ready to go.
Getting Bootstrap 3 was unnecessary since Bootstrap 3 is built in to Yii2 and part of the framework. As was a navigation system, breadcrumbs and database access via Yii2’s ActiveRecord implementation. That saves a lot more time when getting started. These components are pretty tightly integrated so using any or all of them seems natural. Of course, you can always replace any of them with other implementations.
Yii2 is also fully namespaced, just as Symfony2 is. So application components, widgets, libraries, models, etc., are generally isolated into their own vendor’s namespace. It makes writing clear code a lot easier when you don’t have to worry about function name collisions. This causes the directory structure to be very similar to Symfony2, and most other new composer based frameworks. If you’re doing things from a terminal and VIM, expect a lot of directory hopping, and expect it to get old fast. Even using PhpStorm, I find myself scrolling around a lot to get to the files I’m after. It is well organized, though, so once you get used to where things are, it will be intuitive.
There are also a few timesaving tools in Yii2 that are also present in the previous version of Yii, but they’ve been enhanced appropriately. The first is Gii, which is Yii2’s code generator. If you’ve got an existing database that you’re building off of, it will save you a lot of time. It will generate Models, Controllers, or a complete CRUD. It uses the existing database to automatically generate the code from. The code it generates isn’t quite complete, but its an excellent starting point, and certainly saves a lot of typing or cutting & pasting. There are around 70 tables in my projects database. I was able to generated models for the entire database in less than two hours using Gii. It also automatically creates the getters and setters for relations if you are so inclined.
Authentication and Authorization is also built into Yii2, and easily extended. There are a few methods for access control, either a full RBAC model using a database, or using PHP or simply using Groups. All of the different types of access control are built into the framework, so they’re well integrated. Simply choose the method you want to use and things pretty much just work. I did find a limitation, though. If you’re going to be using a database method, you probably will spend a fair amount of time writing an ACL management system. None exists yet, and there is no good way to add new permissions to an existing system that I have found. Hopefully this will be improved in the final version, or a module will be released to address the management of ACLs.
The default templating system used in Yii2 is PHP itself. Since PHP is, and always has been, a templating language, the choice of using PHP as the templating system seems logical. This is a big double edged sword in my book, though. Since the views are meant to only display data, only display logic should be put into templates. Using PHP as the templating system leaves lots of room for code to creep in and create a big mess. Yii2, gives to other options, though, in that it officially supports Smarty and Twig as its templating system. One need only install the correct modules and enable them in the config files to have Yii2 render them by extension, either .tpl or .twig, respectively.
So, for my testing, getting my base application up and running was a bit quicker in Yii2 than it was in Symfony2. More utilities are included in the core framework of Yii2 than Symfony2.
Yii2 also supports theming out of the box. Selecting a theme can be done during runtime — as long as its done early on in the execution before any views are rendered.
There are a few downsides to Yii2, also. Breadcrumbs are manual, which does mean a lot of maintenance within the views. Since Yii2 is still in beta, there isn’t a whole lot of documentation available, so there is a lot of fiddling to figure things out. This should change as it comes into a stable release and matures, however. The Yii2 forum has a lot of very helpful people in it, so if you get stuck, its very possible you can get an answer there. Also, the directory structure isn’t very rigid, which is both a pro and a con. The flexible directory structure makes it so you can customize most aspects of things, but by the same token, it makes it a bit more difficult at times to group things logically that are outside of the scope of Controllers, Components, Views, Models and Modules. Lastly, ActiveRecord, while very capable, isn’t nearly as powerful as Doctrine2, the default ORM for Symfony2. I’m pretty sure that Doctrine2 can be used within Yii2, but that is a subject for another posting.
Both Symfony2 and Yii2 are excellent frameworks. Either would be an excellent choice for starting a new project.
Symfony2 has a mature and stable codebase with dozens of high quality extensions available for it. There is an active (if not fanatic) user base that can help with things if you get stuck. There is also paid support available through several different companies, most of whom have contributed bundles. Twig is an excellent templating engine, and Doctrine2 is arguably the best ORM available for PHP.
Yii2, being still in Beta stage is not necessarily the best choice for a short term project, but is a suitable choice for a project with a longer schedule for release. Yii2 has most things needed for a typical application built into the framework and is usable without any additional packages. This makes updates more reliable as module dependencies are less likely to break when doing a framework update.
After a few weeks of working with them both, I chose Yii2 for the base of my project. It really came down to personal choice. Yii2 has more out of the box functionality and makes more sense to me. Symfony2 seems more disjointed to me and of course makes use of annotations, which I have fairly strong opinions on.