Mobindustry merges with Apriorit,
a Specialized Cybersecurity R&D Company
Symfony vs Yii2: Frameworks Comparison Based on Real Cases
In this article, I’ll compare two PHP web frameworks (Symfony and Yii2) based on my experience developing two systems that are functionally quite similar but that were made by different teams.
In both teams, I took an active part in developing both the architecture and core business logic of the application.
What is PHP
PHP is a popular server-side scripting language used for web development. It is open source, easy to learn, and widely supported, making it a top choice for developing dynamic websites and applications.
Why the PHP framework is essential in development
The PHP framework is essential in development because it provides a structured and organized approach to building web applications. Frameworks like Laravel, CodeIgniter, and Symfony offer pre-built modules and tools that simplify complex tasks such as database integration, user authentication, and security features.
This speeds up development time, ensures code quality, and allows developers to focus on creating unique and innovative features for their projects.
How to choose the best PHP framework
There’s no one-size-fits-all here. The choice of a PHP framework depends on your specific needs and requirements of your project. Consider factors such as project size, complexity, scalability, and community support.
Ultimately, the best PHP framework is the one that meets your project’s specific needs and allows you to create a secure, scalable, and efficient web application.
When choosing a PHP framework for your product, pay attention to the availability of resources and documentation. Ultimately, the best PHP framework is the one that meets your project’s specific needs and allows you to create a secure, scalable, and efficient web application.
What is Yii2
Yii2 is a high-performance, component-based PHP framework designed for building web applications. It is open source and follows the Model-View-Controller (MVC) architectural pattern, making it easy to develop scalable and maintainable web applications.
Yii2 comes with a powerful set of features, such as caching, security, testing, and database integration, which simplifies the development process and ensures high-quality code.
What is Symfony
Symfony is another popular PHP framework used for building web applications. It is also open source and follows the MVC pattern. Symfony is highly flexible and has a wide range of components and libraries for building custom web applications.
It comes with a robust set of features, such as routing, templating, form creation, and security, which makes it a top choice for building complex web applications. Symfony also has strong community support and extensive documentation, making it easy for developers to learn and use.
In this article, I’ll show you the difference between Yii vs Symfony on a practical example.
Brief project description
The two PHP web development projects in question support services that let customers rent devices for a certain period, and the end product in each case was a mobile application.
These systems implement several user roles and use them to control access to the mobile application and the admin panel. Regarding business functionality, they charge a fixed fee from the customer’s balance for every rental hour.
First differences
In the modern world, most web frameworks implemented in the same programming language (like Symfony and Yii2) are architecturally very similar.
I’m not talking about their internal implementation; I’m talking about the general principles on which they’re based.
Over the past 15 years, MVC (Model–View–Controller) has been the most popular architectural model for web applications. It’s simple, understandable, and has been tested by every web developer in one form or another.
For now, we’ll consider the Model, which in our case serves as the link between the application and the database. With regard to the Model, Symfony and Yii2 are strikingly different in terms of their implementation.
DataMapper vs ActiveRecord
Each of these frameworks provides a fairly convenient interface for working with databases in the form of object-relational mapping, or ORM.
It’s common but not mandatory to use the open-source Doctrine2 library when developing with Symfony, and this library in turn implements the DataMapper pattern.
Yii2 boasts its own database interface using the ActiveRecord pattern.
So what’s the difference between these patterns? Both give the opportunity to work with a database and make it possible to perform fairly complex queries. But they do it in different ways. Let’s figure out the differences between them.
Considering that ORM entails working with a database through objects, for starters, we’ll analyze how the aspect of this layer works in the Yii2 framework.
namespace appmodels; use yiidbActiveRecord; class Customer extends ActiveRecord { const STATUS_INACTIVE = 0; const STATUS_ACTIVE = 1; /** * @return string the name of the table associated with this ActiveRecord class. */ public static function tableName() { return '{{customer}}'; } }
Here’s an example of a Model class from the Yii2 documentation. Let’s analyze it component by component.
What can we say about this code? To begin with, we can definitely say that the Customer class inherits from the ActiveRecord base class.
Accordingly, we have a class that will subsequently be used to work not just with the database but directly with the table we need, which was declared in the static function tableName.
We have a class that’s linked with a table in the database, but the table has a field structure. Where is that structure, and how can we work with it?
The answer we need is in the schema table that Yii2 reads through the connection to the database at the right time. The fields in this table will correspond to the public properties of the object. Let’s move on to a little practice.
To get started, we’ll create a customer table from an example in the official documentation:
CREATE TABLE `customer` ( `id` int(11) NOT NULL, `email` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL, `name` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL, `phone` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; -- -- Indexes for table `customer` -- ALTER TABLE `customer` ADD PRIMARY KEY (`id`); -- -- AUTO_INCREMENT for table `customer` -- ALTER TABLE `customer` MODIFY `id` int(11) NOT NULL AUTO_INCREMENT; COMMIT;
Next, we’ll create a table model in our project through the gii console:
php yii gii/model --tableName="customer" --modelClass="Customer"
Now we can declare an instance of the class of the model we just created:
$customer = new Customer(); echo '
'; var_dump($customer->attributes); echo '
‘;
var_dump will output the following:
array(4) { ["id"] => NULL ["email"] => NULL ["name"] => NULL ["phone"] => NULL }
This means we’ve automatically taken the fields we need from the table and can start working with them.
Creating a new model object means creating a new record in the table. But if we need to make any queries on existing records, there are prepared static methods of the parent class for this.
Without interrupting the logical chain, we’ll create a new record in the customer table.
$customer->email = 'johndoe@example.com'; $customer->name = 'John Doe'; $customer->save();
The save method serves two purposes — creating and updating an existing record in the table. In this case, we’ve successfully created a new record.
Everything is very simple. ActiveRecord is a direct consequence of the RAD (rapid application development) paradigm, which brings with it certain pros and cons. But before we talk about them, let’s see what the Symfony framework offers us in this regard.
// src/Entity/Product.php namespace AppEntity; use DoctrineORMMapping as ORM; /** * @ORMEntity */ class Product { /** * @ORMId * @ORMGeneratedValue * @ORMColumn(type="integer") */ private $id; /** * @ORMColumn(type="string", length=255) */ private $name; /** * @ORMColumn(type="integer") */ private $price; public function getId() { return $this->id; } // ... getter and setter methods }
Sample code from the Symfony documentation.
Doctrine2 implements the DataMapper pattern, and as you can see from the code, the model representation in Yii2 and Symfony is very different.
It’s worth noting that in Doctrine2, it’s common to call a model an entity because it’s only a description of the table. The class itself cannot do anything when it comes to working with the database.
So the first and main difference between the approaches is that in Yii2, the model is completely tied to the database. It stores both the description and the state of the values in the table. Alongside the ability to connect and execute queries, the model assumes it will store the business logic.
This is far from all the functionality available for one single class. It turns out a certain harvester of extensive functionality, which in its turn violates the first principle of single responsibility from the definition of SOLID. In Symfony development and Doctrine2, all necessary responsibilities are divided into separate classes. Further, we’ll see this a little more clearly.
It’s worth noting that I didn’t describe the pros and cons of dividing the responsibility frameworks but simply described the particular qualities of implementing both patterns.
Create a new record, as we did with Yii2. We’ll do this in an arbitrary controller since we need to reach the object of the ObjectManager class that’s responsible for the state of entity objects and the subsequent sending of changes made to the database.
This class is the main focus when working with Doctrine2.
$product = new Product(); $product->setName('Sample product#1'); $product->setPrice(777); $entityManager = $this->getDoctrine()->getManager(); $entityManager->persist($product); $entityManager->flush();
The result of executing this code is clearly seen in the Symfony debug panel:
As you can see from the code, an entity is only responsible for its part as a description of the table, and Entity Manager performs its separate role of joining and executing queries to the database based on entities. Here, SOLID principles are not violated.
Additional queries related to the business logic of the application in Symfony are made in a separate class of the entity repository, and Yii2 usually suggests describing such functions in the model itself or in its child classes, depending on the situation.
Finally, we can summarize the pros and cons of working with a database using ActiveRecord and Doctrine2.”
Yii2 ActiveRecord pros and cons:
- Quick design
- Ease of use
- Extensive out-of-the-box functionality
- Suitable for simple CRUD applications
- Violates the main principle of SOLID — single responsibility
- Database-first project development
- Combines business logic with logic of accessing/connecting to the database, so there’s no clear isolation
- Accordingly, a strongly connected architecture complicates testing
Symfony Doctrine 2 pros and cons:
- Clear separation of the application’s functional layers
- DDD (domain-driven design) principle application writing
- Explicit description of the table structure in the entity model allows you to quickly and easily understand which fields are involved depending on the entity in the table
- The DataMapper pattern is harder to learn and understand, so developers don’t always properly use the functionality provided by the library, often working with it as with ActiveRecord-like libraries
- Need to write getter and setter methods every time
- In some cases, business logic is a bit more complex and takes longer to implement than using ActiveRecord
Routing
There are different ways in which you can approach routing in your projects. One common option is to implement it through annotations in the controller. Another option is to build routes dynamically based on the names of the controller and its methods.
Let’s see how Symfony suggests doing this using annotations.
// src/Controller/BlogController.php namespace AppController; use SymfonyComponentRoutingAnnotationRoute; /** * @Route("/blog", requirements={"_locale": "en|es|fr"}, name="blog_") */ class BlogController { /** * @Route("/{_locale}", name="index") */ public function index() { // ... } /** * @Route("/{_locale}/posts/{slug}", name="show") */ public function show(Post $post) { // ... } }
Everything is sufficiently clear. There’s a URL prefix that we indicate in the annotations to the controller class, and there are also separate annotations for controller methods that allow us to build the necessary route system for the application quite flexibly and quickly.
Let’s see how it will look with Yii2 development:
namespace appcontrollers; use Yii; use appmodelsPost; use yiiwebController; use yiiwebNotFoundHttpException; class PostController extends Controller { public function actionView($id) { // ... } public function actionCreate() { // ... } }
Not as obvious as it was in Symfony. Yii2 parses modules and controllers according to a predefined pattern, namely ModuleID / ControllerID / ActionID, and based on this, builds an automatic route system. In order to somehow assign the necessary address rules in our own way, we need to describe them in the urlManager configuration rules.
Having briefly described the routing system in both frameworks, we can draw some conclusions:
- Symfony offers a clearer approach to implementing routing systems, letting you configure them in your own way.
- Yii2 automatically generates a route system to access the controller’s public methods, but any step to the side and we need to configure additional rules in the controller settings.
For me personally, in terms of routing systems, I find the Symfony web framework more intuitive and flexible.
Versioning, support, and updates
Yii2 is the second major version of Yii so far, but a third version is planned that will not be backward compatible. The current version, in my opinion, can’t withstand the competition presented by Symfony and Laravel.
The most important question is this: What is the point of starting a new project on a framework that’s obviously inferior to its competitors? I’ll try to answer it.
The first and most important consideration is the team. The most logical way to complete tasks is using technologies already familiar to your team, especially if the deadlines are tight.
Also, although Yii2 is inferior to its competitors in some aspects, it’s still a fairly good framework in the PHP world. Plus, finding a solution to a problem in Yii2 through open data sources is often easier and faster than solving problems that arise during development in Symfony. During work on the Yii2 project I mentioned, it was noticeable that the community was more active.
As for Symfony, the prospects for updates and support are very good. The framework is actively being developed and is changing gradually over time. I personally have not had any significant problems with updates yet.
What’s been noticeable over the past few years is that the Symfony framework has become much friendlier for beginners to learn, walking the path in new versions from complex to simple without losing functional qualities.
The administrative part of the project
These frameworks differ in their methods of implementing administrative functionality for managing data in the database.
Symfony has a ready-made library called SonataAdminBundle. It has lots of functions, and many projects use it. But it’s already outdated in its own way, and for new projects, it’s usually recommended to use EasyAdminBundle. This library is sufficiently documented and is regularly expanded enough to meet the needs of any client by inheritance and the redefinition/addition of functions. You can also fully implement your own custom routes.
Yii2 has a module called Gii, which auto-generates CRUD code based on tables and models. Many people use it to generate code and then modify that code for further use according to the needs of the project.
Pros and cons of using pre-built libraries in Symfony
- Fast implementation of basic administrative functionality
- Community support for libraries
- Several ready-made integrations with libraries from other frameworks(for example, VichUploaderBundle and UserBundle)
- Customer-ready admin panel design
- It may be more difficult to implement custom functionality in some cases.
- You’ll have to follow the ideology of the library and adapt to its capabilities as well as to its limitations.
- You’ll be dependent on a ready-made solution. In some cases, you’ll have to wait for a solution to a problem in a library or get into someone else’s code yourself. But this is an open-source framework and getting into someone else’s code is considered the norm. In fact, there are stable release versions that supposedly have a minimum number of bugs.
Pros and cons of using Gii in Yii2 for implementing an admin panel
- CRUD code is generated for each model/table, which you can subsequently change as you like.
- You don’t need to follow the ideology of the ready-made library and are free in your work.
- There are a sufficient number of ready-to-use frontend components in the framework itself.
- The time to implement an admin panel can be noticeably longer than with ready-made solutions.
- Yii2 remains strongly tied to Bootstrap 3, which imposes its own limitations when developing the front end.
- Most likely, you’ll have to develop and implement your own design since there’s essentially no design when generating code and templates — only normal and functional Bootstrap components.
Conclusion
In this article, I’ve listed some of the most important differences between the Symfony and Yii2 frameworks that arose during my experience developing systems with them.
Both frameworks are good in their own way. But if I were starting a new project now and had the opportunity to choose, my choice would be Symfony web development because of its active development and stable updates, the availability of ready-made libraries for` building admin panels, and its more modern architecture that meets PHP Standards Recommendations (PSRs).