Modern PHPDoc Annotations
Tags: phpstorm, phpdoc, generics, php
Published: 2020-02-04 23:21:39

---
title: Modern PHPDoc Annotations
published: true
description: PHPDoc in PhpStorm with auto-completion for array key directly from the database with generics, immutable and type safety support.
tags: phpstorm, phpdoc, generics, php
---

first published here: https://suckup.de/2020/02/modern-phpdoc-annotations/


<p>We will start very simple with PhpStorm and default PHPDoc, then we will increase the complexity step by step until we have auto-completion for array keys directly from the database with generics, immutable and type safety support.</p>



<h2>1.0 PhpStorm &amp; auto-generate PHPDoc blocks</h2>
<blockquote>
<p style="text-align: left;">„For documentation comments, PhpStorm provides completion that is enabled by default. PhpStorm creates stubs of „<a href="http://manual.phpdoc.org/HTMLSmartyConverter/HandS/phpDocumentor/tutorial_phpDocumentor.pkg.html" target="_blank" rel="noopener noreferrer">PHPDoc blocks</a>“ when you type the <em>/**</em> opening tag and press <span style="color: #222222;"><span style="color: #27282c;"><span style="font-family: Arial, Helvetica, sans-serif;"><kbd class="western"><span style="font-family: Arial, sans-serif;"><span style="font-size: medium;">Enter</span></span></kbd></span></span></span>, or press <span style="color: #222222;"><span style="color: #27282c;"><span style="font-family: Arial, Helvetica, sans-serif;"><kbd class="western"><span style="font-family: Arial, sans-serif;"><span style="font-size: medium;">Alt+Insert </span></span></kbd></span></span></span>and appoint the code construct (a class, a method, a function, and so on) to document. Depending on your choice, PhpStorm will create the required tags or add an empty documentation stub.“ <span style="color: #222222;"><span style="color: #27282c;"><span style="font-family: Arial, Helvetica, sans-serif;"><span style="font-family: Arial, sans-serif;"><span style="font-size: medium;">–</span></span></span></span></span></p>
</blockquote>
<p style="text-align: right;"><a style="font-family: Arial, Helvetica, sans-serif; text-align: right;" href="https://www.jetbrains.com/help/phpstorm/phpdoc-comments.html" target="_blank" rel="noopener noreferrer"><span style="font-family: Arial, sans-serif;"><span style="font-size: medium;">https://www.jetbrains.com/help/phpstorm/phpdoc-comments.html</span></span></a></p>
<p><span style="color: #222222;"><span style="font-family: Arial, sans-serif;"><span style="font-size: medium;"><b>Code:</b></span></span></span></p>
<pre class="western"><span style="color: #6a737d;"><span style="font-family: Arial, sans-serif;"><span style="font-size: medium;"><i>/**</i></span></span></span>
<span style="color: #24292e;"> <span style="font-family: Arial, sans-serif;"><span style="color: #6a737d;"><span style="font-size: medium;"><i>* @param array </i></span></span><span style="color: #744400;"><span style="font-size: medium;"><i>$row</i></span></span></span></span>
<span style="color: #6a737d;"> <span style="font-family: Arial, sans-serif;"><span style="font-size: medium;"><i>*</i></span></span></span>
<span style="color: #6a737d;"> <span style="font-family: Arial, sans-serif;"><span style="font-size: medium;"><i>* @return array</i></span></span></span>
<span style="color: #6a737d;"> <span style="font-family: Arial, sans-serif;"><span style="font-size: medium;"><i>*/</i></span></span></span>
<span style="color: #24292e;"><span style="font-family: Arial, sans-serif;"><span style="font-size: medium;">abstract function <span style="color: #4d6dc1;">formatRow</span><span style="color: #4554c1;">(</span>array <span style="color: #744400;">$row</span><span style="color: #4554c1;">)</span><span style="color: #4d6dc1;">: </span>array;</span></span></span></pre>



<h2 class="western">1.1 Return $this|static|self</h2>
<p>It‘s quite annoying that php itself currently only have „self“ as return type (<a href="http://suckup.de/2016/01/php-arrays-zusammenzufuehren/" target="_blank" rel="noopener noreferrer">https://wiki.php.net/rfc/static_return_type</a>) for the current class. Because of „<a href="https://www.php.net/manual/en/language.oop5.late-static-bindings.php" target="_blank" rel="noopener noreferrer">late static binding</a>“ you can use „static“ in your code to refer to the class a method was actually called on, even if the method is inherited. But in PHPDoc you can already use:</p>
<ul>
<li>@return <strong>$this</strong>: if you really return $this (e.g. for <em>fluent interface</em>)</li>
<li>@return <strong>static</strong>: refer to the class a method was actually called on</li>
<li>@return <strong>self</strong>: refer to the class a method was written in</li>
</ul>
<p><strong>Code:</strong></p>
<pre class="western"><span style="color: #6a737d;"><span style="font-family: Arial, sans-serif;"><span style="font-size: medium;"><i>/**</i></span></span></span>
<span style="color: #6a737d;"> <span style="font-family: Arial, sans-serif;"><span style="font-size: medium;"><i>* @return </i></span><span style="color: #808080;"><span style="font-size: medium;"><i>static</i></span></span></span></span>
<span style="color: #6a737d;"> <span style="font-family: Arial, sans-serif;"><span style="font-size: medium;"><i>*/</i></span></span></span>
<span style="color: #24292e;"><span style="font-family: Arial, sans-serif;"><span style="font-size: medium;">abstract function <span style="color: #4d6dc1;">getFoo</span><span style="color: #4554c1;">()</span><span style="color: #4d6dc1;">: </span><span style="color: #4d6dc1;">self</span>;</span></span></span></pre>



<div class="wp-block-image"><figure class="aligncenter size-large"><img data-attachment-id="6638" data-permalink="https://suckup.de/2020/02/modern-phpdoc-annotations/type_inference/" data-orig-file="https://suckup.de/wp-content/uploads//2020/02/type_inference.png" data-orig-size="1200,664" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="type_inference" data-image-description="" data-medium-file="https://suckup.de/wp-content/uploads//2020/02/type_inference-300x166.png" data-large-file="https://suckup.de/wp-content/uploads//2020/02/type_inference-1024x567.png" src="https://suckup.de/wp-content/uploads//2020/02/type_inference-1024x567.png" alt="" class="wp-image-6638" srcset="https://suckup.de/wp-content/uploads/2020/02/type_inference-1024x567.png 1024w, https://suckup.de/wp-content/uploads/2020/02/type_inference-300x166.png 300w, https://suckup.de/wp-content/uploads/2020/02/type_inference-768x425.png 768w, https://suckup.de/wp-content/uploads/2020/02/type_inference.png 1200w" sizes="(max-width: 1024px) 100vw, 1024px"><figcaption><a href="https://blog.jetbrains.com/phpstorm/2019/09/phpstorm-2019-2-2-is-released/">https://blog.jetbrains.com/phpstorm/2019/09/phpstorm-2019-2-2-is-released/</a></figcaption></figure></div>



<h2>1.2 New (and not that new) Array Syntax</h2>
<p>PhpStorm and (PHPStan &amp; Psalm) are supporting some new (and some not that new) array syntax for PHPDoc types, but for now PhpStorm will not auto-generate this types.</p>
<p>Examples:</p>
<ul>
<li><span style="font-family: Arial, sans-serif;"><b>int[]</b>: an array with only INT values – [1, 4, 6, 8, 9, …]</span></li>
<li><span style="font-family: Arial, sans-serif;"><b>array&lt;int, int&gt;</b>: an array with only INT values – [4 =&gt; 1, 8 =&gt; 4, 12 =&gt; 6, …]</span></li>
<li><span style="font-family: Arial, sans-serif;"><b>string[]</b>: an array with only STRING values – [„foo“, „bar“, …]</span></li>
<li><span style="font-family: Arial, sans-serif;"><b>array&lt;int, string&gt;</b>: an array with only STRING values – [4 =&gt; „foo“, 8 =&gt; „bar“, …]</span></li>
<li><span style="font-family: Arial, sans-serif;"><b>Order</b><b>[]</b>: an array with only „Order“-Object values – [Order, Order, …]</span></li>
<li><span style="font-family: Arial, sans-serif;"><b>array&lt;int|string, </b><b>Order</b><b>&gt;</b>: an array with INT or STRING as key and „Order“-Object values – [4 =&gt; Order, ‘foo‘ =&gt; Order, …]</span></li>
<li><span style="font-family: Arial, sans-serif;"><b>array&lt;int|string, mixed&gt;</b>: an array with INT or STRING as key and mixed as values – [1 =&gt; 1, 4 =&gt; „foo“, 6 =&gt; \stdClass, …]</span></li>
<li><span style="font-family: Arial, sans-serif;"><b>array&lt;int, array&lt;int, string&gt;&gt;</b>: an array with INT as key and and an array (with INT as key and string as value) as values – [1 =&gt; [1 =&gt; „foo“], 4 =&gt; [1 =&gt; 4], …]</span></li>
<li><span style="font-family: Arial, sans-serif;"><b>array&lt;int, </b><b>string[]</b><b>&gt;</b>: an array with INT as key and and an array (with INT as key and string as value) as values – [1 =&gt; [„foo“, „lall“], 4 =&gt; [„öäü“, „bar“], …]</span></li>
<li><span style="font-family: Arial, sans-serif;"><b>array{output: string, debug: string}</b>: an array with the key „output“ and „debug“, the values are STRING values – [‚output‘ =&gt; ‚foo‘, ‚debug‘ =&gt; ‚bar‘]</span></li>
<li><span style="font-family: Arial, sans-serif;"><b>array&lt;int, array{output: string, debug: string}&gt;</b>: an array with the key „output“ and „debug“, the values are STRING values – [1 =&gt; [‚output‘ =&gt; ‚foo‘, ‚debug‘ =&gt; ‚bar‘], 3 =&gt; [‚output‘ =&gt; ‚foo‘, ‚debug‘ =&gt; ‚bar‘], …]</span></li>
</ul>
<p>Examples (only @psalm-*): supported by PHPStan &amp; Psalm</p>
<ul>
<li><span style="font-family: Arial, sans-serif;"><b>list&lt;array{output: string, debug: string}&gt;</b>: an array with the key „output“ and „debug“, the values are STRING values – [0 =&gt; [‚output‘ =&gt; ‚foo‘, ‚debug‘ =&gt; ‚bar‘], 1 =&gt; [‚output‘ =&gt; ‚foo‘, ‚debug‘ =&gt; ‚bar‘], …]</span></li>
</ul>
<p><strong>Live-Examples:</strong></p>
<p><span style="font-family: Arial, sans-serif;">– </span>Psalm<span style="font-family: Arial, sans-serif;">: <a href="https://psalm.dev/r/922d4ba5b1">https://psalm.dev/r/922d4ba5b1</a></span></p>
<p><span style="font-family: Arial, sans-serif;">– </span>PHPStan<span style="font-family: Arial, sans-serif;">: </span><a href="https://phpstan.org/r/ce657ef4-9f18-46a1-b21a-e51e3a0e6d2d"><span style="font-family: Arial, sans-serif;">https://phpstan.org/r/ce657ef4-9f18-46a1-b21a-e51e3a0e6d2d</span></a></p>
<p><strong>Code:</strong></p>
<pre class="western"><span style="color: #6a737d;"><span style="font-family: Arial, sans-serif;"><span style="font-size: medium;"><i>/**</i></span></span></span>
<span style="color: #24292e;"> <span style="font-family: Arial, sans-serif;"><span style="color: #6a737d;"><span style="font-size: medium;"><i>* @param array&lt;int|string, mixed&gt; </i></span></span><span style="color: #744400;"><span style="font-size: medium;"><i>$row</i></span></span></span></span>
<span style="color: #6a737d;"> <span style="font-family: Arial, sans-serif;"><span style="font-size: medium;"><i>*</i></span></span></span>
<span style="color: #6a737d;"> <span style="font-family: Arial, sans-serif;"><span style="font-size: medium;"><i>* @return array&lt;int|string, mixed&gt;</i></span></span></span>
<span style="color: #6a737d;"> <span style="font-family: Arial, sans-serif;"><span style="font-size: medium;"><i>*/</i></span></span></span>
<span style="color: #24292e;"><span style="font-family: Arial, sans-serif;"><span style="font-size: medium;">abstract function <span style="color: #4d6dc1;">formatRow</span><span style="color: #4554c1;">(</span>array <span style="color: #744400;">$row</span><span style="color: #4554c1;">)</span><span style="color: #4d6dc1;">: </span>array;</span></span></span></pre>
<p><strong>PhpStorm support?:</strong> Sadly PhpStorm did not have good support for these types, so that you often have to add „@psalm-*“ PHPDoc comments. For example PhpStorm will accept „array&lt;int, Order&gt;“ but PhpStorm will not understand the PHPDoc, so that you need to add e.g. „@param Order[] $order“ and „@psalm-param array&lt;int, Order&gt; $order“.</p>



<h2>1.3 Dynamic Autocompletion&nbsp;(+ data from your database) via deep-assoc-completion</h2>
<p>If you have a method e.g. „formatRow($row)“ you can use „getFieldArray()[0]“ (data from the database – you have to connection the IDE with your database and your queries need to be analyzable by PhpStorm (take a look at the next screenshot) and combine static data from „getHeaderFieldArray()“, so that you have auto-completion from different sources.</p>
<p><strong>Code:</strong></p>
<pre class="western"><span style="color: #6a737d;"><span style="font-family: Arial, sans-serif;"><span style="font-size: medium;"><i>/**</i></span></span></span>
<span style="color: #24292e;"> <span style="font-family: Arial, sans-serif;"><span style="color: #6a737d;"><span style="font-size: medium;"><i>* @param array&lt;int|string, mixed&gt; </i></span></span><span style="color: #744400;"><span style="font-size: medium;"><i>$row </i></span></span><span style="color: #6a737d;"><span style="font-size: medium;"><i>= $this-&gt;getFieldArray()[0] + $this-&gt;getHeaderFieldArray()</i></span></span></span></span>
<span style="color: #6a737d;"> <span style="font-family: Arial, sans-serif;"><span style="font-size: medium;"><i>*</i></span></span></span>
<span style="color: #6a737d;"> <span style="font-family: Arial, sans-serif;"><span style="font-size: medium;"><i>* @return array&lt;int|string, mixed&gt;</i></span></span></span>
<span style="color: #6a737d;"> <span style="font-family: Arial, sans-serif;"><span style="font-size: medium;"><i>*/</i></span></span></span>
<span style="color: #24292e;"><span style="font-family: Arial, sans-serif;"><span style="font-size: medium;">abstract function <span style="color: #4d6dc1;">formatRow</span><span style="color: #4554c1;">(</span>array <span style="color: #744400;">$row</span><span style="color: #4554c1;">)</span><span style="color: #4d6dc1;">: </span>array;</span></span></span></pre>
<p>more information + examples: <a href="https://github.com/klesun/deep-assoc-completion">https://github.com/klesun/deep-assoc-completion</a></p>



<h2>1.4 Immutability Check via Static Code Analyses (via psalm)</h2>
<p>And there is even more. :) You can add PHPDoc annotation that will check if you really use immutable classes or at least methods. Please read more here: <a href="https://psalm.dev/articles/immutability-and-beyond">https://psalm.dev/articles/immutability-and-beyond</a></p>
<p><strong>Code:</strong></p>
<pre class="western"><span style="color: #6a737d;"><span style="font-family: Arial, sans-serif;"><span style="font-size: medium;"><i>/**</i></span></span></span>
<span style="color: #24292e;"> <span style="font-family: Arial, sans-serif;"><span style="color: #6a737d;"><span style="font-size: medium;"><i>* @param array&lt;int|string, mixed&gt; </i></span></span><span style="color: #744400;"><span style="font-size: medium;"><i>$row </i></span></span><span style="color: #6a737d;"><span style="font-size: medium;"><i>= $this-&gt;getFieldArray()[0] + $this-&gt;getHeaderFieldArray()</i></span></span></span></span>
<span style="color: #6a737d;"> <span style="font-family: Arial, sans-serif;"><span style="font-size: medium;"><i>*</i></span></span></span>
<span style="color: #6a737d;"> <span style="font-family: Arial, sans-serif;"><span style="font-size: medium;"><i>* @return array&lt;int|string, mixed&gt;</i></span></span></span>
<span style="color: #6a737d;"> <span style="font-family: Arial, sans-serif;"><span style="font-size: medium;"><i>*</i></span></span></span>
<span style="color: #6a737d;"> <span style="font-family: Arial, sans-serif;"><span style="font-size: medium;"><i>* </i></span><span style="color: #666666;"><span style="font-size: medium;">@psalm-mutation-free</span></span></span></span>
<span style="color: #6a737d;"> <span style="font-family: Arial, sans-serif;"><span style="font-size: medium;"><i>*/</i></span></span></span>
<span style="font-family: Arial, sans-serif;"><span style="color: #24292e;"><span style="font-size: medium;">abstract</span></span><span style="color: #24292e;"><span style="font-size: medium;"> function </span></span><span style="color: #4d6dc1;"><span style="font-size: medium;">formatRow</span></span><span style="color: #4554c1;"><span style="font-size: medium;">(</span></span><span style="color: #24292e;"><span style="font-size: medium;">array </span></span><span style="color: #744400;"><span style="font-size: medium;">$row</span></span><span style="color: #4554c1;"><span style="font-size: medium;">)</span></span><span style="color: #4d6dc1;"><span style="font-size: medium;">: </span></span><span style="color: #24292e;"><span style="font-size: medium;">array;</span></span></span></pre>
<p><strong>Live-Example:</strong></p>
<p>– Psalm: <a href="https://psalm.dev/r/5bac0a9a07" target="_blank" rel="noopener noreferrer">https://psalm.dev/r/5bac0a9a07</a></p>



<h2>1.5 Generics in PHP via Static Code Analyses</h2>
<p>We can also use Generics via code annotations. PHPStan &amp; Psalm both support it, but Psalm’s support is more feature complete and both tools can use the „@psalm-“-syntax. Here comes some simple examples.</p>
<p><strong>array_last</strong>: Will return the last array element from the $array (type: <span style="color: #808080;"><em>TLast</em></span>) or the $fallback (type: <span style="color: #808080;"><em>TLastFallback</em></span>). We tell the function that the types comes from the input parameters and that the input is an array of <em><span style="color: #808080;">TLast</span></em> or <span style="color: #808080;"><em>TLastFallback</em></span> from the fallback.</p>
<pre class="western"><span style="color: #808080;"><span style="font-family: Arial, sans-serif;"><span style="font-size: medium;"><i>/**</i></span></span></span>
<span style="color: #000000;"> <span style="font-family: Arial, sans-serif;"><span style="color: #808080;"><i>* </i></span><span style="color: #808080;"><i><b>@param </b></i></span><span style="color: #808080;"><i>array</i></span><span style="color: #808080;"><i>&lt;mixed&gt;</i></span> <span style="color: #660000;"><i>$array</i></span></span></span>
<span style="color: #000000;"> <span style="font-family: Arial, sans-serif;"><span style="color: #808080;"><i>* </i></span><span style="color: #808080;"><i><b>@param </b></i></span><span style="color: #808080;"><i>mixed             </i></span><span style="color: #660000;"><i>$fallback </i></span><span style="color: #808080;"><i>&lt;p&gt;</i></span><span style="color: #808080;"><i>This fallback will be used, if the array is empty.</i></span><span style="color: #808080;"><i>&lt;/p&gt;</i></span></span></span>
<span style="color: #808080;"> <span style="font-family: Arial, sans-serif;"><i>*</i></span></span>
<span style="color: #000000;"> <span style="font-family: Arial, sans-serif;"><span style="color: #808080;"><i>* </i></span><span style="color: #808080;"><i><b>@return </b></i></span><span style="color: #808080;"><i>mixed|null</i></span></span></span>
<span style="color: #808080;"> <span style="font-family: Arial, sans-serif;"><i>*</i></span></span>
<span style="color: #000000;"> <span style="font-family: Arial, sans-serif;"><span style="color: #808080;"><i>* </i></span><span style="color: #808080;"><i><b>@template </b></i></span><span style="color: #808080;"><i>TLast</i></span></span></span>
<span style="color: #000000;"> <span style="font-family: Arial, sans-serif;"><span style="color: #808080;"><i>* </i></span><span style="color: #808080;"><i><b>@template </b></i></span><span style="color: #808080;"><i>TLastFallback</i></span></span></span>
<span style="color: #000000;"> <span style="font-family: Arial, sans-serif;"><span style="color: #808080;"><i>* </i></span><span style="color: #808080;"><i><b>@psalm-param </b></i></span><span style="color: #808080;"><i>TLast[] $array</i></span></span></span>
<span style="color: #000000;"> <span style="font-family: Arial, sans-serif;"><span style="color: #808080;"><i>* </i></span><span style="color: #808080;"><i><b>@psalm-param </b></i></span><span style="color: #808080;"><i>TLastFallback $fallback</i></span></span></span>
<span style="color: #000000;"> <span style="font-family: Arial, sans-serif;"><span style="color: #808080;"><i>* </i></span><span style="color: #808080;"><i><b>@psalm-return </b></i></span><span style="color: #808080;"><i>TLast|TLastFallback</i></span></span></span>
<span style="color: #808080;"> <span style="font-family: Arial, sans-serif;"><i>*/</i></span></span>
<span style="color: #000000;"><span style="font-family: Arial, sans-serif;"><span style="color: #000080;"><b>function </b></span>array_last<span style="color: #660e7a;"><i><b>(</b></i></span><span style="color: #000080;"><b>array </b></span><span style="color: #660000;">$array</span>, <span style="color: #660000;">$fallback </span>= <span style="color: #000080;"><b>null</b></span><span style="color: #660e7a;"><i><b>)</b></i></span></span></span>
<span style="color: #660e7a;"><span style="font-family: Arial, sans-serif;"><i><b>{</b></i></span></span>
<span style="color: #000000;">    <span style="font-family: Arial, sans-serif;"><span style="color: #660000;">$key_last </span>= \array_key_last<span style="color: #660e7a;"><i><b>(</b></i></span><span style="color: #660000;">$array</span><span style="color: #660e7a;"><i><b>)</b></i></span>;</span></span>
<span style="color: #000000;">    <span style="font-family: Arial, sans-serif;"><span style="color: #000080;"><b>if </b></span><span style="color: #660e7a;"><i><b>(</b></i></span><span style="color: #660000;">$key_last </span>=== <span style="color: #000080;"><b>null</b></span><span style="color: #660e7a;"><i><b>) {</b></i></span></span></span>
<span style="color: #000000;">        <span style="font-family: Arial, sans-serif;"><span style="color: #000080;"><b>return </b></span><span style="color: #660000;">$fallback</span>;</span></span>
<span style="color: #000000;">    <span style="font-family: Arial, sans-serif;"><span style="color: #660e7a;"><i><b>}<br></b></i></span></span></span>
<span style="color: #000000;">    <span style="font-family: Arial, sans-serif;"><span style="color: #000080;"><b>return </b></span><span style="color: #660000;">$array</span><span style="color: #660e7a;"><i><b>[</b></i></span><span style="color: #660000;">$key_last</span><span style="color: #660e7a;"><i><b>]</b></i></span>;</span></span>
<span style="color: #660e7a;"><span style="font-family: Arial, sans-serif;"><i><b>}</b></i></span></span>
</pre>
<p><strong>array_first</strong>: Will return the first array element from the $array (type: <span style="color: #808080;"><em>TFirst</em></span>) or the $fallback (type: <span style="color: #808080;"><em>TFirstFallback</em></span>). We tell the function that the types comes from the input params and that the input is an array of <span style="color: #808080;"><em>TFirst</em></span> or <span style="color: #808080;"><em>TFirstFallback</em></span> from the fallback.</p>
<pre class="western"><span style="color: #808080;"><span style="font-family: Arial, sans-serif;"><i>/**</i></span></span>
<span style="color: #000000;"> <span style="font-family: Arial, sans-serif;"><span style="color: #808080;"><i>* </i></span><span style="color: #808080;"><i><b>@param </b></i></span><span style="color: #808080;"><i>array</i></span><span style="color: #808080;"><i>&lt;mixed&gt;</i></span> <span style="color: #660000;"><i>$array</i></span></span></span>
<span style="color: #000000;"> <span style="font-family: Arial, sans-serif;"><span style="color: #808080;"><i>* </i></span><span style="color: #808080;"><i><b>@param </b></i></span><span style="color: #808080;"><i>mixed             </i></span><span style="color: #660000;"><i>$fallback </i></span><span style="color: #808080;"><i>&lt;p&gt;</i></span><span style="color: #808080;"><i>This fallback will be used, if the array is empty.</i></span><span style="color: #808080;"><i>&lt;/p&gt;</i></span></span></span>
<span style="color: #808080;"> <span style="font-family: Arial, sans-serif;"><i>*</i></span></span>
<span style="color: #000000;"> <span style="font-family: Arial, sans-serif;"><span style="color: #808080;"><i>* </i></span><span style="color: #808080;"><i><b>@return </b></i></span><span style="color: #808080;"><i>mixed|null</i></span></span></span>
<span style="color: #808080;"> <span style="font-family: Arial, sans-serif;"><i>*</i></span></span>
<span style="color: #000000;"> <span style="font-family: Arial, sans-serif;"><span style="color: #808080;"><i>* </i></span><span style="color: #808080;"><i><b>@template </b></i></span><span style="color: #808080;"><i>TFirst</i></span></span></span>
<span style="color: #000000;"> <span style="font-family: Arial, sans-serif;"><span style="color: #808080;"><i>* </i></span><span style="color: #808080;"><i><b>@template </b></i></span><span style="color: #808080;"><i>TFirstFallback</i></span></span></span>
<span style="color: #000000;"> <span style="font-family: Arial, sans-serif;"><span style="color: #808080;"><i>* </i></span><span style="color: #808080;"><i><b>@psalm-param </b></i></span><span style="color: #808080;"><i>TFirst[] $array</i></span></span></span>
<span style="color: #000000;"> <span style="font-family: Arial, sans-serif;"><span style="color: #808080;"><i>* </i></span><span style="color: #808080;"><i><b>@psalm-param </b></i></span><span style="color: #808080;"><i>TFirstFallback $fallback</i></span></span></span>
<span style="color: #000000;"> <span style="font-family: Arial, sans-serif;"><span style="color: #808080;"><i>* </i></span><span style="color: #808080;"><i><b>@psalm-return </b></i></span><span style="color: #808080;"><i>TFirst|TFirstFallback</i></span></span></span>
<span style="color: #808080;"> <span style="font-family: Arial, sans-serif;"><i>*/</i></span></span>
<span style="color: #000000;"><span style="font-family: Arial, sans-serif;"><span style="color: #000080;"><b>function </b></span>array_first<span style="color: #660e7a;"><i><b>(</b></i></span><span style="color: #000080;"><b>array </b></span><span style="color: #660000;">$array</span>, <span style="color: #660000;">$fallback </span>= <span style="color: #000080;"><b>null</b></span><span style="color: #660e7a;"><i><b>)</b></i></span></span></span>
<span style="color: #660e7a;"><span style="font-family: Arial, sans-serif;"><i><b>{</b></i></span></span>
<span style="color: #000000;">    <span style="font-family: Arial, sans-serif;"><span style="color: #660000;">$key_first </span>= array_key_first<span style="color: #660e7a;"><i><b>(</b></i></span><span style="color: #660000;">$array</span><span style="color: #660e7a;"><i><b>)</b></i></span>;</span></span>
<span style="color: #000000;">    <span style="font-family: Arial, sans-serif;"><span style="color: #000080;"><b>if </b></span><span style="color: #660e7a;"><i><b>(</b></i></span><span style="color: #660000;">$key_first </span>=== <span style="color: #000080;"><b>null</b></span><span style="color: #660e7a;"><i><b>) {</b></i></span></span></span>
<span style="color: #000000;">        <span style="font-family: Arial, sans-serif;"><span style="color: #000080;"><b>return </b></span><span style="color: #660000;">$fallback</span>;</span></span>
<span style="color: #000000;">    <span style="font-family: Arial, sans-serif;"><span style="color: #660e7a;"><i><b>}<br></b></i></span></span></span>
<span style="color: #000000;">    <span style="font-family: Arial, sans-serif;"><span style="color: #000080;"><b>return </b></span><span style="color: #660000;">$array</span><span style="color: #660e7a;"><i><b>[</b></i></span><span style="color: #660000;">$key_first</span><span style="color: #660e7a;"><i><b>]</b></i></span>;</span></span>
<span style="color: #660e7a;"><span style="font-family: Arial, sans-serif;"><i><b>}</b></i></span></span></pre>
<p>So we can define „Templates“ and map input arguments on that types, this can be even more complex if you use it in a class context and you map the „Templates“ on class properties. But the logic will be the same.</p>
<p>Here is a more complex example: <a href="https://github.com/voku/Arrayy/blob/master/src/Collection/CollectionInterface.php">https://github.com/voku/Arrayy/blob/master/src/Collection/CollectionInterface.php</a></p>
<p><strong>PhpStorm support?</strong>: Noop, sadly we need to hack this via „PHPSTORM_META“, so here is an example:</p>
<ul>
<li>override(\array_filter(0), type(0)); // suppose first parameter type is MyClass[] then return type of array_filter will be MyClass[]</li>
<li>override(\array_reduce(0), elementType(0)); // suppose first parameter type is MyClass[] then return type of array_reduce will be MyClass</li>
</ul>
<p><strong>Read more here: </strong></p>
<ul>
<li><a href="https://blog.jetbrains.com/phpstorm/2019/02/new-phpstorm-meta-php-features/">https://blog.jetbrains.com/phpstorm/2019/02/new-phpstorm-meta-php-features/</a></li>
<li><a href="https://gist.github.com/voku/477e5c22a67c2d37ca42150d94e371ea">https://gist.github.com/voku/477e5c22a67c2d37ca42150d94e371ea</a></li>
</ul>



<h2>2.0 Resume </h2>
<p>It‘s not perfect, and type check and auto-completion only with PHPDoc is not really what I expected for the year 2020. But it‘s working and I hope PhpStorm will bring more support for the new types annotations in the future.</p>
<p><strong>More Links:</strong></p>
<ul>
<li><a href="https://docs.phpdoc.org/latest/guides/types.html">https://docs.phpdoc.org/latest/guides/types.html</a></li>
<li><a href="https://scrutinizer-ci.com/docs/tools/php/php-analyzer/guides/annotating_code">https://scrutinizer-ci.com/docs/tools/php/php-analyzer/guides/annotating_code</a></li>
<li><a href="https://github.com/klesun/deep-assoc-completion/blob/master/docs/deep-keys-overview.md">https://github.com/klesun/deep-assoc-completion/blob/master/docs/deep-keys-overview.md</a></li>
<li><a href="https://github.com/php-fig/fig-standards/blob/master/proposed/phpdoc.md#appendix-a-types">https://github.com/php-fig/fig-standards/blob/master/proposed/phpdoc.md#appendix-a-types</a></li>
<li><a href="https://psalm.dev/docs/annotating_code/supported_annotations/">https://psalm.dev/docs/annotating_code/supported_annotations/</a></li>
</ul>
<p>&nbsp;</p>