Skip to content

Intention Actions

Laravel Idea provides a set of intention actions — quick code transformations available via Alt+Enter (or ⌥Enter on macOS) when your cursor is on the relevant code.

Promote Request to FormRequest

Trigger: cursor on an Illuminate\Http\Request parameter in a controller method.

This intention extracts all validation rules found in the current method into a new FormRequest class. After the refactoring:

  • The parameter type is updated to the new FormRequest class.
  • Inline $request->validate([...]) calls are removed or replaced with $request->safe().
  • The generated class is opened/placed according to your Code Generation settings.

Before:

php
public function store(Request $request)
{
    $data = $request->validate([
        'name'  => 'required|string|max:255',
        'email' => 'required|email',
    ]);
    // ...
}

After:

php
public function store(StoreUserRequest $request)
{
    $data = $request->safe();
    // ...
}

Generated FormRequest:

php
class StoreUserRequest extends FormRequest
{
    public function rules(): array
    {
        return [
            'name'  => ['required', 'string', 'max:255'],
            'email' => ['required', 'email'],
        ];
    }
}

Note: If the validation rules contain references to external variables or method calls, the plugin will warn you before proceeding. You will need to fix those references manually.

Convert Facade alias to Facade call

Trigger: cursor on a facade alias (e.g., Cache, Auth, DB) that is registered as a global alias in your Laravel application.

Replaces all uses of the alias within the current method with the fully-qualified facade class reference and inserts the corresponding use statement.

Before:

php
Cache::put('key', $value, 60);
Cache::get('key');

After:

php
use Illuminate\Support\Facades\Cache;

Cache::put('key', $value, 60);
Cache::get('key');

Convert Facade call to Dependency

Trigger: cursor on a facade class reference (e.g., Cache, Illuminate\Support\Facades\Cache) inside a method.

Replaces all static facade calls in the current method with calls on an injected dependency. A popup lets you choose whether to inject it:

  • Into the constructor (adds a promoted constructor property).
  • Into the current method (adds a typed parameter).

The plugin analyses which facade methods are used and picks the best matching interface or concrete class.

Before:

php
public function handle()
{
    Cache::put('key', $value, 60);
    Cache::get('key');
}

After (constructor injection):

php
public function __construct(
    private readonly CacheRepository $cache,
) {}

public function handle()
{
    $this->cache->put('key', $value, 60);
    $this->cache->get('key');
}

Requirement: Constructor property promotion must be enabled in Laravel Idea settings.

Move dependency to constructor

Trigger: cursor on a typed (non-primitive) parameter in a non-static, non-magic method.

Moves the parameter to the class constructor as a promoted property and replaces all local uses of the variable with $this->propertyName.

If the same parameter signature exists in multiple methods of the class, a popup appears asking whether to apply the change to just the current method or to all matching methods.

Before:

php
public function process(UserRepository $userRepository): void
{
    $userRepository->find($id);
}

After:

php
public function __construct(
    private readonly UserRepository $userRepository,
) {}

public function process(): void
{
    $this->userRepository->find($id);
}

Requirement: Constructor property promotion must be enabled in Laravel Idea settings.

Convert validation string to array

Trigger: cursor on a pipe-separated validation rule string (e.g., "required|email|max:255").

Converts the string to an equivalent PHP array, which is the modern recommended style.

Before:

php
'email' => 'required|email|max:255',

After:

php
'email' => ['required', 'email', 'max:255'],

Convert all validation strings to array

Trigger: cursor on any pipe-separated validation rule string inside a validation rules() array.

The same conversion as above but applied to every field in the surrounding array at once.

Before:

php
[
    'name'  => 'required|string|max:255',
    'email' => 'required|email',
    'age'   => 'nullable|integer|min:0',
];

After:

php
[
    'name'  => ['required', 'string', 'max:255'],
    'email' => ['required', 'email'],
    'age'   => ['nullable', 'integer', 'min:0'],
];

Convert validation rule to the Rule object

Trigger: cursor on a string validation rule that has a corresponding Rule:: factory method. Supported rules: unique, exists, in, not_in, array, file, image, dimensions.

Converts the string form to the fluent Rule:: object API and inserts the required use statement.

Before:

php
'email' => ['required', 'unique:users,email'],

After:

php
use Illuminate\Validation\Rule;

'email' => ['required', Rule::unique('users', 'email')]

Other examples:

BeforeAfter
'in:active,inactive'Rule::in(['active', 'inactive'])
'dimensions:width=100,height=200'Rule::dimensions()->width(100)->height(200)
'image'Rule::imageFile()

Convert to [Controller::class] call

Trigger: cursor on a string-based controller reference in a route definition (e.g., "UserController@index").

Converts the legacy string format to the modern class-constant array syntax and inserts the use statement for the controller class.

Before:

php
Route::get('/users', 'UserController@index');
Route::post('/users', 'App\Http\Controllers\UserController');

After:

php
use App\Http\Controllers\UserController;

Route::get('/users', [UserController::class, 'index']);
Route::post('/users', UserController::class);

Convert all controller calls

Trigger: cursor on any string-based controller reference in a route file.

Same conversion as above, applied to every string-based controller reference in the entire file.

Convert Eloquent scope to #[Scope]

Trigger: cursor on a method name that starts with scope inside an Eloquent model class (Laravel 12.6+ project with #[Scope] attribute syntax enabled).

Migrates the old naming convention-based scope to the new PHP attribute syntax:

  • Removes the scope prefix from the method name.
  • Adds the #[Scope] attribute.
  • Changes the method visibility to protected if it was public.

Before:

php
public function scopeActive(Builder $query): void
{
    $query->where('active', true);
}

After:

php
use Illuminate\Database\Eloquent\Attributes\Scope;

#[Scope]
protected function active(Builder $query): void
{
    $query->where('active', true);
}

Note: This intention is only available when the project's Laravel version supports the #[Scope] attribute syntax (configurable in Laravel Idea settings).

Convert all Eloquent scopes to #[Scope]

Trigger: cursor on any scope* method inside an Eloquent model.

Same conversion as above, applied to every scope* method in the current model class.

Convert Blade braces

{{ }} → {!! !!}

Trigger: cursor inside {{ ... }} braces in a Blade template.

Converts HTML-escaped output braces to unescaped output braces. Use this when you intentionally want to output raw HTML.

Before:

blade
{{ $htmlContent }}

After:

blade
{!! $htmlContent !!}

Warning: Unescaped output is only safe if the content is trusted. Prefer for user-supplied data to prevent XSS.

{!! !!} → {{ ... }}

Trigger: cursor inside {!! ... !!} braces in a Blade template.

Converts unescaped output back to HTML-escaped output.

Before:

blade
{!! $htmlContent !!}

After:

blade
{{ $htmlContent }}

Convert to @class directive

Trigger: cursor inside a class="..." attribute that contains multiple space-separated CSS classes (in a Blade template).

Converts a static multi-class attribute to Blade's @class([...]) directive, placing each class on its own line so conditional classes can be added easily.

Before:

blade
<div class="flex items-center gap-4">

After:

blade
<div @class([
    'flex',
    'items-center',
    'gap-4',
])>

Requirement: The project's Laravel version must support the @class directive (Laravel 9+).

Wrap with @class directive

Trigger: cursor inside a class="..." attribute in a Blade template.

Wraps the existing class attribute value inside the @class([...]) directive as a single string entry, giving you a starting point to add conditional class expressions.

Before:

blade
<div class="btn-primary">

After:

blade
<div @class(['btn-primary'])>