0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【PHPフレームワークFlow】Flowでmago試す

0
Posted at

はじめに

ちょっと前にmagoのv1.0がリリースされたという話を聞きました。
Flowのプロジェクトでどんな感じで使えるのか試してみたいので、インストールから試してみます。

magoとは

magoとは、phpの静的解析、リンター、フォーマッターなどを担う比較的新めのツールです。
Rustで書かれていて速いらしいので、試してみようと思います。

mago試す

install

まずはcomposerに入れます。

composer require --dev "carthage-software/mago:^1.47.2"

composerに入るのはmagoのwrapperのようで、初回実行時に色々ダウンロードするようでした。
また、flowの場合は./bin/magoに実行ファイルが入るので注意です。

% ./bin/mago
Mago: The powerful PHP toolchain. Lint, format, and analyze your code with ease.

Usage: mago [OPTIONS] <COMMAND>

Commands:
  init                  Initialize a new Mago configuration file
  config                Display the effective configuration
  extension             Inspect or validate configured external extensions
  list-files            List all files that will be processed
  cst                   Display the abstract syntax tree (CST) of PHP code
  lint                  Run linting rules on PHP code
  analyze               Perform static analysis on PHP code
  guard                 Enforce architectural rules and layer dependencies
  inspect-baseline      Inspect and visualize a baseline file
  format                Format PHP code according to style settings
  self-update           Update Mago to the latest version
  generate-completions  Generate shell completions for the given shell
  version               Display Mago's version
  help                  Print this message or the help of the given subcommand(s)

Options:
      --workspace <WORKSPACE>          The path to the workspace directory
      --config <CONFIG>                The path to the configuration file
      --php-version <PHP_VERSION>      The PHP version to use for parsing and analysis
      --threads <THREADS>              The number of threads to use for linting, formatting, and analysis
      --allow-unsupported-php-version  Allow using an unsupported PHP version
      --no-version-check               Silence the project version drift warning
      --no-extensions                  Disable all external extensions for this invocation
      --colors <COLORS>                When to use colored output. Can be "auto", "always", or "never" [default: auto] [possible values: auto, always,
                                       never]
  -h, --help                           Print help (see more with '--help')
  -V, --version                        Print version

mago init

mago init で初期設定を行います。
質問に回答して設定ファイルを作成してくれます。

% ./bin/mago init

 Mago

 ⬩ Welcome! Let's get you set up.

  ╭─ Step 1: Project Setup
  │
  │  Found `composer.json`. Use it to auto-configure project paths & PHP version? · yes
  │
  │  Reading composer.json...
  │  Project settings detected!
  ╰─
  ╭─ Step 2: Linter Configuration
  │
  │  The Linter checks your code for stylistic issues and inconsistencies.
  │  It helps keep your codebase clean and readable.
  │
  │  Use `composer.json` to auto-detect framework integrations? · yes
  │
  │  Detecting integrations from composer.json...
  │  Done!
  ╰─
  ╭─ Step 3: Formatter Configuration
  │
  │  The Formatter automatically rewrites your files to a consistent style.
  │  This ends debates about spacing and helps you focus on the code.
  │
  │  Do you want to use a preset formatter configuration? · no
  │  The default settings are PER-CS compatible. Do you want to customize them? · no
  │
  │  Great choice! Sticking to the defaults is highly recommended.
  │
  │  Opt into the smallest possible diff when formatting? (keeps your line breaks intact — let Mago decide if unsure) · no
  ╰─
  ╭─ Step 4: Analyzer Configuration
  │
  │  The Analyzer finds logical bugs and type errors before you run your code.
  │  This is the most powerful part of Mago.
  │
  │  Use `composer.json` to auto-detect analyzer plugins? · yes
  │
  │  Detecting plugins from composer.json...
  │  No plugins detected.
  │
  │  Choose a strictness level for the analyzer:
  │
  │  Strictness preset · Balanced - Sensible defaults for most projects
  │
  │  Would you like to customize individual settings? · no
  ╰─
  ╭─ Step 5: Review & Confirm
  │
  │
  │  Your `mago.toml` file will look like this:
  │
  │  ```toml
  │  #:schema https://mago.carthage.software/1.47.2/schema.json
  │  # Welcome to Mago!
  │  # For full documentation, see https://mago.carthage.software/1.47.2/en/tools/overview/
  │  version = "1"
  │  php-version = "8.5.0"
  │
  │  [source]
  │  workspace = "."
  │  paths = ["Packages/Application/Neos.Welcome/PHPStan", "Packages/Framework/Neos.Flow/Tests"]
  │  includes = ["vendor"]
  │  excludes = []
  │
  │  [source.glob]
  │  literal-separator = true
  │
  │  [formatter]
  │  print-width = 120
  │  tab-width = 4
  │  use-tabs = false
  │
  │  [linter]
  │  integrations = ["phpunit"]
  │
  │  [linter.rules]
  │  ambiguous-function-call = { enabled = false }
  │  literal-named-argument = { enabled = false }
  │  halstead = { effort-threshold = 7000 }
  │
  │  [analyzer]
  │  plugins = []
  │  find-unused-definitions = true
  │  find-unused-expressions = false
  │  analyze-dead-code = false
  │  memoize-properties = true
  │  allow-possibly-undefined-array-keys = true
  │  check-throws = false
  │  unchecked-exceptions = ["Error", "LogicException"]
  │  unchecked-exception-classes = []
  │  check-missing-override = false
  │  find-unused-parameters = false
  │  strict-list-index-checks = false
  │  strict-array-index-existence = false
  │  allow-array-truthy-operand = false
  │  no-boolean-literal-comparison = false
  │  check-missing-type-hints = false
  │  register-super-globals = true
  │  ```
  │
  │  Write configuration to `mago.toml`? · yes
  ╰─

  ✅ Configuration file created successfully!

  ╭─ 🎉 You're all set!
  │
  │  Mago is now configured for your project.
  │
  │  What's next?
  │    - Run `mago lint` to check for issues.
  │    - Run `mago analyze` to find type errors.
  │    - See formatting changes with `mago fmt --dry-run`.
  │
  │  Tip: Use the `--help` flag on any command for more options.
  │
  ╰─ For full documentation, visit: https://mago.carthage.software/

mago analyse

mago analyse は静的解析のコマンドです。
初期のまま実行したらLibraryまで全て実行されてしまいました。

% ./bin/mago analyse

~割愛、個々の解析結果~

error: found 22535 issues: 20246 error(s), 2254 warning(s), 35 help message(s)
 = 8 issues contain auto-fix suggestions

設定ファイルでパスの有効無効を設定します。
Libraryなど解析対象ではないけど依存しているコードはincludesに追加します。

[source]
workspace = "."
paths = ["Packages/Application/Neos.Welcome/classes"]
includes = ["Packages/Framework", "Packages/Libraries"]
excludes = []

解析対象を自分の書いたコードに絞ったことで解析結果が減りました。
それにしても、実行時間が0.83秒なのは速すぎますね!

% time ./bin/mago analyse

~割愛、個々の解析結果~

error: found 147 issues: 106 error(s), 40 warning(s), 1 help message(s)

./bin/mago analyse  0.83s user 0.71s system 340% cpu 0.451 total

--minimum-report-levelを付与することで出力するエラーレベルを選択することができます。

% ./bin/mago analyze --minimum-report-level error

error: found 106 issues: 106 error(s)

検出されたエラー

検出されたエラーを一部見てみます。
analyseでは主に型関連のチェックをしてくれます。
PHPDocのミスマッチなどがメイン。

InjectしているTypeのミスマッチ
(Flowではこの書き方で行けるので、過検知ですね)

error[incompatible-property-type]: Property `Neos\Welcome\Controller\SessionController::$view` has an incompatible type declaration from docblock.
   ┌─ Packages/Application/Neos.Welcome/Classes/Controller/SessionController.php:13:13
   │
13 │      * @var \Neos\Flow\Mvc\View\JsonView
   │             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ This type `Neos\Flow\Mvc\View\JsonView` is incompatible with the parent's type.
   │
   ┌─ Packages/Framework/Neos.Flow/Classes/Mvc/Controller/ActionController.php:89:13
   │
89 │      * @var ViewInterface
   │             ------------- The parent property is defined with type `Neos\Flow\Mvc\View\ViewInterface` here.
   │
   = PHP requires property types to be invariant, meaning the type declaration in a child class must be exactly the same as in the parent class.
   = Help: Change the type of `$view` to `Neos\Flow\Mvc\View\ViewInterface` to match the parent property.

returnしている型が違うというエラー

error[invalid-return-statement]: Invalid return type for function `Neos\Welcome\Domain\Model\Item::getTags`: expected `Doctrine\Common\Collections\Collection<int, Neos\Welcome\Domain\Model\Tag>`, but found `Doctrine\Common\Collections\Collection<Neos\Welcome\Domain\Model\Tag, mixed>`.
   ┌─ Packages/Application/Neos.Welcome/Classes/Domain/Model/Item.php:68:16
   │
68 │         return $this->tags;
   │                ^^^^^^^^^^^ This has type `Doctrine\Common\Collections\Collection<Neos\Welcome\Domain\Model\Tag, mixed>`
   │
   = The type `Doctrine\Common\Collections\Collection<Neos\Welcome\Domain\Model\Tag, mixed>` returned here is not compatible with the declared return type `Doctrine\Common\Collections\Collection<int, Neos\Welcome\Domain\Model\Tag>`.
   = Help: Change the return value to match `Doctrine\Common\Collections\Collection<int, Neos\Welcome\Domain\Model\Tag>`, or update the function's return type declaration.

引数の型エラー

error[mixed-argument]: Invalid argument type for argument #2 of `str_repeat`: expected `non-negative-int`, but found `mixed`.
   ┌─ Packages/Application/Neos.Welcome/Classes/Controller/TestController.php:56:36
   │
56 │         $indent = str_repeat('  ', $depth);
   │                   ----------       ^^^^^^ Argument has type `mixed`
   │                   │
   │                   Arguments to this function are incorrect
   │
   = The type `mixed` is too general and does not match the expected type `non-negative-int`.
   = Help: Add specific type hints or assertions to the argument value.

などなど。

mago lint

mago lint でリンティングができます。
analyseとは違い、コードスタイルだったりがメイン。

% time ./bin/mago lint

error: found 199 issues: 15 error(s), 122 warning(s), 42 note(s), 20 help message(s)
 = 172 issues contain auto-fix suggestions
 
./bin/mago lint  0.07s user 0.04s system 97% cpu 0.112 total

検出されたエラー

検出されたエラーを一部見てみます。

厳密比較に関する警告

warning[identity-comparison]: Use identity comparison `===` instead of equality comparison `==`.
    ┌─ Packages/Application/Neos.Welcome/Classes/Controller/ArrayCollectionController.php:134:24
    │
134 │         return $val %2 == 1;
    │                        ^^ Equality operator is used here
    │
    = Identity comparison `===` checks for both value and type equality, while equality comparison `==` performs type coercion, which can lead to unexpected results.
    = Help: Use `===` to ensure both value and type are equal.

declare(strict_types=1);がないことによる警告

warning[strict-types]: Missing `declare(strict_types=1);` statement at the beginning of the file.
  ┌─ Packages/Application/Neos.Welcome/Classes/Service/SignalService.php:1:1
  │
1 │ <?php
  │ ^^^^^
  │
  = The `strict_types` directive enforces strict type checking, which can prevent subtle bugs.
  = Help: Add `declare(strict_types=1);` at the top of your file.

利用されてないインポートに関する警告
(Flowでは必要なので、これは過検知ですね)

warning[no-redundant-use]: Unused import: `Flow`.
  ┌─ Packages/Application/Neos.Welcome/Classes/Controller/Template2Controller.php:8:5
  │
8 │ use Neos\Flow\Annotations as Flow;
  │ --- ^^^^^^^^^^^^^^^^^^^^^ `Flow` is imported but never used.
  │ │
  │ Unused `use` statement.
  │
  = Help: Remove the entire `use` statement.

などなど。

おわりに

今回はFlowのプロジェクトでmagoを試してみました。
Flowの書き方による過検知も多いですが、この速度で実行されるスピードはやはり魅力ですね。
今後も色々試してみようと思います。

ここまでご覧いただきありがとうございました!

0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?