Giter Club home page Giter Club logo

rector-laravel's Introduction

Rector Rules for Laravel

Tests Code Analysis Packagist Downloads Packagist Version

See available Laravel rules

Install

This package is a Rector extension developed by the Laravel community.

Install the RectorLaravel package as dependency:

composer require driftingly/rector-laravel --dev

Use Sets

To add a set to your config, use RectorLaravel\Set\LaravelSetList class and pick one of the constants:

<?php

declare(strict_types=1);

use Rector\Config\RectorConfig;
use RectorLaravel\Set\LaravelSetList;

return RectorConfig::configure()
    ->withSets([
        LaravelSetList::LARAVEL_110
    ]);

Available Sets

Set Purpose
LaravelSetList::LARAVEL_ARRAY_STR_FUNCTION_TO_STATIC_CALL Converts most string and array helpers into Str and Arr Facades' static calls.
https://laravel.com/docs/11.x/facades#facades-vs-helper-functions
LaravelSetList::LARAVEL_CODE_QUALITY Replaces magical call on $this->app["something"] to standalone variable with PHPDocs.
LaravelSetList::LARAVEL_CONTAINER_STRING_TO_FULLY_QUALIFIED_NAME Changes the string or class const used for a service container make call.
https://laravel.com/docs/11.x/container#the-make-method
LaravelSetList::LARAVEL_ELOQUENT_MAGIC_METHOD_TO_QUERY_BUILDER Transforms magic method calls on Eloquent Models into corresponding Query Builder method calls.
https://laravel.com/docs/11.x/eloquent
LaravelSetList::LARAVEL_FACADE_ALIASES_TO_FULL_NAMES Replaces Facade aliases with full Facade names.
https://laravel.com/docs/11.x/facades#facade-class-reference
LaravelSetList::LARAVEL_IF_HELPERS Replaces abort(), report(), throw statements inside conditions with abort_if(), report_if(), throw_if() function calls.
https://laravel.com/docs/11.x/helpers#method-abort-if
LaravelSetList::LARAVEL_LEGACY_FACTORIES_TO_CLASSES Migrates Eloquent legacy model factories (with closures) into class based factories.
https://laravel.com/docs/8.x/releases#model-factory-classes
LaravelSetList::LARAVEL_STATIC_TO_INJECTION Replaces Laravel's Facades with Dependency Injection.
https://tomasvotruba.com/blog/2019/03/04/how-to-turn-laravel-from-static-to-dependency-injection-in-one-day/
https://laravel.com/docs/11.x/facades#facades-vs-dependency-injection

Contributors

Thank you everyone who works so hard on improving this package:

Hire The Rector Team

Rector is a tool that we develop and share for free, so anyone can automate their refactoring. But not everyone has dozens of hours to understand complexity of abstract-syntax-tree in their own time. That's why we provide commercial support - to save your time.

Would you like to apply Rector on your code base but don't have time for the struggle with your project? Hire the Rector team to get there faster.

Learn Rector Faster

Not everyone has time to understand Rector and AST complexity. You can speed up the process by reading the book The Power of Automated Refactoring. Not only will it help you learn and understand Rector but it supports the project as well.

rector-laravel's People

Contributors

asugai avatar bram-pkg avatar canvural avatar cappuc avatar clementbirkle avatar driftingly avatar egorbwork avatar fridzema avatar genijaho avatar gisostallenberg avatar hirenkeraliya avatar ikari7789 avatar j3j5 avatar joelvh avatar johnbacon avatar lxshadowxl avatar peterfox avatar phh avatar rene-bos avatar sabbelasichon avatar samsonasik avatar simivar avatar stoffo avatar szepeviktor avatar tanerkay avatar tomasvotruba avatar u01jmg3 avatar zingimmick avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

rector-laravel's Issues

JsonCallToExplicitJsonCallRector with getJson()

We can't just replace json('GET' to getJson(. Only if no $data passed.

image

There are different signatures and getJson does not support any params ($data)

public function json($method, $uri, array $data = [], array $headers = [], $options = 0);

public function getJson($uri, array $headers = [], $options = 0);

Add Rector back to branch protection

After migration, the rules around branch protection were blocking tests and the ability to merge PRs.

Pull local workflows for checks and Rector.

rule AddGenericReturnTypeToRelationsRector trigger Error

With

 "rector/rector": "^0.18.12",
  "driftingly/rector-laravel": "^0.26.2",
 "phpstan/phpstan": "^1.10",
 "nunomaduro/larastan": "^2.7",

when the rule AddGenericReturnTypeToRelationsRector::class is activated

I get this error on multiple class:

 [ERROR] Could not process "app/Models/User.php" file, due to:                                                          
         "System error: "Call to a member function mapPHPStanPhpDocTypeNodeToPHPStanType() on null"                     
                                                                                                                        
         Stack trace:                                                                                                   
         #0 vendor/driftingly/rector-laravel/src/Rector/ClassMethod/AddGenericReturnTypeToRelationsRector.php(162):     
         RectorLaravel\Rector\ClassMethod\AddGenericReturnTypeToRelationsRector->areNativeTypeAndPhpDocReturnTypeEqual( 
         Object(PhpParser\Node\Stmt\ClassMethod), Object(PhpParser\Node\Name\FullyQualified),                           
         Object(PHPStan\PhpDocParser\Ast\PhpDoc\ReturnTagValueNode))                                                    
         #1 vendor/rector/rector/src/Rector/AbstractScopeAwareRector.php(27):                                           
         RectorLaravel\Rector\ClassMethod\AddGenericReturnTypeToRelationsRector->refactorWithScope(Object(PhpParser\Nod 
         e\Stmt\ClassMethod), Object(PHPStan\Analyser\MutatingScope))                                                   
         #2 vendor/rector/rector/src/Rector/AbstractRector.php(132):                                                    
         Rector\Core\Rector\AbstractScopeAwareRector->refactor(Object(PhpParser\Node\Stmt\ClassMethod))                 
         #3 vendor/rector/rector/vendor/nikic/php-parser/lib/PhpParser/NodeTraverser.php(176):                          
         Rector\Core\Rector\AbstractRector->enterNode(Object(PhpParser\Node\Stmt\ClassMethod))                          
         #4 vendor/rector/rector/vendor/nikic/php-parser/lib/PhpParser/NodeTraverser.php(105):                          
         PhpParser\NodeTraverser->traverseArray(Array)                                                                  
         #5 vendor/rector/rector/vendor/nikic/php-parser/lib/PhpParser/NodeTraverser.php(196):                          
         PhpParser\NodeTraverser->traverseNode(Object(PhpParser\Node\Stmt\Class_))                                      
         #6 vendor/rector/rector/vendor/nikic/php-parser/lib/PhpParser/NodeTraverser.php(105):                          
         PhpParser\NodeTraverser->traverseArray(Array)                                                                  
         #7 vendor/rector/rector/vendor/nikic/php-parser/lib/PhpParser/NodeTraverser.php(196):                          
         PhpParser\NodeTraverser->traverseNode(Object(PhpParser\Node\Stmt\Namespace_))                                  
         #8 vendor/rector/rector/vendor/nikic/php-parser/lib/PhpParser/NodeTraverser.php(85):                           
         PhpParser\NodeTraverser->traverseArray(Array)                                                                  
         #9 vendor/rector/rector/src/PhpParser/NodeTraverser/RectorNodeTraverser.php(50):                               
         PhpParser\NodeTraverser->traverse(Array)                                                                       
         #10 vendor/rector/rector/src/Application/FileProcessor.php(116):                                               
         Rector\Core\PhpParser\NodeTraverser\RectorNodeTraverser->traverse(Array)                                       
         #11 vendor/rector/rector/src/Application/ApplicationFileProcessor.php(177):                                    
         Rector\Core\Application\FileProcessor->processFile(Object(Rector\Core\ValueObject\Application\File),           
         Object(Rector\Core\ValueObject\Configuration))                                                                 
         #12 vendor/rector/rector/src/Application/ApplicationFileProcessor.php(153):                                    
         Rector\Core\Application\ApplicationFileProcessor->processFile(Object(Rector\Core\ValueObject\Application\File) 
         , Object(Rector\Core\ValueObject\Configuration))                                                               
         #13 vendor/rector/rector/src/Console/Command/WorkerCommand.php(132):                                           
         Rector\Core\Application\ApplicationFileProcessor->processFiles(Array,                                          
         Object(Rector\Core\ValueObject\Configuration), Object(Closure))                                                
         #14 vendor/rector/rector/vendor/evenement/evenement/src/EventEmitterTrait.php(111):                            
         Rector\Core\Console\Command\WorkerCommand->Rector\Core\Console\Command\{closure}(Array)                        
         #15 vendor/rector/rector/vendor/clue/ndjson-react/src/Decoder.php(117):                                        
         RectorPrefix202312\Evenement\EventEmitter->emit('data', Array)                                                 
         #16 vendor/rector/rector/vendor/evenement/evenement/src/EventEmitterTrait.php(111):                            
         RectorPrefix202312\Clue\React\NDJson\Decoder->handleData(Array)                                                
         #17 vendor/rector/rector/vendor/react/stream/src/Util.php(62):                                                 
         RectorPrefix202312\Evenement\EventEmitter->emit('data', Array)                                                 
         #18 vendor/rector/rector/vendor/evenement/evenement/src/EventEmitterTrait.php(111):                            
         RectorPrefix202312\React\Stream\Util::RectorPrefix202312\React\Stream\{closure}('{"action":"main...')          
         #19 vendor/rector/rector/vendor/react/stream/src/DuplexResourceStream.php(154):                                
         RectorPrefix202312\Evenement\EventEmitter->emit('data', Array)                                                 
         #20 vendor/rector/rector/vendor/react/event-loop/src/StreamSelectLoop.php(201):                                
         RectorPrefix202312\React\Stream\DuplexResourceStream->handleData(Resource id #1883)                            
         #21 vendor/rector/rector/vendor/react/event-loop/src/StreamSelectLoop.php(173):                                
         RectorPrefix202312\React\EventLoop\StreamSelectLoop->waitForStreamActivity(NULL)                               
         #22 vendor/rector/rector/src/Console/Command/WorkerCommand.php(90):                                            
         RectorPrefix202312\React\EventLoop\StreamSelectLoop->run()                                                     
         #23 vendor/rector/rector/vendor/symfony/console/Command/Command.php(327):                                      
         Rector\Core\Console\Command\WorkerCommand->execute(Object(RectorPrefix202312\Symfony\Component\Console\Input\A 
         rgvInput), Object(RectorPrefix202312\Symfony\Component\Console\Output\ConsoleOutput))                          
         #24 vendor/rector/rector/vendor/symfony/console/Application.php(960):                                          
         RectorPrefix202312\Symfony\Component\Console\Command\Command->run(Object(RectorPrefix202312\Symfony\Component\ 
         Console\Input\ArgvInput), Object(RectorPrefix202312\Symfony\Component\Console\Output\ConsoleOutput))           
         #25 vendor/rector/rector/vendor/symfony/console/Application.php(333):                                          
         RectorPrefix202312\Symfony\Component\Console\Application->doRunCommand(Object(Rector\Core\Console\Command\Work 
         erCommand), Object(RectorPrefix202312\Symfony\Component\Console\Input\ArgvInput),                              
         Object(RectorPrefix202312\Symfony\Component\Console\Output\ConsoleOutput))                                     
         #26 vendor/rector/rector/src/Console/ConsoleApplication.php(53):                                               
         RectorPrefix202312\Symfony\Component\Console\Application->doRun(Object(RectorPrefix202312\Symfony\Component\Co 
         nsole\Input\ArgvInput), Object(RectorPrefix202312\Symfony\Component\Console\Output\ConsoleOutput))             
         #27 vendor/rector/rector/vendor/symfony/console/Application.php(216):                                          
         Rector\Core\Console\ConsoleApplication->doRun(Object(RectorPrefix202312\Symfony\Component\Console\Input\ArgvIn 
         put), Object(RectorPrefix202312\Symfony\Component\Console\Output\ConsoleOutput))                               
         #28 vendor/rector/rector/bin/rector.php(129): RectorPrefix202312\Symfony\Component\Console\Application->run()  
         #29 vendor/rector/rector/bin/rector(5): require_once('vendor...')                                              
         #30 vendor/bin/rector(119): include('vendor...')                                                               
         #31 {main}". On line: 290   

When the rule is disabled, no errors occurs

With this packages version:

"rector/rector": "^0.18.4",
"driftingly/rector-laravel": "^0.26.0",
"phpstan/phpstan": "^1.10",
"nunomaduro/larastan": "^2.6",

No errors are triggered, and command line display Rector is done!/
But I get this warning in the console when rule AddGenericReturnTypeToRelationsRector is enabled

Get staticTypeMapper property from AbstractRector on RectorLaravel\Rector\ClassMethod\AddGenericReturnTypeToRelationsRector is deprecated, inject via __construct() instead

laravel54 every => nth breaks modern use of Collection::every

On my Laravel 10 project, I've enabled the LaravelLevelSetList::UP_TO_LARAVEL_100 set. (Please tell me if that's not the right way to use this package.)

In the laravel54 rules, it renames uses of Collection::every to Collection::nth. I'm sure this was appropriate for Laravel 5.4, but Collection has since added a new every method which is completely different from the nth method. I have had to disable the set in the meantime.

Support for rector 1.0.0

It seems there is actually no support for the latest rector release (1.0.0).

I am getting some errors.

First the rector.php config structure changed and ->sets() seems to be replaced by ->withSets().

Changing that brings up an error:

[ERROR] Class "Rector\Core\Rector\AbstractRector" not found.

Requirement for PHP 8.1

Just wondering why this dependency requires a greater version of PHP (>=8.1) than Rector (^7.2|^8.0) does? It makes it more problematic to use on older versions of PHP. Thanks

Relations return type rector is incomplete

When utilising the AddGenericReturnTypeToRelationsRector rector, some of the relations it generates are incomplete. In my case, this mostly affects belongs to, where Larastan is expecting <RelatedModel, CurrentModel> but is only recieving . I have a feeling quite a few of the relationships have this expectation.

Laravel Cashier upgrade rules

Can we include rules to upgrade Cashier to later versions like 13 and 14 in this repository? At least to handle the boring method renames and whatever work that can be automated.

Since it's a first-party Laravel package it would make sense to include it in this repo, but while adding new classes that are Cashier-specific, the Rector rules become bloated and hard to navigate.

A solution could be to prepend the rules with the Cashier prefix, for example, CashierStripeOptionsToStripeRector.

Or would a new repository be a better idea?

AddGenericReturnTypeToRelationsRector incorrectly handles a morphTo relation

Given the following code (with correct generics):

class Translations extends Model
{
    /**
     * @return MorphTo<Model,  \App\Models\Translations\Translations>
     */
    public function translatable(): MorphTo
    {
        return $this->morphTo('translatable', 'model', 'value');
    }
}

The rule changes it to the following:

class Translations extends Model
{
    /**
     * @return MorphTo<\translatable, \App\Models\Translations\Translations>
     */
    public function translatable(): MorphTo
    {
        return $this->morphTo('translatable', 'model', 'value');
    }
}

Which in return gives problems with Larastan. This is because it is returned by the function getRelatedModelClassFromMethodCall. I can fix it rewriting it to the following (but I guess this breaks other stuff?):

    private function getRelatedModelClassFromMethodCall(MethodCall $methodCall): ?string
    {
        $argType = $this->getType($methodCall->getArgs()[0]->value);

        if (! $argType instanceof GenericClassStringType) {
            return null;
        }

        if ($argType instanceof ConstantStringType) {
            return $argType->getValue();
        }

        $modelType = $argType->getGenericType();

        if (! $modelType instanceof ObjectType) {
            return null;
        }

        return $modelType->getClassName();
    }

What should be the correct fix for this problem? Maybe add a check if the given relation is a morphTo?

L8 rules: Seeders are now namespaced

Hi there,

After joining a meet-up on Rector (PHP-WVL) I was very curious about the package. I'm now using it to upgrade a L7 to L8 and noticed that there's probably a rule missing, although I'm not sure as it could be that I'm not familiar enough with rector.

The high impact change is that Seeder classes need namespacing from L8 forward. Is it possible that this rules needs to be added still, if so how can I help?

Rector 0.15.0 - Laravel60|70 - ParamTypeDeclarationRector throws error

Hey,

Using:

  • Rector 0.15.0
  • Rector-Laravel 0.14.1

I use the set

  • LaravelLevelSetList::UP_TO_LARAVEL_90,

When running rector, I get the following error:

  • [ERROR] Use specific rules to infer params instead. This rule was split info many small ones.

Seems to refer to the following file in rector-laravel:

I did some small digging, looks like 0.15.0 of rector now throws an error.

Current solution is to use older version of rector, but thought I'd report this.

Moving Laravel Rector to the Laravel community :heart:

In the past, we've moved few Rector-framework packages from the core directly to their communities.
It gives the community full power and freedom to decide what to add to the upgrade sets 👍

See:

Based on such a great experience and positive community feedback, we've decided to do this for a Laravel framework package, that deserves much more contributions and maintainer from their own community.

See tweet https://twitter.com/rectorphp/status/1585361016262639616 :)


At the moment, I'm speaking with @driftingly on possible takeover of this package 💪

Thanks for reaching out and the @laravel community the spread the news 🙏

Cannot autowire service "RectorLaravel\Rector\Assign\CallOnAppArrayAccessToStandaloneAssignRector": argument "$nodesToAddCollector" of method "__construct()" has type "Rector\PostRector\Collector\NodesToAddCollector" but this class was not found.

I just upgraded to rector 0.17.1 and I have this error when running rector process --dry-run

rector process --dry-run

                                                                                                                        
 [ERROR] Cannot autowire service "RectorLaravel\Rector\Assign\CallOnAppArrayAccessToStandaloneAssignRector": argument   
         "$nodesToAddCollector" of method "__construct()" has type "Rector\PostRector\Collector\NodesToAddCollector" but
         this class was not found.                                                                                      
                                                                                                                        

Script rector process --dry-run handling the scan event returned with error code 1

Here is my rector.php file

declare(strict_types=1);

use Rector\Config\RectorConfig;
use Rector\DeadCode\Rector\Node\RemoveNonExistingVarAnnotationRector;
use Rector\Php70\Rector\StaticCall\StaticCallOnNonStaticToInstanceCallRector;
use Rector\Php80\Rector\FuncCall\ClassOnObjectRector;
use Rector\Php81\Rector\Array_\FirstClassCallableRector;
use Rector\Php81\Rector\MethodCall\SpatieEnumMethodCallToEnumConstRector;
use Rector\Php82\Rector\Class_\ReadOnlyClassRector;
use Rector\Privatization\Rector\Class_\ChangeReadOnlyVariableWithDefaultValueToConstantRector;
use Rector\Set\ValueObject\LevelSetList;
use Rector\Set\ValueObject\SetList;
use RectorLaravel\Set\LaravelSetList;

return static function (RectorConfig $rectorConfig): void {
    $rectorConfig->paths([
        __DIR__ . "/app",
        __DIR__ . "/config",
        /**
         * @todo Try to uncomment and see if it still gets stuck in infinite loop (since 0.15.10)
         */
        // __DIR__ . "/database",
        __DIR__ . "/lang",
        __DIR__ . "/resources/views",
        __DIR__ . "/routes",
        __DIR__ . "/tests",
    ]);

    $rectorConfig->skip([
        ClassOnObjectRector::class,
        StaticCallOnNonStaticToInstanceCallRector::class,
        FirstClassCallableRector::class,
        RemoveNonExistingVarAnnotationRector::class,
        RemoveLastReturnRector::class,
        ChangeReadOnlyVariableWithDefaultValueToConstantRector::class,

        __DIR__ . "/database/migrations/*",
        ReadOnlyClassRector::class => [
            __DIR__ . "/app/Events", // Because Laravel trait "InteractsWithSockets" have non read only property.
            __DIR__ . "/app/Jobs", // Because Laravel trait "InteractsWithQueue" have non read only property.
        ],
        SpatieEnumMethodCallToEnumConstRector::class,
    ]);

    // define sets of rules
    $rectorConfig->sets([
        LevelSetList::UP_TO_PHP_82,
        SetList::DEAD_CODE,
        SetList::PRIVATIZATION,
        SetList::EARLY_RETURN,
        SetList::TYPE_DECLARATION,
        LaravelSetList::LARAVEL_90,
        LaravelSetList::LARAVEL_CODE_QUALITY,
        LaravelSetList::LARAVEL_LEGACY_FACTORIES_TO_CLASSES,
    ]);
};

I just tried to require rector/rector:0.17.0 and there is no issue. I guess 0.17.1 contains breaking changes for package maintainers.

\str_contains should not be replaced by Str::contains when on PHP 8+

FuncCallToStaticCallRector is configured to replace str_contains with Str::contains, but this is also is done on PHP 8, where the native str_contains is used.
Could we add a (target) version check at

new FuncCallToStaticCall('str_contains', 'Illuminate\Support\Str', 'contains'),
, so it will be skipped when the native function is used?

Can you tell me in what way you would like me to create a PR if you're open to such a PR?

How to use with rector-prefixed?

Currently, when I try to use it with rector-prefixed

it fails with such error

- rector/rector-laravel[dev-main, 0.10.0] require rector/rector ^0.10 -> satisfiable by rector/rector[0.10.0, ..., 0.10.x-dev (alias of dev-main)].

Facades are rewritten to Service via StaticCallOnNonStaticToInstanceCallRector

Hi,

How can I prevent that Facades are being rewritten to Service classes?

-        $subtotal = Webshop::calculateTotals($order->cart, $order->country, coupon: $coupon);
+        $subtotal = (new Webshop())->calculateTotals($order->cart, $order->country, coupon: $coupon);

Want to keep the Facade-way, because Facade isn't static.

Adding one of those to withSkip() didn't help: ThisCallOnStaticMethodToStaticCallRector::class & StaticCallOnNonStaticToInstanceCallRector

[Idea] UnifyModelDatesWithCastsRector: Make rule configurable for date casting

First of all, this project looks fantastic. I used this rule on a codebase and it covered 90% of my needs.

However, this is just a proposal but could there be a way to add configuration to this rule, so that you can cast specific properties to values that the end user defines?

I.e something that is not just datetime?

return static function (RectorConfig $rectorConfig): void {
    $rectorConfig->ruleWithConfiguration(UnifyModelDatesWithCastsRector::class, [
        new UnifyModelDateWithCast('App\Models\User', 'date_of_birth', 'immutable_date'), 
        new UnifyModelDateWithCast('App\Models\AnotherModel', 'another_column', 'immutable_datetime'), 
        new UnifyModelDateWithCast('App\Models\YetAnotherModel', 'another_column', 'date'), 
    ]);
};

and UnifyModelDateWithCast would be something like:

<?php

namespace App\Namespace;

class UnifyModelDateWithCast
{
    public function __construct(
        private readonly string $modelNamespace, 
        private readonly string $column, 
        private readonly string $castToValue, 
    ) {
    }
}

UnifyModelDateWithCast was just off the top of my head, and could be named more appropriately.

and everything else not specified here using the config will be set as datetime, as the current behaviour. Also, by default if there is no configuration, all casting will be done as datetime, as the current behaviour.

Desired outcome of above

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

 class User extends Model
 {
     protected $casts = [
-        'age' => 'integer',
+        'age' => 'integer', 'date_of_birth' => 'immutable_date',
     ];
-
-    protected $dates = ['date_of_birth'];
 }
namespace App\Models;

use Illuminate\Database\Eloquent\Model;

 class AnotherModel extends Model
 {
     protected $casts = [
-        'age' => 'integer',
+        'age' => 'integer', 'another_column' => 'immutable_datetime',
     ];
-
-    protected $dates = ['another_column'];
 }
namespace App\Models;

use Illuminate\Database\Eloquent\Model;

 class YetAnotherModel extends Model
 {
     protected $casts = [
-        'age' => 'integer',
+        'age' => 'integer', 'another_column' => 'date',
     ];
-
-    protected $dates = ['another_column'];
 }

Ideally, looking at this https://github.com/laravel/framework/blob/10.x/src/Illuminate/Database/Eloquent/Concerns/HasAttributes.php#L750-L784, the accepted values should be anything that is:

  • date
  • datetime
  • custom_datetime
  • immutable_date
  • immutable_custom_datetime
  • immutable_datetime
  • timestamp?

I've just gotten into learning about Rector, so could attempt to make a PR for the above, if it was desired behaviour of this project.

I am also not sure of how possible, all of this would be.

Again, all just an idea, which may or may not be progressed upon or even desired.

ADD: Refactor Controllers to Single Responsibility principle

it used to be a custom to have massive Controller files
most Laravel devs need to refactor their controllers to single respons

Feature Request

add a refactor that refactors all old style Controller classes according to single responsibility principle (Separation of Concerns #SOLID) + all of their usages

i.e:
SpaghettiController.php:
class SpaghettiController ..
{

	public function list() {...}

	public function show()  {...}

    public function delete()  {...}
}

into separate files in the same directory:

SpaghettiListController.php:

class SpaghettiListController .. {
    public function __invoke () {...}
}

SpaghettiShowController.php:

class SpaghettiShowController .. {
    public function __invoke () {...}
}

SpaghettiDeleteController.php:

class SpaghettiDeleteController .. {
    public function __invoke () {...}
}

upstream: rectorphp/rector#7847

a more Laravel specific feature would be to rewrite api routes to use these new controller invoke methods:

Route::get('spaghetti/{spaghetti_id}', (new SpaghettiController())->show(...));
or
Route::get('spaghetti/{spaghetti_id}', [SpaghettiController::class, 'show']);

into

Route::get('spaghetti/{spaghetti_id}', SpaghettiShowController::class);

Tag a release

Hi, some PRs went in recently, would it be possible to tag a release please?

Create sets for laravel upgrade rules

I check all the rules and upgrade for the laravel 7 to 8 and 8 to 9.
I got the rules can we make a set for this laravel upgrade?
if you agree then I will do that.

Error with change property visibility

Hello

When i use dev-main branch, i receive this error:

./vendor/bin/rector --dry-run
Fatal error: Cannot redeclare non-readonly property Rector\Core\Rector\AbstractRector::$phpDocInfoFactory as readonly
RectorLaravel\Rector\ClassMethod\AddGenericReturnTypeToRelationsRector::$phpDocInfoFactory in /var/www/api/vendor/driftingly/rector-laravel/src/Rector/ClassMethod/AddGenericReturnTypeToRelationsRector.php on line 30

but when i use 0.26.1 version then error:

Fatal error: Access level to RectorLaravel\Rector\ClassMethod\AddGenericReturnTypeToRelationsRector::$phpDocInfoFactory must be protected (as in class Rector\Core\Rector\AbstractRector) or weaker in /var/www/api/vendor/driftingly/rector-laravel/src/Rector/ClassMethod/AddGenericReturnTypeToRelationsRector.php on line 30

PHP 8.1
Laravel 10.0

Refactor uses FQDN despite namespace is present (since 0.16.0)

I just noticed #76 got merged, and since then I have an issue:

One of my blade file is specifying a namespace for a Facade, but rector still tries to use the FQDN at the call location.

Here is my blade file (before)

@php
    use Illuminate\Support\Str;
    
    $parentId = Str::random(12);
@endphp

<div class="accordion" id="{{ $id }}">
    {{ $slot }}
</div>

And here is what Rector wants to refactor:

@php
  use Illuminate\Support\Str;

- $parentId = Str::random(12);
+ $parentId = Illuminate\Support\Str::random(12);
@endphp

Is it something I need to configure to explicitly disable FQDN when the namespace is present?

`RedirectRouteToToRouteHelperRector` error on calls without `->with`

The following fixture causes an error when run with the RedirectRouteToToRouteHelperRector rule.

Seems to be caused by $this->removeNode($methodCall);

<?php

namespace RectorLaravel\Tests\Rector\MethodCall\RedirectRouteToToRouteHelperRector\Fixture;

use Illuminate\Support\Facades\Redirect;

class Fixture
{
    public function store()
    {
        return redirect()->route('home');
    }

    public function update()
    {
        return Redirect::route('home');
    }
}

?>
-----
<?php

namespace RectorLaravel\Tests\Rector\MethodCall\RedirectRouteToToRouteHelperRector\Fixture;

use Illuminate\Support\Facades\Redirect;

class Fixture
{
    public function store()
    {
        return to_route('home');
    }

    public function update()
    {
        return to_route('home');
    }
}

?>

RouteActionCallableRector (Cannot autowire service)

<?php

use Rector\Config\RectorConfig;
use RectorLaravel\Rector\StaticCall\RouteActionCallableRector;

return static function (RectorConfig $rectorConfig): void {
    $rectorConfig->paths([
        __DIR__ . '/routes',
    ]);

    $rectorConfig->ruleWithConfiguration(RouteActionCallableRector::class, [
        RouteActionCallableRector::NAMESPACE => 'App\Http\Controllers',
    ]);
};
 [ERROR] Cannot autowire service "RectorLaravel\Rector\StaticCall\RouteActionCallableRector": argument                  
         "$routerRegisterNodeAnalyzer" of method "__construct()" references class                                       
         "RectorLaravel\NodeFactory\RouterRegisterNodeAnalyzer" but no such service exists.  

Tested with both PHP 8.1.17,8.2.4

rector/rector: 0.15.24
driftingly/rector-laravel: 0.17.0

Any idea what i am doing wrong?

[QUESTION] withTypeCoverageLevel and withDeadCodeLevel

Hi

I'm started using rector-laravel. can I ask about the withTypeCoverageLevel and withDeadCodeLevel ? on what level should I stop ?

I'm on Laravel 11 just updated from Laravel 10

here is my config

return RectorConfig::configure()

    ->withPaths([
        __DIR__ . '/app',
        __DIR__ . '/config',
        __DIR__ . '/database',
        __DIR__ . '/public',
        __DIR__ . '/resources',
        __DIR__ . '/routes',
        __DIR__ . '/tests',
    ])
    ->withPhpSets()
    ->withTypeCoverageLevel(27)
    ->withDeadCodeLevel(35)
    ->withSets([
        LaravelSetList::LARAVEL_110,
        LaravelSetList::LARAVEL_CODE_QUALITY,
    ]);
    
    
    my composer version


    "require": {
        "php": "^8.2",
        
   
    
    And I installed php version 8.3 
    
    
    Thank you in advance

EloquentMagicMethodToQueryBuilderRector transforms class to include namespace

Example from EloquentMagicMethodToQueryBuilderRector prepends query to the Eloquent magic methods.

Example:

 use App\Models\User;

-$user = User::find(1);
+$user = User::query()->find(1);

After trying it:

 use App\Models\User;

-$user = User::find(1);
+$user = \App\Models\User::query()->find(1);

Is there a way for the rule to leave the class at the current class name and only prepend the query() method?

Ruleset is very simple:

return static function (RectorConfig $rectorConfig): void {
    $rectorConfig->paths([
        __DIR__ . '/app',
    ]);
    $rectorConfig->rule(EloquentMagicMethodToQueryBuilderRector::class);
};

Issue installing alongside new Rector release (`v0.19.0`)

From Composer

Problem 1
    - driftingly/rector-laravel 0.29.0 requires rector/rector ^0.18.5 -> found rector/rector[0.18.5, ..., 0.18.13] but it conflicts with your root composer.json require (^0.19.0).

I was led to believe that ^0.18.5 would allow ^0.19.0 but perhaps not when <1.0.0.

Prohibit Rector from making Closures static

Since Laravel tends to depend on lots of behind the scene magic, using static on calls to functions and closures tends not give what you want. Rector should not introduce these things.

I propose adding these somewhere sensible (maybe to all the LARAVEL_number and LARAVEL_CODE_QUALITY):

    $rectorConfig->skip([
        \Rector\Php70\Rector\StaticCall\StaticCallOnNonStaticToInstanceCallRector::class,
        \Rector\CodingStyle\Rector\Closure\StaticClosureRector::class,
        \Rector\CodingStyle\Rector\ArrowFunction\StaticArrowFunctionRector::class,
        \Rector\Php70\Rector\MethodCall\ThisCallOnStaticMethodToStaticCallRector::class,
    ]]);

Support for Laravel 10?

Is there any work being done behind the scenes to support the migration to the current release of Laravel 10?

If not, I'd be glad to open a PR for it. Thank you 😁.

Can't execute rector-laravel

Dear Team,

I installed rector and rector-laravel reffering this site.
And these commands are I executed;

vagrant@homestead:~/code/laravel-project$ php -v
PHP 8.0.25 (cli) (built: Oct 28 2022 18:02:51) ( NTS )
Copyright (c) The PHP Group
Zend Engine v4.0.25, Copyright (c) Zend Technologies
    with Zend OPcache v8.0.25, Copyright (c), by Zend Technologies

vagrant@homestead:~/code$ cd laravel-project/
vagrant@homestead:~/code/laravel-project$ mkdir --parents tools/rector
vagrant@homestead:~/code/laravel-project$ composer req --working-dir=tools/rector rector/rector
・・・
vagrant@homestead:~/code/laravel-project$ tools/rector/vendor/bin/rector --version
Rector 0.14.8
vagrant@homestead:~/code/laravel-project$ tools/rector/vendor/bin/rector init

Then, edit laravel-project/rector.php :

declare(strict_types=1);

use Rector\CodeQuality\Rector\Class_\InlineConstructorDefaultToPropertyRector;
use Rector\Config\RectorConfig;
use Rector\Set\ValueObject\LevelSetList;

return static function (RectorConfig $rectorConfig): void {
    $rectorConfig->paths([
        __DIR__ . '/Flow',
        __DIR__ . '/app',
        __DIR__ . '/bootstrap',
        __DIR__ . '/config',
        __DIR__ . '/database',
        __DIR__ . '/public',
        __DIR__ . '/resources',
        __DIR__ . '/routes',
        __DIR__ . '/storage',
        __DIR__ . '/tests',
        __DIR__ . '/tools',
    ]);

    // register a single rule
    $rectorConfig->rule(InlineConstructorDefaultToPropertyRector::class);

    // define sets of rules
        $rectorConfig->sets([
            LevelSetList::UP_TO_PHP_80
        ]);
};

Execute rector.php
tools/rector/vendor/bin/rector process --dry-run
→run successfully

Install rector-laravel
composer req --working-dir=tools/rector driftingly/rector-laravel
Edit laravel-project/rector.php again

declare(strict_types=1);

use Rector\CodeQuality\Rector\Class_\InlineConstructorDefaultToPropertyRector;
use Rector\Config\RectorConfig;
use Rector\Set\ValueObject\LevelSetList;
use RectorLaravel\Set\LaravelSetList;

return static function (RectorConfig $rectorConfig): void {
    $rectorConfig->paths([
        __DIR__ . '/Flow',
        __DIR__ . '/app',
        __DIR__ . '/bootstrap',
        __DIR__ . '/config',
        __DIR__ . '/database',
        __DIR__ . '/public',
        __DIR__ . '/resources',
        __DIR__ . '/routes',
        __DIR__ . '/storage',
        __DIR__ . '/tests',
        __DIR__ . '/tools',
    ]);

    // register a single rule
    $rectorConfig->rule(InlineConstructorDefaultToPropertyRector::class);

    // define sets of rules
        $rectorConfig->sets([
            UP_TO_LARAVEL_70
        ]);
};

Execute;

vagrant@homestead:~/code/laravel-project$ tools/rector/vendor/bin/rector process --dry-run
[ERROR] Class "Rector\Larave\Set\LaravelSetList" not found

Why this error occured?

Thanks, Kate.

ArgumentAdderRector for nullable arguments should not be added

In `config/sets/laravel60.php:

new ArgumentAdder('Illuminate\Database\Query\Builder', 'from', 1, 'as', null)

The argument 'as' is nullable, which means it is not required.
This rule changes the code as shown:

         DB::query()
-            ->from('table_name')
+            ->from('table_name', null)

which is strange, because the argument is not required, so calling ->from('table_name') is perfectly fine.

    public function from($table, $as = null)
    {

I suggest removing all ArgumentAdder's from laravel60.php for the 'as'-argument, because all four of them are nullable.

AddExtendsAnnotationToModelFactoriesRector rule are not applying any diff

I'm trying to use the AddExtendsAnnotationToModelFactoriesRector to add the @extends annotation to factory classes, but nothing is applied. Am I missing something?

Factory class database/factories/CategoryFactory.php

<?php

namespace Database\Factories;

use Illuminate\Database\Eloquent\Factories\Factory;

class CategoryFactory extends Factory
{
    protected $model = \App\Models\Category::class;

    public function definition()
    {
        return [
            'name' => $this->faker->sentence(),
        ];
    }
}

Rector config rector.php

<?php

declare(strict_types=1);

use Rector\Config\RectorConfig;

return static function (RectorConfig $rectorConfig): void {
    $rectorConfig->paths([
        __DIR__ . '/database',
    ]);

    // register a single rule
    $rectorConfig->rule(RectorLaravel\Rector\Class_\AddExtendsAnnotationToModelFactoriesRector::class);
};

Bug: LARAVEL_STATIC_TO_INJECTION Rule

This rule is converted in the wrong way that's laravel will not allow.

class SkipWithArguments
{
+    public function __construct(private \Illuminate\Routing\Redirector $redirector)
+    {
+    }
     public function run()
     {
-        return redirect('/destination')->back()->with('error', 'Incorrect credential.');
+        return $this->redirector->back('/destination')->back()->with('error', 'Incorrect credential.');
     }
}

As per the documentation of the laravel first parameter of the back method, it's an integer but it's passing a string.

Attributes are lost in conversion

See output of my dry run below.

58) modules/text_product/Database/factories/SupplierFactory.php:5

    ---------- begin diff ----------
@@ @@
 use TextProduct\Models\Supplier;
 use TextProduct\Models\Country;

-$factory->define(Supplier::class, fn(Faker $faker) => [
-    'name' => $faker->company,
-    'origin_country_id' => Country::factory(),
-    'type' => $faker->numberBetween(1, 3),
-]);
+class SupplierFactory extends \Illuminate\Database\Eloquent\Factories\Factory
+{
+    protected $model = Supplier::class;
+}
    ----------- end diff -----------

Applied rules:
 * FactoryDefinitionRector (https://laravel.com/docs/7.x/database-testing#writing-factories)

Name, origin country id and type are lost in conversion.
Note that this is in another folder than a base laravel.

When i converted back the arrow function to anonymous functions (or closure if you prefer this term), this was working as expected.

Allow configuration with `EloquentOrderByToLatestOrOldestRector` rule

By default, EloquentOrderByToLatestOrOldestRector modifies all orderBy and orderByDesc methods to use latest() or oldest() instead.

Our team feels we'd like to do this only regarding timestamps, as oldest('name') or similar could be confusing.

As such, some configuration allowing for explicit column names you'd like to change to oldest() or latest() is desired.


This suggestion was also briefly mentioned in the relevant PR:

These changes apply to all columns in our project, not just date/datetime columns. Is that intended behavior? If so, I'm wondering if rector-laravel is open to configuration, so we can specify which columns should and shouldn't have these rules applied.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.