Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
PHP CS Fixer - Laravel Coding Style Ruleset
<?php
use PhpCsFixer\Config;
use PhpCsFixer\Finder;
$rules = [
'array_syntax' => ['syntax' => 'short'],
'binary_operator_spaces' => [
'default' => 'single_space',
'operators' => ['=>' => null]
],
'blank_line_after_namespace' => true,
'blank_line_after_opening_tag' => true,
'blank_line_before_statement' => [
'statements' => ['return']
],
'braces' => true,
'cast_spaces' => true,
'class_attributes_separation' => [
'elements' => ['method']
],
'class_definition' => true,
'concat_space' => [
'spacing' => 'none'
],
'declare_equal_normalize' => true,
'elseif' => true,
'encoding' => true,
'full_opening_tag' => true,
'fully_qualified_strict_types' => true, // added by Shift
'function_declaration' => true,
'function_typehint_space' => true,
'heredoc_to_nowdoc' => true,
'include' => true,
'increment_style' => ['style' => 'post'],
'indentation_type' => true,
'linebreak_after_opening_tag' => true,
'line_ending' => true,
'lowercase_cast' => true,
'lowercase_constants' => true,
'lowercase_keywords' => true,
'lowercase_static_reference' => true, // added from Symfony
'magic_method_casing' => true, // added from Symfony
'magic_constant_casing' => true,
'method_argument_space' => true,
'native_function_casing' => true,
'no_alias_functions' => true,
'no_extra_blank_lines' => [
'tokens' => [
'extra',
'throw',
'use',
'use_trait',
]
],
'no_blank_lines_after_class_opening' => true,
'no_blank_lines_after_phpdoc' => true,
'no_closing_tag' => true,
'no_empty_phpdoc' => true,
'no_empty_statement' => true,
'no_leading_import_slash' => true,
'no_leading_namespace_whitespace' => true,
'no_mixed_echo_print' => [
'use' => 'echo'
],
'no_multiline_whitespace_around_double_arrow' => true,
'multiline_whitespace_before_semicolons' => [
'strategy' => 'no_multi_line'
],
'no_short_bool_cast' => true,
'no_singleline_whitespace_before_semicolons' => true,
'no_spaces_after_function_name' => true,
'no_spaces_around_offset' => true,
'no_spaces_inside_parenthesis' => true,
'no_trailing_comma_in_list_call' => true,
'no_trailing_comma_in_singleline_array' => true,
'no_trailing_whitespace' => true,
'no_trailing_whitespace_in_comment' => true,
'no_unneeded_control_parentheses' => true,
'no_unreachable_default_argument_value' => true,
'no_useless_return' => true,
'no_whitespace_before_comma_in_array' => true,
'no_whitespace_in_blank_line' => true,
'normalize_index_brace' => true,
'not_operator_with_successor_space' => true,
'object_operator_without_whitespace' => true,
'ordered_imports' => ['sortAlgorithm' => 'alpha'],
'phpdoc_indent' => true,
'phpdoc_inline_tag' => true,
'phpdoc_no_access' => true,
'phpdoc_no_package' => true,
'phpdoc_no_useless_inheritdoc' => true,
'phpdoc_scalar' => true,
'phpdoc_single_line_var_spacing' => true,
'phpdoc_summary' => true,
'phpdoc_to_comment' => true,
'phpdoc_trim' => true,
'phpdoc_types' => true,
'phpdoc_var_without_name' => true,
'psr4' => true,
'self_accessor' => true,
'short_scalar_cast' => true,
'simplified_null_return' => false, // disabled by Shift
'single_blank_line_at_eof' => true,
'single_blank_line_before_namespace' => true,
'single_class_element_per_statement' => true,
'single_import_per_statement' => true,
'single_line_after_imports' => true,
'single_line_comment_style' => [
'comment_types' => ['hash']
],
'single_quote' => true,
'space_after_semicolon' => true,
'standardize_not_equals' => true,
'switch_case_semicolon_to_colon' => true,
'switch_case_space' => true,
'ternary_operator_spaces' => true,
'trailing_comma_in_multiline_array' => true,
'trim_array_spaces' => true,
'unary_operator_spaces' => true,
'visibility_required' => [
'elements' => ['method', 'property']
],
'whitespace_after_comma_in_array' => true,
];
$project_path = getcwd();
$finder = Finder::create()
->in([
$project_path . '/app',
$project_path . '/config',
$project_path . '/database',
$project_path . '/resources',
$project_path . '/routes',
$project_path . '/tests',
])
->name('*.php')
->notName('*.blade.php')
->ignoreDotFiles(true)
->ignoreVCS(true);
return Config::create()
->setFinder($finder)
->setRules($rules)
->setRiskyAllowed(true)
->setUsingCache(true);
@ejunker

This comment has been minimized.

Copy link

@ejunker ejunker commented Jul 18, 2019

no_extra_blank_lines and phpdoc_indent are duplicated

@manniL

This comment has been minimized.

Copy link

@manniL manniL commented Jul 18, 2019

And no_extra_blank_lines has two different constraints 🤔

@laravel-shift

This comment has been minimized.

Copy link
Owner Author

@laravel-shift laravel-shift commented Jul 26, 2019

Corrected.

@paulcdejean

This comment has been minimized.

Copy link

@paulcdejean paulcdejean commented Oct 28, 2019

    'concat_space' => [
        'spacing' => 'none'
    ],

What is the reason for this?

Here it says "use a space before and after ."

https://github.com/php-fig-rectified/fig-rectified-standards/blob/master/PSR-2-R-coding-style-guide-additions.md#multi-line-declarationconditionconcatenation

@jasonmccreary

This comment has been minimized.

Copy link

@jasonmccreary jasonmccreary commented Oct 28, 2019

Because it's Laravel's standard - https://docs.styleci.io/presets#laravel

@axit-joost

This comment has been minimized.

Copy link

@axit-joost axit-joost commented Jan 8, 2020

Unless my tired eyes are deceiving me, I think that no_unused_use or no_unused_imports is missing? It's in the Style CI Laravel preset.

@perifer

This comment has been minimized.

Copy link

@perifer perifer commented Jan 17, 2020

Great resource!

What do you think about adding return_type_declaration => true?

PSR-12 sais:

When you have a return type declaration present, there MUST be one space after the colon followed by the type declaration. The colon and declaration MUST be on the same line as the argument list closing parenthesis with no spaces between the two characters.

public function functionName(int $arg1, $arg2): string

https://www.php-fig.org/psr/psr-12/#45-method-and-function-arguments

Update: also seems to be in the Laravel preset, https://docs.styleci.io/presets#laravel

@slavarazum

This comment has been minimized.

Copy link

@slavarazum slavarazum commented Jan 17, 2020

Is there a way to make 2 spaces in docblocks like in basic Laravel Skeleton?

@jasonmccreary

This comment has been minimized.

Copy link

@jasonmccreary jasonmccreary commented Jan 17, 2020

@perifer I will review this and see if it belongs in this native ruleset.

@slavarazum, I think that's a tricky one. There are some settings for docblocks. But I couldn't lock it down just right. Let me know if you find anything.

@slavarazum

This comment has been minimized.

Copy link

@slavarazum slavarazum commented Jan 17, 2020

@jasonmccreary
Also, haven't found appropriate rule, when setup ruleset for Laravel projects before...

https://laravel.com/docs/6.x/contributions#coding-style

Laravel follows PSR2 Standard, I think we can simplify this config by adding @PSR2 rule and remove all direct rules from it.

@dmason30

This comment has been minimized.

Copy link

@dmason30 dmason30 commented Apr 23, 2020

I would much prefer if it just did some basic PSR2, for those using their own linter like PHP_Code_Sniffer linting rules like simplified_null_return cause me nothing but hassle.

@jasonmccreary

This comment has been minimized.

Copy link

@jasonmccreary jasonmccreary commented Apr 23, 2020

Yeah, I actually got bitten by the simplified_null_return too. Think I'll remove it as it's a risky rule anyway. 😅

@dmason30

This comment has been minimized.

Copy link

@dmason30 dmason30 commented Apr 23, 2020

@jasonmccreary Yeah that would be great 😄 , I don't expect you to support other linters but if I included an php_cs file with an empty rules array and without installing the php_cs_fixer package would that stop any lints from running in a shift? Or would you need me to have the package as a dependency

@jasonmccreary

This comment has been minimized.

Copy link

@jasonmccreary jasonmccreary commented Apr 23, 2020

@dmason30, you're welcome to try. Can't guarantee Shift would be as accurate as some tasks still rely on a basic code style. Not many though. If you want to throw a dummy .php_cs file in your project, I'd recommend at least using the PSR-2 preset. It'd be a one-liner and likely give you the same results.

TBH, the fuss about Shift applying the Laravel code style has never made much sense to me. Shift does everything in atomic commits which can be ignored/reviewed/reverted easily. In addition, you can reapply your own code style before merging Shift's PR. So while I appreciate the "personal style" aspect, it's a painless "fix" compared to the overall upgrade process.

@dmason30

This comment has been minimized.

Copy link

@dmason30 dmason30 commented Apr 23, 2020

I have no real issue with it running the lint - it normally introduces me to rules that I end up adding to our custom configuration which means less changes are made each time we do a shift. I am happy with 99% of the changes it makes its just I feel I need to sanity check it each time because it includes risky changes and our custom linter handles reverting any non-risky changes where we need it too. When it changes 2000 files its a bit of a task to go through it.

TBH I am leaning towards having a tweaked version of this config in our projects and adding that to our linting step and using PHP_Code_Sniffer for some of the rules php_cs_fixer doesn't have.

@eduarguz

This comment has been minimized.

Copy link

@eduarguz eduarguz commented May 10, 2020

Hi guys, I have been using this ruleset for many projects even without using laravel shift in these projects.

Inspired by this article, Sharing PHP-CS-Fixer rules across projects and teams, I have made this config into a package (WIP for now).

Wanted to ask:

  • To anyone: Is this useful? At least it is for me now 😬....

  • To @jasonmccreary:
    Is it ok to use this ruleset as an opensource package?
    Is it ok to use Laravel Shift name a few times in the readme?
    Is it ok to use the ShiftCS name as a namespace in this package?
    Is it ok to use the shift-php-cs name as the name of the package?

You can see the Work In Progress here... https://github.com/eduarguz/shift-php-cs

@laravel-shift

This comment has been minimized.

Copy link
Owner Author

@laravel-shift laravel-shift commented May 11, 2020

@eduarguz. Absolutely no problem. Any link to laravelshift.com in your readme would be appreciated.

@iraklisg

This comment has been minimized.

Copy link

@iraklisg iraklisg commented Jun 3, 2020

Shouldn't be 'ordered_imports' => ['sortAlgorithm' => 'length'], for Laravel 🤔?

@stefanbauer

This comment has been minimized.

Copy link

@stefanbauer stefanbauer commented Jun 3, 2020

No, they changed it some versions ago.

@dillingham

This comment has been minimized.

Copy link

@dillingham dillingham commented Jul 28, 2020

I added 'php_unit_method_casing' => true to match laravel's test name style

@jasonmccreary

This comment has been minimized.

Copy link

@jasonmccreary jasonmccreary commented Jul 28, 2020

A reminder this is the laravel/laravel code style, not necessary the framework style. There are very slight differences.

Furthermore, from my understanding, that's not a valid value. You should explicitly set case one way or the other.

@dillingham

This comment has been minimized.

Copy link

@dillingham dillingham commented Jul 28, 2020

@jasonmccreary good to know thanks.

I understood it as that the default, when set, is camel,
No harm in being explicit ['case' => 'camel_case'] 😀

@RahulDey12

This comment has been minimized.

Copy link

@RahulDey12 RahulDey12 commented Jul 29, 2020

Anyone has an idea of how to fix blade file styles.

@Arkhas

This comment has been minimized.

Copy link

@Arkhas Arkhas commented Sep 17, 2020

I have an issue with one of the parameters when using optionnal parameters in routing with Dependancy Injection, for exemple :

this code is just for exemple purpose

Route::get('user/{name?}', function ($name = null, Request $request) {
    return $name;
});

is transform into :

Route::get('user/{name?}', function ($name, Request $request) {
    return $name;
});

passing 'no_unreachable_default_argument_value' => true, to 'no_unreachable_default_argument_value' => false, resolve this issue

@eduarguz

This comment has been minimized.

Copy link

@eduarguz eduarguz commented Sep 18, 2020

@Arkhas I think you can swap the parameters order, this happens due to Laravel's magic parameter injection. Saw that somewhere but could not find the link :(

@jasonmccreary

This comment has been minimized.

Copy link

@jasonmccreary jasonmccreary commented Sep 18, 2020

@Arkhas, the proper way to write that closure would be:

Route::get('user/{name?}', function (Request $request, $name = null) {
    return $name;
});

Per the rule that you noted, the way you have it has an "unreachable parameter" and technically incorrect from a PHP standpoint. You're relying on the magic dependency resolution of Laravel to allow that order. Which could change in the future.

@delta1186

This comment has been minimized.

Copy link

@delta1186 delta1186 commented Oct 14, 2020

@jasonmccreary are you using this setting in Shift production? Just wondering as tlint is using 1 space. Just trying to figure out which standard to use. tighten/tlint#194

'concat_space' => [
        'spacing' => 'none'
    ],

Thanks, Kevin

@jasonmccreary

This comment has been minimized.

Copy link

@jasonmccreary jasonmccreary commented Oct 14, 2020

@delta1186, Laravel does not have a space between the concat operator.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.