Adds default value for arguments in defined methods.
🔧 configure it!
<?php
declare(strict_types=1);
use RectorLaravel\Rector\ClassMethod\AddArgumentDefaultValueRector;
use RectorLaravel\ValueObject\AddArgumentDefaultValue;
use Rector\Config\RectorConfig;
return static function (RectorConfig $rectorConfig): void {
$containerConfigurator->extension('rectorConfig', [
[
'class' => AddArgumentDefaultValueRector::class,
'configuration' => [
'added_arguments' => [
new AddArgumentDefaultValue('SomeClass', 'someMethod', 0, false),
],
],
],
]);
};
↓
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);
}
}
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');
Move help facade-like function calls to constructor injection
🔧 configure it!
<?php
declare(strict_types=1);
use RectorLaravel\Rector\FuncCall\ArgumentFuncCallToMethodCallRector;
use RectorLaravel\ValueObject\ArgumentFuncCallToMethodCall;
use Rector\Config\RectorConfig;
return static function (RectorConfig $rectorConfig): void {
$containerConfigurator->extension('rectorConfig', [
[
'class' => ArgumentFuncCallToMethodCallRector::class,
'configuration' => [
new ArgumentFuncCallToMethodCall('view', 'Illuminate\Contracts\View\Factory', 'make'),
],
],
]);
};
↓
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 (new \Illuminate\Testing\TestResponse)->assertStatus(200)
with (new \Illuminate\Testing\TestResponse)->assertOk()
class ExampleTest extends \Illuminate\Foundation\Testing\TestCase
{
public function testOk()
{
- $this->get('/')->assertStatus(200);
- $this->get('/')->assertStatus(\Illuminate\Http\Response::HTTP_OK);
- $this->get('/')->assertStatus(\Symfony\Component\HttpFoundation\Response::HTTP_OK);
+ $this->get('/')->assertOk();
+ $this->get('/')->assertOk();
+ $this->get('/')->assertOk();
}
public function testNoContent()
{
- $this->get('/')->assertStatus(204);
- $this->get('/')->assertStatus(\Illuminate\Http\Response::HTTP_NO_CONTENT);
- $this->get('/')->assertStatus(\Symfony\Component\HttpFoundation\Response::HTTP_NO_CONTENT);
+ $this->get('/')->assertNoContent();
+ $this->get('/')->assertNoContent();
+ $this->get('/')->assertNoContent();
}
public function testUnauthorized()
{
- $this->get('/')->assertStatus(401);
- $this->get('/')->assertStatus(\Illuminate\Http\Response::HTTP_UNAUTHORIZED);
- $this->get('/')->assertStatus(\Symfony\Component\HttpFoundation\Response::HTTP_UNAUTHORIZED);
+ $this->get('/')->assertUnauthorized();
+ $this->get('/')->assertUnauthorized();
+ $this->get('/')->assertUnauthorized();
}
public function testForbidden()
{
- $this->get('/')->assertStatus(403);
- $this->get('/')->assertStatus(\Illuminate\Http\Response::HTTP_FORBIDDEN);
- $this->get('/')->assertStatus(\Symfony\Component\HttpFoundation\Response::HTTP_FORBIDDEN);
+ $this->get('/')->assertForbidden();
+ $this->get('/')->assertForbidden();
+ $this->get('/')->assertForbidden();
}
public function testNotFound()
{
- $this->get('/')->assertStatus(404);
- $this->get('/')->assertStatus(\Illuminate\Http\Response::HTTP_NOT_FOUND);
- $this->get('/')->assertStatus(\Symfony\Component\HttpFoundation\Response::HTTP_NOT_FOUND);
+ $this->get('/')->assertNotFound();
+ $this->get('/')->assertNotFound();
+ $this->get('/')->assertNotFound();
}
public function testMethodNotAllowed()
{
- $this->get('/')->assertStatus(405);
- $this->get('/')->assertStatus(\Illuminate\Http\Response::HTTP_METHOD_NOT_ALLOWED);
- $this->get('/')->assertStatus(\Symfony\Component\HttpFoundation\Response::HTTP_METHOD_NOT_ALLOWED);
+ $this->get('/')->assertMethodNotAllowed();
+ $this->get('/')->assertMethodNotAllowed();
+ $this->get('/')->assertMethodNotAllowed();
}
public function testUnprocessableEntity()
{
- $this->get('/')->assertStatus(422);
- $this->get('/')->assertStatus(\Illuminate\Http\Response::HTTP_UNPROCESSABLE_ENTITY);
- $this->get('/')->assertStatus(\Symfony\Component\HttpFoundation\Response::HTTP_UNPROCESSABLE_ENTITY);
+ $this->get('/')->assertUnprocessable();
+ $this->get('/')->assertUnprocessable();
+ $this->get('/')->assertUnprocessable();
}
public function testGone()
{
- $this->get('/')->assertStatus(410);
- $this->get('/')->assertStatus(\Illuminate\Http\Response::HTTP_GONE);
- $this->get('/')->assertStatus(\Symfony\Component\HttpFoundation\Response::HTTP_GONE);
+ $this->get('/')->assertGone();
+ $this->get('/')->assertGone();
+ $this->get('/')->assertGone();
}
public function testInternalServerError()
{
- $this->get('/')->assertStatus(500);
- $this->get('/')->assertStatus(\Illuminate\Http\Response::HTTP_INTERNAL_SERVER_ERROR);
- $this->get('/')->assertStatus(\Symfony\Component\HttpFoundation\Response::HTTP_INTERNAL_SERVER_ERROR);
+ $this->get('/')->assertInternalServerError();
+ $this->get('/')->assertInternalServerError();
+ $this->get('/')->assertInternalServerError();
}
public function testServiceUnavailable()
{
- $this->get('/')->assertStatus(503);
- $this->get('/')->assertStatus(\Illuminate\Http\Response::HTTP_SERVICE_UNAVAILABLE);
- $this->get('/')->assertStatus(\Symfony\Component\HttpFoundation\Response::HTTP_SERVICE_UNAVAILABLE);
+ $this->get('/')->asserServiceUnavailable();
+ $this->get('/')->asserServiceUnavailable();
+ $this->get('/')->asserServiceUnavailable();
}
}
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('...');
}
}
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());
The EloquentMagicMethodToQueryBuilderRule is designed to automatically transform certain magic method calls on Eloquent Models into corresponding Query Builder method calls.
use App\Models\User;
-$user = User::find(1);
+$user = User::query()->find(1);
Changes orderBy()
to latest()
or oldest()
🔧 configure it!
<?php
declare(strict_types=1);
use RectorLaravel\Rector\MethodCall\EloquentOrderByToLatestOrOldestRector;
use Rector\Config\RectorConfig;
return static function (RectorConfig $rectorConfig): void {
$containerConfigurator->extension('rectorConfig', [
[
'class' => EloquentOrderByToLatestOrOldestRector::class,
'configuration' => [
'allowed_patterns' => [
'submitted_a*',
'*tested_at',
'$allowed_variable_name',
],
],
],
]);
};
↓
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([]);
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);
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);
}
}
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!
<?php
declare(strict_types=1);
use RectorLaravel\Rector\PropertyFetch\OptionalToNullsafeOperatorRector;
use Rector\Config\RectorConfig;
return static function (RectorConfig $rectorConfig): void {
$containerConfigurator->extension('rectorConfig', [
[
'class' => OptionalToNullsafeOperatorRector::class,
'configuration' => [
'exclude_methods' => [
'present',
],
],
],
]);
};
↓
-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.')
}
}
It will removes the dump data just like dd or dump functions from the code.`
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;
}
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,
];
}
}
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 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']);
}
}
Use PHP callable syntax instead of string syntax for controller route declarations.
🔧 configure it!
<?php
declare(strict_types=1);
use RectorLaravel\Rector\StaticCall\RouteActionCallableRector;
use Rector\Config\RectorConfig;
return static function (RectorConfig $rectorConfig): void {
$containerConfigurator->extension('rectorConfig', [
[
'class' => RouteActionCallableRector::class,
'configuration' => [
'namespace' => 'App\Http\Controllers',
],
],
]);
};
↓
-Route::get('/users', 'UserController@index');
+Route::get('/users', [\App\Http\Controllers\UserController::class, 'index']);
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
}
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());
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!');
}
}