Laravel and its other first-party packages follow Semantic Versioning. Major framework releases are released every year (~February), while minor and patch releases may be released as often as every week. Minor and patch releases should never contain breaking changes.
When referencing the Laravel framework or its components from your application or package, you should always use a version constraint such as ^9.0, since major releases of Laravel do include breaking changes. However, we strive to always ensure you may update to a new major release in one day or less.
From 8.x to 9.x important changes:
- php is beginning transition to require function return type.
- Belongs to many methods (
firstOr...
,UpdateOr...
) now comparing against the related model not pivot. - They moved from
swiftMailer
tosymfonyMailer
. - lang directory have located to project root directory.
- Use
current_password
validation rule instead ofpassword
New features in 9.x:
- Route controller group.
- Anonymous migration class.
- New helper functions.
- Refreshed ignition error page.
- Render blade string.
- Forced scope bindings.
- Laravel scout DB engine.
- Full text indexing.
- Enum attribute casting.
- Simplified accessors and mutators.
we will discuss every point below:
Route controller group
If a group of routes all utilize the same controller, you may use the controller
method to define the common controller for all of the routes within the group. Then, when defining the routes, you only need to provide the controller method that they invoke:
use App\Http\Controllers\OrderController;
Route::controller(OrderController::class)->group(function () {
Route::get('/orders/{id}', 'show');
Route::post('/orders', 'store');
});
They don't stop here but also made new console format when listing
project routesphp artisan route:list
Anonymous migration class
Migration file now not class with name but anonymous one.
<?php
...
return new class extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
...
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
...
}
};
New helper functions
-
str('__') /** equals to */ Str::of('__');
and it's good specially in blade as we don't need to use name space qualifier of Str class. to_route('__'); /** equals to */ redirect()->route('__');
Refreshed ignition error page
Render blade string
Sometimes you may need to transform a raw Blade template string into valid HTML.
use Illuminate\Support\Facades\Blade;
return Blade::render('Hello, @if(true) {$name} @endif', ['name' => 'Julian Bashir']);
Forced scope bindings
To bind models only belong to another model.
Route::get('/users/{user}/posts/{post:id}', function(User $user, Post $post){
...
})
we use post:id
to see if user has this post , if not returns 404 but this can be dis-informative so explicitly:
Route::get('/users/{user}/posts/{post}', function(User $user, Post $post){
...
})->scopeBindings();
Laravel scout DB engine
Scout package performs full text search, It used to using services but now for small projects we can use our DB engine.
Full text indexing
- In migration class:
$table->text('body')->fullText();
- When searching:
Post::whereFullText('body', '__')->get();
Enum attribute casting
Eloquent also allows you to cast your attribute values to PHP "backed" enums.
use App\Enums\ServerStatus;
/**
* The attributes that should be cast.
*
* @var array
*/
protected $casts = [
'status' => ServerStatus::class,
];
also Laravel allows you to type-hint an Enum on your route definition and Laravel will only invoke the route if that route segment corresponds to a valid Enum value. Otherwise, a 404 HTTP response will be returned automatically.
<?php
namespace App\Enums;
enum Category: string
{
case Fruits = 'fruits';
case People = 'people';
}
use App\Enums\Category;
use Illuminate\Support\Facades\Route;
Route::get('/categories/{category}', function (Category $category) {
return $category->value;
});
Simplified accessors and mutators
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
/**
* Interact with the user's first name.
*
* @param string $value
* @return \Illuminate\Database\Eloquent\Casts\Attribute
*/
protected function firstName(): Attribute
{
return new Attribute(
get: fn ($value) => ucfirst($value),
set: fn ($value) => strtolower($value),
);
}
}
Top comments (0)