I looked back at my git history today and worked out I’ve been using Laravel since November 2015. At the time it was like a breath of fresh air. For the 4 years leading up to that I’d been responsible for a legacy PHP application written in Symfony 1. Whilst a game changer in it’s own right the world had moved on since Symfony 1 was released and Laravel was right at the forefront of that movement. Laravel made me more productive and more confident in my code and I’ve built many apps and api’s on top of it since.
Fast forward to 2020 and I’ve been looking into Javascript more and more. The benefits of using the same language on the front and back end make sense to me. I set out to find a Javascript Framework that could replace my beloved Laravel. The first framework I found was Sails. Whilst it seems popular and robust I was struggling to get my head round a different way of planning and building apps. That’s when I discovered AdonisJs. The article that brought it to my attention highlighted how similar it was to Laravel so I had to give it a try.
This article is aimed at Laravel Developers and focuses on the similarities and differences between the two frameworks. I will focus on the key parts of the Laravel Framework that make it so productive.
- Command Line Tool
- Routing
- Migrations
- ORM
- Testing
- Queuing
- Cache
CLI
One of the great things with Laravel is the ‘artisan’ cli it comes bundled with that gives loads of command line tools for doing common tasks. I’ve broken out the main sections to make the comparison easier. Both frameworks have almost identical ways to make commands, controllers, exceptions, models, providers and seeders.
Laravel
make
make:command Create a new Artisan command
make:controller Create a new controller class
make:exception Create a new custom exception class
make:migration Create a new migration file
make:model Create a new Eloquent model class
make:provider Create a new service provider class
make:seeder Create a new seeder class
AdonisJs
make
make:command Make a new ace command
make:controller Make a new HTTP or Websocket channel controller
make:exception Make a new exception
make:migration Create a new migration file
make:model Make a new lucid model
make:provider Make a new provider
make:seed Create a database seeder
They also have very similar tools for running, rolling back and resetting migrations.
The big gap that I can see in the AdonisJs CLI is commands for managing Queues. More on this later.
Routing
Routing feels almost identical. Both frameworks offer ways to respond to all the HTTP verbs, GET, POST, PUT, PATCH and DELETE. You can write your closure in the route file itself or point to a Controller.
Laravel
Route::get('/', function () {
return 'Hello World';
});
Route::get('/user', 'UserController@index');
AdonisJs
Route.get('/', () => 'Hello World')
Route.get('user', 'UserController.index')
Migrations
One of the most powerful features in Laravel is the ability to write all your database changes as ‘migrations’. These are files which describe the database change you are making. You run them with the CLI and Laravel keeps track of where the app is up to. It’s incredibly powerful not least because your database changes are kept in version control.
Both frameworks operate in very similar ways. Each migration has an ‘up’ and a ‘down’ method. The ‘down’ is designed to reverse the changes of the ‘up’. I’ll show a comparison of a migration designed to add a new table called airlines and add a email column to the users table.
Laravel Up:
public function up()
{
Schema::create('airlines', function (Blueprint $table) {
$table->increments();
$table->string('airline');
$table->timestamps();
});
Schema::table('users', function (Blueprint $table) {
$table->string('email');
});
}
AdonisJs Up:
up () {
this.create('airlines', (table) => {
table.increments()
table.string('airline')
table.timestamps()
});
this.alter('users', (table) => {
table.string('email')
})
}
Laravel Down:
public function down()
{
Schema::table('users', function (Blueprint $table) {
$table->dropColumn('email');
});
Schema::drop('airlines');
}
AdonisJs Down:
down () {
this.alter('users', (table) => {
table.dropColumn('email')
})
this.drop('airlines')
}
As you can see they look very similar and are conceptually identical.
Conclusion
That concludes todays article. I’ll conclude the comparison tomorrow looking at ORM, Testing, Queues and Caching.