Porting Smarty to Twig with PEGs
As part of our ongoing refactoring efforts, I’ve frequently been compelled to swap out old libraries in the codebase for better alternatives. There’s a major concern that needs to be dealt with when doing this: you don’t want to leave a bunch of orphaned code and half finished refactors all over the application.
We have started to move templates from Smarty over to the Twig templating language, why?
- Twig has better data-structure support: dictionaries, objects, arrays.
- It has better performance characteristics.
- It’s a more active project.
Fabien Potencier has a great post giving an overview of templating languages in PHP.
The reasons for switching to Twig are compelling, but we have about 100 Smarty templates in the application we need to port to make the transition. I think it’s worth explaining steps we are taking to make sure that we do not leave this job half finished.
Putting Twig in a Wrapper
We wrapped Twig_Template in a class and added methods we were using in Smarty but that were not in Twig_Template. Specifically, we allowed variables to be inserted into the template’s scope using the method assign(). This helped cut down on the grunt work involved during porting.
Note the assign method on line 23, it populates the parameters array which is eventually passed into Twig’s render() or display() method.
Making Porting Plugins a Breeze:
We have a ton of Smarty modifiers and functions that we need to move over. Twig has a great plugin infrastructure, but there was room for improvements specific to our use case. We subclassed Twig_Extension and built out a library that automatically loads in all our extensions. Our FreshTwigExtension class uses get_class_methods() to register all the methods found within classes that extend it as Twig_Filter_Methods. As we move our templates over to Twig we just grab a modifier’s code and drop it into one of these subclasses.
This class makes loading extensions easier, and is used in association with an auto-loader.
Automatic Code Conversion with PEGs:
We wanted to automate as much of the process of porting from Smarty to Twig as possible. Parsing Expression Grammars are a great way to easily build parsers. I felt that it would be worth taking the time to build a PEG for translating between the two templating languages. It would be much faster to build a tool to do this than to do the work manually. Here’s the grammar we built for porting from Smarty to Twig:
Notice how the most complicated rules are just a combination of much simpler rules.
Using this parsing library, we can convert a large Smarty template to Twig in a matter of minutes. This makes it far easier to complete the transition to Twig.
Nerding out on new technology is definitely a favourite pastime of mine, and I think really important to growing as a technologist. That said, pulling new technologies into a large production codebase, without seeing their inception through to the end is a bad habit to get into. Going as far as creating a parser for your porting strategy is worthwhile to help stop this.
We’ve made our Smarty to Twig converter available on github: