78
63

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

ランサーズAdvent Calendar 2017

Day 2

php_cs_fixerのオプションをハックする ~ 実行時のdiffつき ~

Last updated at Posted at 2017-12-01

ランサーズ Advent Calendar 2017第二弾、12/2は上野が担当させてもらいます。

はじめに

今年はLancers Topの開発を通じて、CakePHP1.3の世界から3.4, 3.5の世界に飛び出し、CakePHP3.5の移行ガイドの翻訳にチャレンジするなどしてみて、アクセスがめんどくさい情報をわかりやすく伝えることはOSSに機能を一つ追加することよりもむしろ価値があるのではないかと、コミュニティーに対する還元の考え方が変わった1年でした。

そこで去年度の「githubのissue, pull request 検索をハックする!」に引き続きハックシリーズで「php_cs_fixerのオプションをハックする」と称してphpのコーディング規則を揃え自動修正してくれるphp_cs_fixerでどのような修正が可能か、実行時のdiffも含めご紹介します。

本題の前の準備系(基本割愛しています)

そもそもphp_cs_fixerってなに?

PHPのコーディングスタイルを揃えて自動で修正してくれるlibraryです。

  • メンバーの好みや癖で同じリポジトリで記述が異なるようなことを防いでくれます。
  • レビューでする側も受ける側もストレスなコーディング規約に関する指摘がなくなります
  • 宗教戦争が収まり平和な世界の中でで大事なビジネスロジックに集中した開発ができます

PHPには他にPHP CodeSnifferがあります

インストールと実行コマンド

幾つか記事が出ているので省略します。

## 例1) composerで導入
$ composer require friendsofphp/php-cs-fixer
$ vi .php_cs
$ ./vendor/friendsofphp/php-cs-fixer/php-cs-fixer fix --config=./.php_cs

## 例1) homebrewで導入
$ brew install homebrew/php/php-cs-fixer
$ vi .php_cs
$ php-cs-fixer fix --config=./.php_cs

.php_csのオプション紹介(本題)

.php_csの記述サンプル

対象のフォルダとルールを設定します。

$finder = PhpCsFixer\Finder::create()
    ->notName('README.md')
    ->notName('.php_cs')
    ->notName('composer.*')
    ->notName('phpunit.xml*')
    ->notName('*.xml')
    ->exclude('tests')    // ここから除外フォルダー
    ->exclude('config/Seeds')
    ->exclude('vendor')
    ->exclude('plugin')
    ->exclude('tmp')
    ->in(__DIR__);

return PhpCsFixer\Config::create()
    ->setRules([
        '@PSR2' => true,
        '@PHP71Migration' => true,
        'array_syntax' => ['syntax' => 'short'],
        'ereg_to_preg' => true,
        'function_typehint_space' => true,
        'no_unused_imports' => true,
        'no_empty_comment' => true,
        'no_empty_phpdoc' => true,
        'no_whitespace_before_comma_in_array' => true, 
        // 'ordered_imports' => true,
        'return_type_declaration' => true,
        'ternary_operator_spaces' => true,
        'whitespace_after_comma_in_array' => true,
        'psr4' => true,
    ])
    ->setUsingCache(false)
    ->setFinder($finder);

以後は利用できるルールの各種オプションを本家よりわかりやすい説明を目指して、変換前後のdiffつきで紹介します。
お好みのコーディング規約に沿って組み合わせて使ってください。

array_syntax

arrayの記述方法を短縮系にするか

'array_syntax' => ['syntax' => 'short'],
'array_syntax' => array('syntax' => 'long'),
short long
array_syntax_short.png array_syntax_long.png

binary_operator_spaces

= や => などの演算子を揃えるかを設定できます

'binary_operator_spaces' => [
    'align_double_arrow' => true,
    'align_equals' => true,
],
align_equals align_double_arrow
スクリーンショット 2017-11-29 1.33.51.png スクリーンショット 2017-11-29 1.34.51.png

blank_line_after_namespace

ネームスペースの後ろに一行改行を入れます。

  • @PSR-2, @Symfonyでデフォルトtrueです。
'blank_line_after_namespace' => true
スクリーンショット 2017-11-29 1.51.21.png

blank_line_after_opening_tag

PHPの開始タグの後に一行改行を入れます

  • @Symfonyでデフォルトtrueで指定されます
'blank_line_after_opening_tag' => true,
スクリーンショット 2017-11-29 1.53.11.png

blank_line_before_return

returnの前に一行改行を入れます

'blank_line_before_return' => true,
スクリーンショット 2017-11-29 1.56.46.png

blank_line_before_statement

特定の記述の前に一行改行を入れる

  • @Symfonyではデフォルトでいかが設定されている
'blank_line_before_statement' => [
    'statements' => [
        'break', 
        'continue', 
        'declare', 
        'return', 
        'throw', 
        'try'
    ]
],
スクリーンショット 2017-11-29 2.02.11.png

braces

各構造体は、中括弧で囲んで適切にインデントさせる必要があるためフォーマットを統一する

  • @PSR-2, @Symfonyで以下のデフォルト指定がされている。
'braces' => [
    'allow_single_line_closure' => false,
    'position_after_anonymous_constructs' => 'same'
    'position_after_control_structures' => 'same'
    'position_after_functions_and_oop_constructs' => 'next'
],

allow_single_line_closure

クロージャーを1行で書くことを許容する

'braces' => [
    'allow_single_line_closure' => false,
],
スクリーンショット 2017-11-29 2.08.39.png

position_after_anonymous_constructs

クロージャや無名クラスの中括弧開始の位置を指定

  • same: 同じ行、 next: 次の行 が指定できる
'braces' => [
    'position_after_anonymous_constructs' => 'next'
],
スクリーンショット 2017-11-29 2.13.28.png

position_after_control_structures

if,else,for,foreach,try などの制御構造の中括弧開始位置を指定

  • same: 同じ行、 next: 次の行 が指定できる
'braces' => [
    'position_after_control_structures' => 'next'
],
スクリーンショット 2017-11-29 2.17.34.png

position_after_functions_and_oop_constructs

class, function などの宣言の後で用いる中括弧開始位置を指定

  • same: 同じ行、 next: 次の行 が指定できる
'braces' => [
    'position_after_functions_and_oop_constructs' => 'same'
],
スクリーンショット 2017-11-29 2.13.28.png

cast_spaces

キャストをした時に後ろにスペースを開けるか。

  • @Symfonyのときのデフォルトはsingle
  • single: 半角空白を空ける 、none: 空白を入れない
'cast_spaces' => [
    'space' => 'single'
],
スクリーンショット 2017-11-29 2.28.53.png

class_keyword_remove

::classのキーワードを絶対パスの名前に置き換える

'class_keyword_remove' => true,

スクリーンショット 2017-11-30 19.49.43.png

combine_consecutive_issets, combine_consecutive_unsets

isset(X) && isset(Y) && ...の記述を isset(X,Y,...) に置き換える
unset(x) が続く記述を unset(x,y,...) に置き換える

'combine_consecutive_issets' => true,
'combine_consecutive_unsets' => true,

スクリーンショット 2017-11-30 19.58.51.png

compact_nullable_typehint

nullを許容する型宣言で余計な空白を削除する

'compact_nullable_typehint' => true,

スクリーンショット 2017-11-30 20.02.48.png

concat_space

結合演算子の前後に空ける空白の指定

  • Symfonyではnoneがデフォルト指定されます
'concat_space' => [
    'spacing' => 'single'
],

スクリーンショット 2017-11-30 20.10.05.png

declare_strict_types (PHP>=7.0)

型を厳密に判断する strict モードを強制する

  • @PHP70Migration:risky, @PHP71Migration:risky で利用できます
'declare_strict_types' => true,

スクリーンショット 2017-11-30 21.06.56.png

dir_constant

dirname(__FILE__)__DIR__ に書き換えます。

  • dirname()をオーバライドしているときはリスクを伴います
'dir_constant' => true,

elseif

空白のあるelse if の代わりに elseif を使うようにします

  • @PSR2, @Symfonyでデフォルトtrueです
'elseif' => true,

スクリーンショット 2017-11-30 20.30.31.png

encoding

PHPコードの文字コードをBOMでなくUTF-8にします

  • @PSR1,@PSR2, @Symfonyでデフォルトtrueです
'encoding' => true,

ereg_to_preg

非推奨になっている ereg系 の処理を pregに変換します

  • ereg関数をオーバーライドしている場合リスクを伴います
  • @Symfony:riskyの場合にデフォルトtureです
'ereg_to_preg' => true,

スクリーンショット 2017-11-30 20.39.54.png

full_opening_tag

ロングタグ(<?php) と echoを伴うショートタグ(<?=) 以外を使用禁止にします
@PSR1,@PSR2, @Symfonyでデフォルトtrueです

'full_opening_tag' => true,

function_declaration

関数宣言後のスペース設定

  • @PSR2,@Symfonyでデフォルトで以下が設定されています
'function_declaration' => [
    'closure_function_spacing' => 'one',  // クロージャーのfunctionの後ろのスペース
],

スクリーンショット 2017-11-30 20.45.34.png

function_to_constant

特定の関数を定数に置き換えます。

  • @Symfony:riskではデフォルトで以下が設定されています。
  • 各関数をオーバライドしていたときにはリスクを伴います。
'function_to_constant' => [
    'functions' => ['get_class', 'php_sapi_name', 'phpversion', 'pi']
],

スクリーンショット 2017-11-30 21.06.22.png

function_typehint_space

関数の返り値の型宣言にスペースが抜けていると補完する

'function_typehint_space' => true,

スクリーンショット 2017-11-30 21.09.35.png

general_phpdoc_annotation_remove

特定のアノテーションを削除します

  • デフォルトは[]です
'general_phpdoc_annotation_remove' => [
    'annotations' => [
        'todo'
    ]
],

スクリーンショット 2017-11-30 21.12.46.png

header_comment

ヘッダーコメントを追加、削除、変更します

  • デフォルトで以下が設定されています。headerは必須項目なので必ず指定が必要です
'header_comment' => [
    'commentType' => 'comment',
    'header' => '', // <== デフォルト指定なし指定必須項目
    'location' => 'after_declare_strict',
    'separate' => 'both',
]

commentType

comment(default) PHPDoc
スクリーンショット 2017-11-30 21.18.11.png スクリーンショット 2017-11-30 21.22.25.png

location

after_declare_strict(default) after_open
スクリーンショット 2017-11-30 21.25.36.png スクリーンショット 2017-11-30 21.25.48.png

separate

both(default) bottom none top
スクリーンショット 2017-11-30 21.18.11.png スクリーンショット 2017-11-30 21.28.21.png スクリーンショット 2017-11-30 21.28.12.png スクリーンショット 2017-11-30 21.27.51.png

heredoc_to_nowdoc

heredoc のうち変換可能なものを nowdoc に変換する

'heredoc_to_nowdoc' => true,

スクリーンショット 2017-11-30 21.35.03.png

include

include, require, ファイルパスは、単一のスペースで区切る必要があります。ファイルパスをカッコの中に入れないでください

'include' => true,

スクリーンショット 2017-11-30 21.39.55.png

increment_style

可能であれば、インクリメントおよびデクリメント演算子はpre,postで統一してを使用する必要があります。

  • pre, postを指定できます。
  • デフォルトはpreです
'increment_style' => [
    'style' => 'post'
],

スクリーンショット 2017-11-30 21.48.35.png

indentation_type

コードインデントに定められたインデントを使用しなければいけない

  • @PSR2,@Symfonyでデフォルトで true が設定されます。
'indentation_type' => true,

is_null

is_null($hoge)null === $hogeに置き換える

  • is_null()をオーバーライドしている場合リスクを伴います
  • 後述するuse_yoda_styletrueの場合はデフォルトが true で設定されます
'is_null' => true,

line_ending

全てのPHPファイルで同じ改行コードを使わなくてはいけない

  • @PSR2,@Symfonyでデフォルトで true が設定されます。
'line_ending' => true,

linebreak_after_opening_tag

開始タグの後ろに改行を入れて開始タグの行には記述がないようにする

'linebreak_after_opening_tag' => true,

スクリーンショット 2017-11-30 22.01.24.png

list_syntax (PHP >= 7.1)

listで使用する構造を統一します。

  • デフォルトはlongです
'list_syntax' => [
    'syntax' => 'long'
],
long(default) short
スクリーンショット 2017-11-30 22.08.55.png スクリーンショット 2017-11-30 22.09.05.png

lowercase_cast, lowercase_constants, lowercase_keywords

特定の記述を小文字で記述することを強制する

'lowercase_cast' => true,
'lowercase_constants' => true,
'lowercase_keywords' => true,
lowercase_cast lowercase_constants lowercase_keywords
@PSR2 --- true true
@Symfony true true true
画像 スクリーンショット 2017-11-30 22.14.23.png スクリーンショット 2017-11-30 22.17.37.png スクリーンショット 2017-11-30 22.18.12.png

mb_str_functions

マルチバイト非対応関数をマルチバイト対応関数(mb_xxxx)に置き換える

  • 該当の関数をオーバライドしていたときにリスクを伴います
'mb_str_functions' => true,

スクリーンショット 2017-12-02 0.52.53.png

method_argument_space

メソッドの引数とメソッド呼び出しで、各カンマの前にスペースを禁止して、各カンマの後にスペースを求めます。

  • 2つのオプションを持ち@PSR2,@Symfonyでデフォルトでいかが指定されています
'method_argument_space' => [
    'ensure_fully_multiline' => false,
    'keep_multiple_spaces_after_comma' => false,
],

標準

前方にはカンマを入れない 後方にカンマを入れる
スクリーンショット 2017-12-02 1.06.36.png スクリーンショット 2017-12-02 1.06.52.png

ensure_fully_multiline

複数行に渡るときには1行に引数一つとする

'method_argument_space' => [
    'ensure_fully_multiline' => true,
],

スクリーンショット 2017-12-02 1.06.59.png

複数のスペースを許容する(falseで複数スペースを単一にする)

'method_argument_space' => [
    'keep_multiple_spaces_after_comma' => false,
],

スクリーンショット 2017-12-02 1.06.44.png

method_separation

メソッドの前後の分割は一行改行を強制する

  • @Symfonyでデフォルトtrueが指定されます
'method_separation' => true,

スクリーンショット 2017-12-02 1.15.07.png

modernize_types_casting

intval,floatval,doubleval,strval,boolvalの関数をキャストに置き換えます

  • @Symfony:riskyでデフォルトtrueです
  • 各関数をオーバライドしていたときはリスクを伴います
'modernize_types_casting' => true,

スクリーンショット 2017-12-02 1.20.31.png

native_function_invocation

名前解決の速度を上げるために内部関数の前に\を付与する

  • あらゆる関数をオーバライドしていたときにリスクを伴います
'native_function_invocation' => [
    'exclude' => [],
],

スクリーンショット 2017-12-02 1.28.49.png

new_with_braces

newを用いて生成したインスタンスには後方に丸括弧を必要とします

'new_with_braces' => true,

スクリーンショット 2017-12-02 1.32.25.png

no_alias_functions

エイリアス関数の代わりに元の関数を使うように置き換えます

  • エイリアス関数をオーバライドしていたときにリスクを伴います
'no_alias_functions' => true,

スクリーンショット 2017-12-02 1.37.14.png

no_blank_xxxxxx

'no_blank_lines_after_class_opening' => true,
'no_blank_lines_after_phpdoc' => true,
'no_blank_lines_before_namespace' => true,
'no_break_comment' => true,
no_blank_lines_after_class_opening no_blank_lines_after_phpdoc no_blank_lines_before_namespace no_break_comment
@Symfony true true true
@PSR2 true
画像 スクリーンショット 2017-12-02 1.40.50.png スクリーンショット 2017-12-02 1.41.51.png スクリーンショット 2017-12-02 1.43.56.png スクリーンショット 2017-12-02 1.44.54.png

no_closing_tag

phpのとじタグ?>はファイルの最後尾から削除します

  • @PRS2,@Symfonyでデフォルトtrueです

スクリーンショット 2017-12-02 1.52.06.png

no_empty_comment, no_empty_phpdoc, no_empty_statement

空のコメントやphpdoc、ステートメントを削除します

  • @Symfonyでデフォルトtrueです
'no_empty_comment' => true,
'no_empty_phpdoc' => true,
'no_empty_statement' => true,
no_empty_comment no_empty_phpdoc no_empty_statement
スクリーンショット 2017-12-02 1.57.15.png スクリーンショット 2017-12-02 1.56.59.png スクリーンショット 2017-12-02 1.56.52.png

no_extra_consecutive_blank_lines

余計な改行を削除します

  • @Symfonyでデフォルトで以下が指定されます
'no_extra_consecutive_blank_lines' => [
    'tokens' => ['extra']
],

スクリーンショット 2017-12-02 2.01.36.png

no_leading_import_slash

use宣言先頭のバックスラッシュを削除します

  • @Symfonyでデフォルトtrueです
'no_leading_import_slash' => true,

スクリーンショット 2017-12-02 2.06.36.png

no_leading_namespace_whitespace

namespaceの前にスペースがあったとき削除します

  • @Symfonyでデフォルトtrueです
'no_leading_namespace_whitespace' => true,

スクリーンショット 2017-12-02 2.08.53.png

no_mixed_echo_print

echoと``print`のどちらかに記述を統一します

  • @Symfonyでデフォルトechoが指定されます
'no_mixed_echo_print' => [
    'use' => 'echo'
],//

no_multiline_whitespace_around_double_arrow

=>の前後で複数行になるスペースを禁止します

  • @Symfonyでデフォルトtrueです
'no_multiline_whitespace_around_double_arrow' => true,

スクリーンショット 2017-12-02 2.18.59.png

no_multiline_whitespace_before_semicolons, no_singleline_whitespace_before_semicolons

セミコロンの前で複数行になるスペースを禁止します
no_singleline_whitespace_before_semicolonsは1行でもセミコロンの前にスペースを置くことを禁止します

  • @Symfonyでデフォルトtrueです
'no_multiline_whitespace_before_semicolons' => true,
'no_singleline_whitespace_before_semicolons' => true,
no_multiline_whitespace_before_semicolons no_singleline_whitespace_before_semicolons
スクリーンショット 2017-12-02 2.19.16.png スクリーンショット 2017-12-02 2.29.06.png

no_php4_constructor

PHP4での形式の__constructを書き換えます

'no_php4_constructor' => true,

no_short_bool_cast

二重感嘆符を使ったboolキャストを禁止します

  • @Symfonyでデフォルトtrueです

スクリーンショット 2017-12-02 2.26.10.png

no_short_echo_tag

<?=の代わりにロングタグの<?php echoに置き換えます

no_spaces_after_function_name

メソッド名の宣言後にメソッド名とカッコの間にスペースを入れてることを禁止します

  • @PRS2,@Symfonyでデフォルトtrueです
'no_spaces_after_function_name' => true

スクリーンショット 2017-12-02 2.30.51.png

no_spaces_inside_parenthesis

開始カッコの後と閉じカッコの前のスペースを削除します

  • @PRS2,@Symfonyでデフォルトで以下が指定されます
'no_spaces_inside_parenthesis' => true,

スクリーンショット 2017-12-02 2.42.26.png

no_superfluous_elseif,

no_useless_else

(例えばreturnしている場合など)不要なelseififに置き換えます
不要なelseを削除します

'no_superfluous_elseif' => true,
'no_useless_else' => true,
no_superfluous_elseif no_useless_else
スクリーンショット 2017-12-02 2.44.27.png スクリーンショット 2017-12-02 3.12.43.png

no_trailing_comma_in_list_call

リスト関数で余計なカンマを削除します

  • @Symfonyでデフォルトtrueです
'no_superfluous_elseif' => true,

スクリーンショット 2017-12-02 2.48.45.png

no_trailing_comma_in_singleline_array

単一行で記述する配列で余計なカンマを削除します

  • @Symfonyでデフォルトtrueです
'no_trailing_comma_in_singleline_array' => true,

スクリーンショット 2017-12-02 2.49.57.png

no_trailing_whitespace

末尾の空白行を削除する

  • @PRS2,@Symfonyでデフォルトtrueです
'no_trailing_whitespace' => true,

スクリーンショット 2017-12-02 2.53.47.png

no_trailing_whitespace_in_comment

コメントとphpdoc内の余計な空白を削除する

  • @PRS2,@Symfonyでデフォルトtrueです
'no_trailing_whitespace_in_comment' => true,

no_unneeded_control_parentheses

制御構造の周囲にある余計な( )を削除します

  • @Symfonyでデフォルトで以下が指定されます
'no_unneeded_control_parentheses' => [
    'statements' => ['break', 'clone', 'continue', 'echo_print', 'return', 'switch_case', 'yield']
],

スクリーンショット 2017-12-02 2.58.09.png

no_unneeded_curly_braces

コントール制御以外の不要な{ }を削除します。

  • @Symfonyでデフォルトtrueです
'no_unneeded_curly_braces' => true,

no_unneeded_final_method

final宣言されているクラス内でfinal宣言された関数からfinalを削除します

  • @Symfonyでデフォルトtrueです
'no_unneeded_curly_braces' => true,

スクリーンショット 2017-12-02 3.03.52.png

no_unreachable_default_argument_value

デフォルト値が後続の引数で指定されていない場合は引数のデフォルト値を削除する

  • 関数のシグネチャを変更します。したがって、それらに依存するシステム(例えば、リフレクションを通して)を使用している場合(Symfonyの一部のコンポーネントなど)ではリスクを伴います。
'no_unreachable_default_argument_value' => true,

スクリーンショット 2017-12-02 3.05.47.png

no_unused_imports

使っていないuse宣言を削除します。

  • @Symfonyでデフォルトtrueです
'no_unused_imports' => true,

スクリーンショット 2017-12-02 3.09.47.png

no_useless_return

メソッド末尾で何も返さないreturnを削除します

'no_useless_return' => true,

スクリーンショット 2017-12-02 3.14.35.png

no_whitespace_before_comma_in_array

配列内で、カンマの前にスペースを禁止します

  • @Symfonyでデフォルトtrueです
'no_whitespace_before_comma_in_array' => true,

スクリーンショット 2017-12-02 3.17.27.png

no_whitespace_in_blank_line

空白行でスペースを禁止します

  • @Symfonyでデフォルトtrueです
'no_whitespace_in_blank_line' => true,

non_printable_character ~ yoda_style

comming soon!!!


始めてみたら相当な量があり、想像以上のボリュームになってしまいました。
やりだしたら徹底的にやりたい性格なので12/2までに最後まで到達できませんでしたが、一番わかり易いリファレンスになるように最後は気合と意地で随時追記をしていきます。

ランサーズのアドベントカレンダーはエンジニアブログを中心に引き続き各メンバーが公開していきます。
明日の担当は平成元年生まれの同い年で、ランサーズが誇るReactおじさん @numanomanu さんです!! お楽しみに

78
63
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
78
63

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?