180 lines
9.7 KiB
YAML
180 lines
9.7 KiB
YAML
uuid:
|
|
- value: 7064860b-42de-47c3-b5ac-3560d941fe0f
|
|
langcode:
|
|
- value: en
|
|
type:
|
|
- target_id: daily_email
|
|
target_type: node_type
|
|
target_uuid: 8bde1f2f-eef9-4f2d-ae9c-96921f8193d7
|
|
revision_timestamp:
|
|
- value: '2025-05-11T09:00:20+00:00'
|
|
revision_uid:
|
|
- target_type: user
|
|
target_uuid: b8966985-d4b2-42a7-a319-2e94ccfbb849
|
|
revision_log: { }
|
|
status:
|
|
- value: true
|
|
uid:
|
|
- target_type: user
|
|
target_uuid: b8966985-d4b2-42a7-a319-2e94ccfbb849
|
|
title:
|
|
- value: 'Which level is right for you?'
|
|
created:
|
|
- value: '2024-02-20T00:00:00+00:00'
|
|
changed:
|
|
- value: '2025-05-11T09:00:20+00:00'
|
|
promote:
|
|
- value: false
|
|
sticky:
|
|
- value: false
|
|
default_langcode:
|
|
- value: true
|
|
revision_translation_affected:
|
|
- value: true
|
|
path:
|
|
- alias: /daily/2024/02/20/which-level-is-right-for-you
|
|
langcode: en
|
|
body:
|
|
- value: |
|
|
<p>Today, whilst working on <a href="/daily/2024/02/19/introducing-versa">Versa</a>, I was experimenting with different PHPStan levels.</p>
|
|
|
|
<p>Level 1 is the least strict level, and applies the fewest rules and returns the fewest results.</p>
|
|
|
|
<p>As you increase the level, the stricter PHPStan is.</p>
|
|
|
|
<h2 id="levelling-up-to-9">Levelling up to 9</h2>
|
|
|
|
<p>Here is the code to get the values of the <code>--extra-args</code> and <code>--working-dir</code> options:</p>
|
|
|
|
<pre><code class="language-php">$extraArgs = $input->getOption('extra-args');
|
|
$workingDir = $input->getOption('working-dir');
|
|
</code></pre>
|
|
|
|
<p>This passed PHPStan level 8, but these are the errors I get when running level 9:</p>
|
|
|
|
<pre><code class="language-plain">------ ------------------------------------------------------------------------------------------------------- Line versa
|
|
------ ------------------------------------------------------------------------------------------------------- 61 Parameter $extraArgs of static method App\Process\Process::create() expects string|null, mixed given.
|
|
62 Parameter $workingDir of static method App\Process\Process::create() expects string, mixed given.
|
|
72 Parameter $extraArgs of static method App\Process\Process::create() expects string|null, mixed given.
|
|
73 Parameter $workingDir of static method App\Process\Process::create() expects string, mixed given.
|
|
84 Parameter $extraArgs of static method App\Process\Process::create() expects string|null, mixed given.
|
|
85 Parameter $workingDir of static method App\Process\Process::create() expects string, mixed given.
|
|
94 Parameter $extraArgs of static method App\Process\Process::create() expects string|null, mixed given.
|
|
95 Parameter $workingDir of static method App\Process\Process::create() expects string, mixed given.
|
|
104 Parameter $extraArgs of static method App\Process\Process::create() expects string|null, mixed given.
|
|
105 Parameter $workingDir of static method App\Process\Process::create() expects string, mixed given.
|
|
119 Parameter $extraArgs of static method App\Process\Process::create() expects string|null, mixed given.
|
|
120 Parameter $workingDir of static method App\Process\Process::create() expects string, mixed given.
|
|
------ ------------------------------------------------------------------------------------------------------- [ERROR] Found 12 errors
|
|
</code></pre>
|
|
|
|
<p>The issue is that <code>$input->getOption()</code> from Symfony's <code>InputInterface</code> returns <code>mixed</code> - even though it always returns <code>null</code> or a string.</p>
|
|
|
|
<p>If I did <code>--working-dir 2</code>, it would return the string <code>"2"</code>.</p>
|
|
|
|
<p>An empty string throws an error, and an empty value (if there are no extra arguments) returns <code>null</code>.</p>
|
|
|
|
<p>So, I know <code>$workingDir</code> will always be a string and <code>$extraArgs</code> will either a string or <code>null</code>.</p>
|
|
|
|
<h2 id="passing-level-8">Passing level 8</h2>
|
|
|
|
<p>To pass level 8, PHPStan needs to be sure the variables are what I think they are.</p>
|
|
|
|
<p>Here's the code I can use to get it to pass:</p>
|
|
|
|
<pre><code class="language-php">$extraArgs = $input->getOption('extra-args');
|
|
$workingDir = $input->getOption('working-dir');
|
|
assert(is_string($extraArgs) || is_null($extraArgs));
|
|
assert(is_string($workingDir));
|
|
</code></pre>
|
|
|
|
<p>By using <code>assert()</code> and throwing an Exception if the condition fails, PHPStan is now happy with the code and my code passes level 9.</p>
|
|
|
|
<h2 id="here%27s-the-thing">Here's the thing</h2>
|
|
|
|
<p>Although the extra code gets PHPStan to pass, it it worth it?</p>
|
|
|
|
<p>Is this extra code adding value? Does it make the code more readable or is it likely to prevent a bug?</p>
|
|
|
|
<p>In this case, I know the value will always be the type I expect.</p>
|
|
|
|
<p>I can work around this using a baseline or annotations for PHPStan to ignore these lines, <strong>or is level 8 good enough for this project</strong>?</p>
|
|
|
|
<p>Similar to 100% test coverage, is aiming for the highest PHPStan level an objective to be met, or is enough value being added added by the lower level?</p>
|
|
|
|
<p>Which level is right for you and this codebase?</p>
|
|
|
|
|
|
format: full_html
|
|
processed: |
|
|
<p>Today, whilst working on <a href="http://default/daily/2024/02/19/introducing-versa">Versa</a>, I was experimenting with different PHPStan levels.</p>
|
|
|
|
<p>Level 1 is the least strict level, and applies the fewest rules and returns the fewest results.</p>
|
|
|
|
<p>As you increase the level, the stricter PHPStan is.</p>
|
|
|
|
<h2 id="levelling-up-to-9">Levelling up to 9</h2>
|
|
|
|
<p>Here is the code to get the values of the <code>--extra-args</code> and <code>--working-dir</code> options:</p>
|
|
|
|
<pre><code class="language-php">$extraArgs = $input->getOption('extra-args');
|
|
$workingDir = $input->getOption('working-dir');
|
|
</code></pre>
|
|
|
|
<p>This passed PHPStan level 8, but these are the errors I get when running level 9:</p>
|
|
|
|
<pre><code class="language-plain">------ ------------------------------------------------------------------------------------------------------- Line versa
|
|
------ ------------------------------------------------------------------------------------------------------- 61 Parameter $extraArgs of static method App\Process\Process::create() expects string|null, mixed given.
|
|
62 Parameter $workingDir of static method App\Process\Process::create() expects string, mixed given.
|
|
72 Parameter $extraArgs of static method App\Process\Process::create() expects string|null, mixed given.
|
|
73 Parameter $workingDir of static method App\Process\Process::create() expects string, mixed given.
|
|
84 Parameter $extraArgs of static method App\Process\Process::create() expects string|null, mixed given.
|
|
85 Parameter $workingDir of static method App\Process\Process::create() expects string, mixed given.
|
|
94 Parameter $extraArgs of static method App\Process\Process::create() expects string|null, mixed given.
|
|
95 Parameter $workingDir of static method App\Process\Process::create() expects string, mixed given.
|
|
104 Parameter $extraArgs of static method App\Process\Process::create() expects string|null, mixed given.
|
|
105 Parameter $workingDir of static method App\Process\Process::create() expects string, mixed given.
|
|
119 Parameter $extraArgs of static method App\Process\Process::create() expects string|null, mixed given.
|
|
120 Parameter $workingDir of static method App\Process\Process::create() expects string, mixed given.
|
|
------ ------------------------------------------------------------------------------------------------------- [ERROR] Found 12 errors
|
|
</code></pre>
|
|
|
|
<p>The issue is that <code>$input->getOption()</code> from Symfony's <code>InputInterface</code> returns <code>mixed</code> - even though it always returns <code>null</code> or a string.</p>
|
|
|
|
<p>If I did <code>--working-dir 2</code>, it would return the string <code>"2"</code>.</p>
|
|
|
|
<p>An empty string throws an error, and an empty value (if there are no extra arguments) returns <code>null</code>.</p>
|
|
|
|
<p>So, I know <code>$workingDir</code> will always be a string and <code>$extraArgs</code> will either a string or <code>null</code>.</p>
|
|
|
|
<h2 id="passing-level-8">Passing level 8</h2>
|
|
|
|
<p>To pass level 8, PHPStan needs to be sure the variables are what I think they are.</p>
|
|
|
|
<p>Here's the code I can use to get it to pass:</p>
|
|
|
|
<pre><code class="language-php">$extraArgs = $input->getOption('extra-args');
|
|
$workingDir = $input->getOption('working-dir');
|
|
assert(is_string($extraArgs) || is_null($extraArgs));
|
|
assert(is_string($workingDir));
|
|
</code></pre>
|
|
|
|
<p>By using <code>assert()</code> and throwing an Exception if the condition fails, PHPStan is now happy with the code and my code passes level 9.</p>
|
|
|
|
<h2 id="here%27s-the-thing">Here's the thing</h2>
|
|
|
|
<p>Although the extra code gets PHPStan to pass, it it worth it?</p>
|
|
|
|
<p>Is this extra code adding value? Does it make the code more readable or is it likely to prevent a bug?</p>
|
|
|
|
<p>In this case, I know the value will always be the type I expect.</p>
|
|
|
|
<p>I can work around this using a baseline or annotations for PHPStan to ignore these lines, <strong>or is level 8 good enough for this project</strong>?</p>
|
|
|
|
<p>Similar to 100% test coverage, is aiming for the highest PHPStan level an objective to be met, or is enough value being added added by the lower level?</p>
|
|
|
|
<p>Which level is right for you and this codebase?</p>
|
|
|
|
|
|
summary: null
|
|
field_daily_email_cta: { }
|