Change if abort to abort_if
-if ($condition) {
- abort(404);
-}
-if (!$condition) {
- abort(404);
-}
+abort_if($condition, 404);
+abort_unless($condition, 404);
Adds default value for arguments in defined methods.
🔧 configure it!
class SomeClass
{
- public function someMethod($value)
+ public function someMethod($value = false)
{
}
}
Adds the @extends
annotation to Factories.
use Illuminate\Database\Eloquent\Factories\Factory;
+/**
+ * @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\User>
+ */
class UserFactory extends Factory
{
protected $model = \App\Models\User::class;
}
Add generic return type to relations in child of Illuminate\Database\Eloquent\Model
use App\Account;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasMany;
class User extends Model
{
+ /** @return HasMany<Account> */
public function accounts(): HasMany
{
return $this->hasMany(Account::class);
}
}
use App\Account;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasMany;
class User extends Model
{
+ /** @return HasMany<Account, $this> */
public function accounts(): HasMany
{
return $this->hasMany(Account::class);
}
}
Add new $guard
argument to Illuminate\Auth\Events\Login
use Illuminate\Auth\Events\Login;
final class SomeClass
{
public function run(): void
{
- $loginEvent = new Login('user', false);
+ $guard = config('auth.defaults.guard');
+ $loginEvent = new Login($guard, 'user', false);
}
}
Add "$this->mockConsoleOutput = false"; to console tests that work with output content
use Illuminate\Support\Facades\Artisan;
use Illuminate\Foundation\Testing\TestCase;
final class SomeTest extends TestCase
{
+ public function setUp(): void
+ {
+ parent::setUp();
+
+ $this->mockConsoleOutput = false;
+ }
+
public function test(): void
{
$this->assertEquals('content', \trim((new Artisan())::output()));
}
}
Add parent::boot();
call to boot()
class method in child of Illuminate\Database\Eloquent\Model
use Illuminate\Database\Eloquent\Model;
class Product extends Model
{
public function boot()
{
+ parent::boot();
}
}
Add parent::register();
call to register()
class method in child of Illuminate\Foundation\Support\Providers\EventServiceProvider
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
class EventServiceProvider extends ServiceProvider
{
public function register()
{
+ parent::register();
}
}
Convert migrations to anonymous classes.
use Illuminate\Database\Migrations\Migration;
-class CreateUsersTable extends Migration
+return new class extends Migration
{
// ...
-}
+};
Replace $app->environment() === 'local'
with $app->environment('local')
-$app->environment() === 'production';
+$app->environment('production');
Apply default instead of null coalesce
🔧 configure it!
-custom_helper('app.name') ?? 'Laravel';
+custom_helper('app.name', 'Laravel');
Move help facade-like function calls to constructor injection
🔧 configure it!
class SomeController
{
+ /**
+ * @var \Illuminate\Contracts\View\Factory
+ */
+ private $viewFactory;
+
+ public function __construct(\Illuminate\Contracts\View\Factory $viewFactory)
+ {
+ $this->viewFactory = $viewFactory;
+ }
+
public function action()
{
- $template = view('template.blade');
- $viewFactory = view();
+ $template = $this->viewFactory->make('template.blade');
+ $viewFactory = $this->viewFactory;
}
}
Replace assertSee with assertSeeHtml when testing HTML with escape set to false
-$response->assertSee("<li>foo</li>", false);
+$response->assertSeeHtml("<li>foo</li>");
-$response->assertDontSee("<li>foo</li>", false);
+$response->assertDontSeeHtml("<li>foo</li>");
-$response->assertSeeInOrder(["<li>foo</li>", "<li>bar</li>"], false);
+$response->assertSeeHtmlInOrder(["<li>foo</li>", "<li>bar</li>"]);
Replace (new \Illuminate\Testing\TestResponse)->assertStatus(200)
with (new \Illuminate\Testing\TestResponse)->assertOk()
class ExampleTest extends \Illuminate\Foundation\Testing\TestCase
{
public function testFoo()
{
- $this->get('/')->assertStatus(200);
- $this->get('/')->assertStatus(204);
- $this->get('/')->assertStatus(401);
- $this->get('/')->assertStatus(403);
- $this->get('/')->assertStatus(404);
- $this->get('/')->assertStatus(405);
- $this->get('/')->assertStatus(422);
- $this->get('/')->assertStatus(410);
- $this->get('/')->assertStatus(500);
- $this->get('/')->assertStatus(503);
+ $this->get('/')->assertOk();
+ $this->get('/')->assertNoContent();
+ $this->get('/')->assertUnauthorized();
+ $this->get('/')->assertForbidden();
+ $this->get('/')->assertNotFound();
+ $this->get('/')->assertMethodNotAllowed();
+ $this->get('/')->assertUnprocessable();
+ $this->get('/')->assertGone();
+ $this->get('/')->assertInternalServerError();
+ $this->get('/')->assertServiceUnavailable();
}
}
Convert negated calls to contains
to doesntContain
, or vice versa.
use Illuminate\Support\Collection;
$collection = new Collection([0, 1, null, -1]);
-! $collection->contains(fn (?int $number): bool => is_null($number));
-! $collection->doesntContain(fn (?int $number) => $number > 0);
+$collection->doesntContain(fn (?int $number): bool => is_null($number));
+$collection->contains(fn (?int $number) => $number > 0);
Avoid negated conditionals in filter()
by using reject()
, or vice versa.
use Illuminate\Support\Collection;
$collection = new Collection([0, 1, null, -1]);
-$collection->filter(fn (?int $number): bool => ! is_null($number));
-$collection->filter(fn (?int $number): bool => ! $number);
-$collection->reject(fn (?int $number) => ! $number > 0);
+$collection->reject(fn (?int $number): bool => is_null($number)); // Avoid negation
+$collection->reject(fn (?int $number): bool => (bool) $number); // Explicitly cast
+$collection->filter(fn (?int $number): bool => $number > 0); // Adds return type
Replace magical call on $this->app["something"]
to standalone type assign variable
class SomeClass
{
/**
* @var \Illuminate\Contracts\Foundation\Application
*/
private $app;
public function run()
{
- $validator = $this->app['validator']->make('...');
+ /** @var \Illuminate\Validation\Factory $validationFactory */
+ $validationFactory = $this->app['validator'];
+ $validator = $validationFactory->make('...');
}
}
Use the $this->travelTo()
method in Laravel's TestCase
class instead of the Carbon::setTestNow()
method.
use Illuminate\Support\Carbon;
use Illuminate\Foundation\Testing\TestCase;
class SomeTest extends TestCase
{
public function test()
{
- Carbon::setTestNow('2024-08-11');
+ $this->travelTo('2024-08-11');
}
}
Renames the Billable stripeOptions()
to stripe().
use Illuminate\Database\Eloquent\Model;
use Laravel\Cashier\Billable;
class User extends Model
{
use Billable;
- public function stripeOptions(array $options = []) {
+ public function stripe(array $options = []) {
return [];
}
}
Add parent::boot();
call to boot()
class method in child of Illuminate\Database\Eloquent\Model
use Illuminate\Database\Query\Builder;
final class SomeClass
{
public function run(Builder $query)
{
- $query->whereDate('created_at', '<', Carbon::now());
+ $dateTime = Carbon::now();
+ $query->whereDate('created_at', '<=', $dateTime);
+ $query->whereTime('created_at', '<=', $dateTime);
}
}
Convert DB Expression string casts to getValue()
method calls.
use Illuminate\Support\Facades\DB;
-$string = (string) DB::raw('select 1');
+$string = DB::raw('select 1')->getValue(DB::connection()->getQueryGrammar());
Convert DB Expression __toString()
calls to getValue()
method calls.
use Illuminate\Support\Facades\DB;
-$string = DB::raw('select 1')->__toString();
+$string = DB::raw('select 1')->getValue(DB::connection()->getQueryGrammar());
Dispatch non ShouldQueue jobs to dispatchSync
-dispatch(new SomeJob());
-Bus::dispatch(new SomeJob());
-$this->dispatch(new SomeJob());
+dispatch_sync(new SomeJob());
+Bus::dispatchSync(new SomeJob());
+$this->dispatchSync(new SomeJob());
Use the event or dispatch helpers instead of the static dispatch method.
-ExampleEvent::dispatch($email);
+event(new ExampleEvent($email));
-ExampleJob::dispatch($email);
+dispatch(new ExampleJob($email));
The EloquentMagicMethodToQueryBuilderRule is designed to automatically transform certain magic method calls on Eloquent Models into corresponding Query Builder method calls.
🔧 configure it!
use App\Models\User;
-$user = User::find(1);
+$user = User::query()->find(1);
Changes orderBy()
to latest()
or oldest()
🔧 configure it!
use Illuminate\Database\Eloquent\Builder;
$column = 'tested_at';
-$builder->orderBy('created_at');
-$builder->orderBy('created_at', 'desc');
-$builder->orderBy('submitted_at');
-$builder->orderByDesc('submitted_at');
-$builder->orderBy($allowed_variable_name);
+$builder->oldest();
+$builder->latest();
+$builder->oldest('submitted_at');
+$builder->latest('submitted_at');
+$builder->oldest($allowed_variable_name);
$builder->orderBy($unallowed_variable_name);
$builder->orderBy('unallowed_column_name');
Add type hinting to where relation has methods e.g. whereHas
, orWhereHas
, whereDoesntHave
, orWhereDoesntHave
, whereHasMorph
, orWhereHasMorph
, whereDoesntHaveMorph
, orWhereDoesntHaveMorph
-User::whereHas('posts', function ($query) {
+User::whereHas('posts', function (\Illuminate\Contracts\Database\Query\Builder $query) {
$query->where('is_published', true);
});
-$query->whereHas('posts', function ($query) {
+$query->whereHas('posts', function (\Illuminate\Contracts\Database\Query\Builder $query) {
$query->where('is_published', true);
});
Change typehint of closure parameter in where method of Eloquent Builder
-$query->where(function ($query) {
+$query->where(function (\Illuminate\Contracts\Database\Eloquent\Builder $query) {
$query->where('id', 1);
});
Replace use of the unsafe empty()
function with Laravel's safer blank()
& filled()
functions.
-empty([]);
-!empty([]);
+blank([]);
+filled([]);
Change env variable to env static call
-$_ENV['APP_NAME'];
+\Illuminate\Support\Env::get('APP_NAME');
Call the state methods directly instead of specify the name of state.
-$factory->state('delinquent');
-$factory->states('premium', 'delinquent');
+$factory->delinquent();
+$factory->premium()->delinquent();
Upgrade legacy factories to support classes.
use Faker\Generator as Faker;
-$factory->define(App\User::class, function (Faker $faker) {
- return [
- 'name' => $faker->name,
- 'email' => $faker->unique()->safeEmail,
- ];
-});
+class UserFactory extends \Illuminate\Database\Eloquent\Factories\Factory
+{
+ protected $model = App\User::class;
+ public function definition()
+ {
+ return [
+ 'name' => $this->faker->name,
+ 'email' => $this->faker->unique()->safeEmail,
+ ];
+ }
+}
Use the static factory method instead of global factory function.
-factory(User::class);
+User::factory();
Change app()
func calls to facade calls
class SomeClass
{
public function run()
{
- return app('translator')->trans('value');
+ return \Illuminate\Support\Facades\App::get('translator')->trans('value');
}
}
Change method calls from $this->json
to $this->postJson,
$this->putJson,
etc.
-$this->json("POST", "/api/v1/users", $data);
+$this->postJson("/api/v1/users", $data);
Converts the computed methods of a Livewire component to use the Computed Attribute
use Livewire\Component;
class MyComponent extends Component
{
- public function getFooBarProperty()
+ #[\Livewire\Attributes\Computed]
+ public function fooBar()
{
}
}
Converts the $queryString
property of a Livewire component to use the Url Attribute
use Livewire\Component;
class MyComponent extends Component
{
+ #[\Livewire\Attributes\Url]
public string $something = '';
+ #[\Livewire\Attributes\Url]
public string $another = '';
-
- protected $queryString = [
- 'something',
- 'another',
- ];
}
Changes action in rule definitions from string to array notation.
-$router->get('/user', 'UserController@get');
+$router->get('/user', ['uses => 'UserController@get']);
Changes middlewares from rule definitions from string to array notation.
-$router->get('/user', ['middleware => 'test']);
-$router->post('/user', ['middleware => 'test|authentication']);
+$router->get('/user', ['middleware => ['test']]);
+$router->post('/user', ['middleware => ['test', 'authentication']]);
Migrate to the new Model attributes syntax
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
- public function getFirstNameAttribute($value)
+ protected function firstName(): \Illuminate\Database\Eloquent\Casts\Attribute
{
- return ucfirst($value);
- }
-
- public function setFirstNameAttribute($value)
- {
- $this->attributes['first_name'] = strtolower($value);
- $this->attributes['first_name_upper'] = strtoupper($value);
+ return \Illuminate\Database\Eloquent\Casts\Attribute::make(get: function ($value) {
+ return ucfirst($value);
+ }, set: function ($value) {
+ return ['first_name' => strtolower($value), 'first_name_upper' => strtoupper($value)];
+ });
}
}
Change minutes argument to seconds in Illuminate\Contracts\Cache\Store
and Illuminate\Support\Facades\Cache
class SomeClass
{
public function run()
{
- Illuminate\Support\Facades\Cache::put('key', 'value', 60);
+ Illuminate\Support\Facades\Cache::put('key', 'value', 60 * 60);
}
}
Refactor Model $casts
property with casts()
method
use Illuminate\Database\Eloquent\Model;
class Person extends Model
{
- protected $casts = [
- 'age' => 'integer',
- ];
+ protected function casts(): array
+ {
+ return [
+ 'age' => 'integer',
+ ];
+ }
}
Swap the use of NotBooleans used with filled()
and blank()
to the correct helper.
-!filled([]);
-!blank([]);
+blank([]);
+filled([]);
Use today()
instead of now()->startOfDay()
-$now = now()->startOfDay();
+$now = today();
Convert simple calls to optional helper to use the nullsafe operator
🔧 configure it!
-optional($user)->getKey();
-optional($user)->id;
+$user?->getKey();
+$user?->id;
// macro methods
optional($user)->present()->getKey();
Change deprecated $defer
= true; to Illuminate\Contracts\Support\DeferrableProvider
interface
use Illuminate\Support\ServiceProvider;
+use Illuminate\Contracts\Support\DeferrableProvider;
-final class SomeServiceProvider extends ServiceProvider
+final class SomeServiceProvider extends ServiceProvider implements DeferrableProvider
{
- /**
- * @var bool
- */
- protected $defer = true;
}
Change "redirect" call with 301 to "permanentRedirect"
class SomeClass
{
public function run()
{
- Illuminate\Routing\Route::redirect('/foo', '/bar', 301);
+ Illuminate\Routing\Route::permanentRedirect('/foo', '/bar');
}
}
Replace redirect()->back()
and Redirect::back()
with back()
use Illuminate\Support\Facades\Redirect;
class MyController
{
public function store()
{
- return redirect()->back()->with('error', 'Incorrect Details.')
+ return back()->with('error', 'Incorrect Details.')
}
public function update()
{
- return Redirect::back()->with('error', 'Incorrect Details.')
+ return back()->with('error', 'Incorrect Details.')
}
}
Replace redirect()->route("home")
and Redirect::route("home")
with to_route("home")
use Illuminate\Support\Facades\Redirect;
class MyController
{
public function store()
{
- return redirect()->route('home')->with('error', 'Incorrect Details.')
+ return to_route('home')->with('error', 'Incorrect Details.')
}
public function update()
{
- return Redirect::route('home')->with('error', 'Incorrect Details.')
+ return to_route('home')->with('error', 'Incorrect Details.')
}
}
refactors calls with the pre Laravel 11 methods for blueprint geometry columns
-$blueprint->point('coordinates')->spatialIndex();
+$blueprint->geometry('coordinates', 'point')->spatialIndex();
It will removes the dump data just like dd or dump functions from the code.`
🔧 configure it!
class MyController
{
public function store()
{
- dd('test');
return true;
}
public function update()
{
- dump('test');
return true;
}
}
Removes the $model
property from Factories.
use Illuminate\Database\Eloquent\Factories\Factory;
class UserFactory extends Factory
{
- protected $model = \App\Models\User::class;
}
Removes redundant value helper calls
-value(new Object())->something();
+(new Object())->something();
Removes redundant with helper calls
-with(new Object())->something();
+(new Object())->something();
Replace assertTimesSent with assertSentTimes
-Notification::assertTimesSent(1, SomeNotification::class);
+Notification::assertSentTimes(SomeNotification::class, 1);
Replace expectJobs and expectEvents methods in tests
use Illuminate\Foundation\Testing\TestCase;
class SomethingTest extends TestCase
{
public function testSomething()
{
- $this->expectsJobs([\App\Jobs\SomeJob::class, \App\Jobs\SomeOtherJob::class]);
- $this->expectsEvents(\App\Events\SomeEvent::class);
+ \Illuminate\Support\Facades\Bus::fake([\App\Jobs\SomeJob::class, \App\Jobs\SomeOtherJob::class]);
+ \Illuminate\Support\Facades\Event::fake([\App\Events\SomeEvent::class]);
$this->get('/');
+
+ \Illuminate\Support\Facades\Bus::assertDispatched(\App\Jobs\SomeJob::class);
+ \Illuminate\Support\Facades\Bus::assertDispatched(\App\Jobs\SomeOtherJob::class);
+ \Illuminate\Support\Facades\Event::assertDispatched(\App\Events\SomeEvent::class);
}
}
Replace $this->faker
with the fake()
helper function in Factories
class UserFactory extends Factory
{
public function definition()
{
return [
- 'name' => $this->faker->name,
- 'email' => $this->faker->unique()->safeEmail,
+ 'name' => fake()->name,
+ 'email' => fake()->unique()->safeEmail,
];
}
}
Changes the string or class const used for a service container make call
🔧 configure it!
-app('encrypter')->encrypt('...');
-\Illuminate\Support\Facades\Application::make('encrypter')->encrypt('...');
+app(Illuminate\Contracts\Encryption\Encrypter::class)->encrypt('...');
+\Illuminate\Support\Facades\Application::make(Illuminate\Contracts\Encryption\Encrypter::class)->encrypt('...');
Replace withoutJobs
, withoutEvents
and withoutNotifications
with Facade fake
-$this->withoutJobs();
-$this->withoutEvents();
-$this->withoutNotifications();
+\Illuminate\Support\Facades\Bus::fake();
+\Illuminate\Support\Facades\Event::fake();
+\Illuminate\Support\Facades\Notification::fake();
Change if report to report_if
-if ($condition) {
- report(new Exception());
-}
-if (!$condition) {
- report(new Exception());
-}
+report_if($condition, new Exception());
+report_unless($condition, new Exception());
Change static validate()
method to $request->validate()
use Illuminate\Http\Request;
class SomeClass
{
- public function store()
+ public function store(\Illuminate\Http\Request $request)
{
- $validatedData = Request::validate(['some_attribute' => 'required']);
+ $validatedData = $request->validate(['some_attribute' => 'required']);
}
}
Change request variable definition in Facade
-$_GET['value'];
-$_POST['value'];
-$_REQUEST['value'];
-$_POST;
-$_GET;
-$_REQUEST;
+\Illuminate\Support\Facades\Request::query('value');
+\Illuminate\Support\Facades\Request::post('value');
+\Illuminate\Support\Facades\Request::input('value');
+\Illuminate\Support\Facades\Request::query();
+\Illuminate\Support\Facades\Request::post();
+\Illuminate\Support\Facades\Request::all();
Use new JsonResponse instead of response()->json()
-response()->json(['key' => 'value']);
+return new JsonResponse(['key' => 'value']);
Reverse conditionable method calls
-$conditionable->when(!$condition, function () {});
+$conditionable->unless($condition, function () {});
-$conditionable->unless(!$condition, function () {});
+$conditionable->when($condition, function () {});
Use PHP callable syntax instead of string syntax for controller route declarations.
🔧 configure it!
-Route::get('/users', 'UserController@index');
+Route::get('/users', [\App\Http\Controllers\UserController::class, 'index']);
Route::group(['namespace' => 'Admin'], function () {
- Route::get('/users', 'UserController@index');
+ Route::get('/users', [\App\Http\Controllers\Admin\UserController::class, 'index']);
})
Change server variable to Request facade's server method
-$_SERVER['VARIABLE'];
+\Illuminate\Support\Facade\Request::server('VARIABLE');
Change PHP session usage to Session Facade methods
-$_SESSION['key'];
-$_SESSION['key'] = 'value';
-$_SESSION;
-session_regenerate_id();
-session_unset();
-session_destroy();
-session_start();
-unset($_SESSION['key']);
-isset($_SESSION['key'])
+\Illuminate\Support\Facades\Session::get('key');
+\Illuminate\Support\Facades\Session::put('key', 'value');
+\Illuminate\Support\Facades\Session::all();
+\Illuminate\Support\Facades\Session::regenerate();
+\Illuminate\Support\Facades\Session::flush();
+\Illuminate\Support\Facades\Session::destroy();
+\Illuminate\Support\Facades\Session::start();
+\Illuminate\Support\Facades\Session::forget('key');
+\Illuminate\Support\Facades\Session::has('key');
Use Sleep::sleep()
and Sleep::usleep()
instead of the sleep()
and usleep()
function.
-sleep(5);
+\Illuminate\Support\Sleep::sleep(5);
Use Str::startsWith()
or Str::endsWith()
instead of substr()
=== $str
-if (substr($str, 0, 3) === 'foo') {
+if (Str::startsWith($str, 'foo')) {
// do something
}
changes use of a new throw instance to class string
-throw_if($condition, new MyException('custom message'));
+throw_if($condition, MyException::class, 'custom message');
Change if throw to throw_if
-if ($condition) {
- throw new Exception();
-}
-if (!$condition) {
- throw new Exception();
-}
+throw_if($condition, new Exception());
+throw_unless($condition, new Exception());
Automatically type hints your tappable closures
-tap($collection, function ($collection) {}
+tap($collection, function (Collection $collection) {}
-(new Collection)->tap(function ($collection) {}
+(new Collection)->tap(function (Collection $collection) {}
Use the base collection methods instead of their aliases.
use Illuminate\Support\Collection;
$collection = new Collection([0, 1, null, -1]);
-$collection->average();
-$collection->some(fn (?int $number): bool => is_null($number));
+$collection->avg();
+$collection->contains(fn (?int $number): bool => is_null($number));
Unify Model $dates
property with $casts
use Illuminate\Database\Eloquent\Model;
class Person extends Model
{
protected $casts = [
- 'age' => 'integer',
+ 'age' => 'integer', 'birthday' => 'datetime',
];
-
- protected $dates = ['birthday'];
}
Use $this->components
property within commands
use Illuminate\Console\Command;
class CommandWithComponents extends Command
{
public function handle()
{
- $this->ask('What is your name?');
- $this->line('A line!');
- $this->info('Info!');
- $this->error('Error!');
+ $this->components->ask('What is your name?');
+ $this->components->line('A line!');
+ $this->components->info('Info!');
+ $this->components->error('Error!');
}
}
Convert string validation rules into arrays for Laravel's Validator.
Validator::make($data, [
- 'field' => 'required|nullable|string|max:255',
+ 'field' => ['required', 'nullable', 'string', 'max:255'],
]);
Changes where
method and static calls to whereLike
calls in the Eloquent & Query Builder.
Can be configured for the Postgres driver with [WhereToWhereLikeRector::USING_POSTGRES_DRIVER => true]
.
🔧 configure it!
-$query->where('name', 'like', 'Rector');
-$query->orWhere('name', 'like', 'Rector');
-$query->where('name', 'like binary', 'Rector');
+$query->whereLike('name', 'Rector');
+$query->orWhereLike('name', 'Rector');
+$query->whereLike('name', 'Rector', true);
-$query->where('name', 'ilike', 'Rector');
-$query->orWhere('name', 'ilike', 'Rector');
-$query->where('name', 'like', 'Rector');
+$query->whereLike('name', 'Rector');
+$query->orWhereLike('name', 'Rector');
+$query->whereLike('name', 'Rector', true);