<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Brent Roose</title>
    <description>The latest articles on DEV Community by Brent Roose (@brendt).</description>
    <link>https://dev.to/brendt</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F135875%2F046a83b8-a3b7-4a60-845d-f38b0323c570.png</url>
      <title>DEV Community: Brent Roose</title>
      <link>https://dev.to/brendt</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/brendt"/>
    <language>en</language>
    <item>
      <title>PHP 8.1 in 8 code blocks</title>
      <dc:creator>Brent Roose</dc:creator>
      <pubDate>Sun, 07 Nov 2021 00:00:00 +0000</pubDate>
      <link>https://dev.to/brendt/php-81-in-8-code-blocks-5dl6</link>
      <guid>https://dev.to/brendt/php-81-in-8-code-blocks-5dl6</guid>
      <description>&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="n"&gt;enum&lt;/span&gt; &lt;span class="nc"&gt;Status&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;draft&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;published&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;archived&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;color&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nc"&gt;Status&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;draft&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'grey'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;   
            &lt;span class="nc"&gt;Status&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;published&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'green'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;   
            &lt;span class="nc"&gt;Status&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;archived&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'red'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;   
        &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;&lt;a href="https://stitcher.io/blog/php-enums"&gt;Enums&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;






&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PostData&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;__construct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="kt"&gt;public&lt;/span&gt; &lt;span class="n"&gt;readonly&lt;/span&gt; &lt;span class="n"&gt;string&lt;/span&gt; &lt;span class="nv"&gt;$title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="kt"&gt;public&lt;/span&gt; &lt;span class="n"&gt;readonly&lt;/span&gt; &lt;span class="n"&gt;string&lt;/span&gt; &lt;span class="nv"&gt;$author&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="kt"&gt;public&lt;/span&gt; &lt;span class="n"&gt;readonly&lt;/span&gt; &lt;span class="n"&gt;string&lt;/span&gt; &lt;span class="nv"&gt;$body&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="kt"&gt;public&lt;/span&gt; &lt;span class="n"&gt;readonly&lt;/span&gt; &lt;span class="nc"&gt;DateTimeImmutable&lt;/span&gt; &lt;span class="nv"&gt;$createdAt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="kt"&gt;public&lt;/span&gt; &lt;span class="n"&gt;readonly&lt;/span&gt; &lt;span class="nc"&gt;PostState&lt;/span&gt; &lt;span class="nv"&gt;$state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;&lt;a href="https://stitcher.io/blog/php-81-readonly-properties"&gt;Readonly properties&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;






&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PostStateMachine&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;__construct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="kt"&gt;private&lt;/span&gt; &lt;span class="n"&gt;string&lt;/span&gt; &lt;span class="nv"&gt;$state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Draft&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;&lt;a href="https://stitcher.io/blog/php-81-new-in-initializers"&gt;New in initializers&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;






&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$fiber&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Fiber&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;$valueAfterResuming&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Fiber&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;suspend&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'after suspending'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// … &lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nv"&gt;$valueAfterSuspending&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$fiber&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;start&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nv"&gt;$fiber&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;resume&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'after resuming'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;&lt;a href="https://stitcher.io/blog/fibers-with-a-grain-of-salt"&gt;Fibers, a.k.a. "green threads"&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Do you want to learn more about PHP 8.1? There's &lt;a href="https://road-to-php.com/"&gt;The Road to PHP 8.1&lt;/a&gt;. For the next 10 days, you'll receive a daily email covering a new and exiting feature of PHP 8.1; afterwards you'll be automatically unsubscribed, so no spam or followup. &lt;a href="https://road-to-php.com/"&gt;Subscribe now!&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$array1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"a"&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="nv"&gt;$array2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"b"&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="nv"&gt;$array&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"a"&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;...&lt;/span&gt;&lt;span class="nv"&gt;$array1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;...&lt;/span&gt;&lt;span class="nv"&gt;$array2&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="nb"&gt;var_dump&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$array&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// ["a" =&amp;gt; 1, "b" =&amp;gt; 2]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;&lt;a href="https://stitcher.io/blog/new-in-php-81#array-unpacking-with-string-keys-rfc"&gt;Array unpacking also supports string keys&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;






&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nv"&gt;$a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nv"&gt;$b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="cm"&gt;/* … */&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nv"&gt;$foo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;...&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nv"&gt;$foo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;&lt;a href="https://wiki.php.net/rfc/first_class_callable_syntax"&gt;First class callables&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;






&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;generateSlug&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;HasTitle&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nc"&gt;HasId&lt;/span&gt; &lt;span class="nv"&gt;$post&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;strtolower&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$post&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getTitle&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="nv"&gt;$post&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getId&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;&lt;a href="https://stitcher.io/blog/new-in-php-81#pure-intersection-types-rfc"&gt;Pure intersection types&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;






&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$list&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"a"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"b"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"c"&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="nf"&gt;array_is_list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$list&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// true&lt;/span&gt;

&lt;span class="nv"&gt;$notAList&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"a"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"b"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"c"&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="nf"&gt;array_is_list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$notAList&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// false&lt;/span&gt;

&lt;span class="nv"&gt;$alsoNotAList&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"a"&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"a"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"b"&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"b"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"c"&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"c"&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="nf"&gt;array_is_list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$alsoNotAList&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;&lt;a href="https://stitcher.io/blog/new-in-php-81#new-array_is_list-function-rfc"&gt;The new &lt;code&gt;array_is_list&lt;/code&gt; function&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>php</category>
      <category>php81</category>
    </item>
    <item>
      <title>What's new in PHP 8.1</title>
      <dc:creator>Brent Roose</dc:creator>
      <pubDate>Fri, 29 Jan 2021 00:00:00 +0000</pubDate>
      <link>https://dev.to/brendt/what-s-new-in-php-8-1-2mg</link>
      <guid>https://dev.to/brendt/what-s-new-in-php-8-1-2mg</guid>
      <description>&lt;p&gt;PHP 8.1 is currently is active development and will probably be release somewhere around the end of November 2021. We already know some of the features, changes and deprecations, so let's go through them one by one.&lt;/p&gt;

&lt;p&gt;Do you want to stay up-to-date about PHP 8.1's development? Subscribe to my newsletter and receive occasional updates:&lt;/p&gt;

&lt;h2&gt;
  
  
  New features
&lt;/h2&gt;

&lt;p&gt;As with every release, PHP 8.1 adds some nice new features. Keep in mind that this list will grow over the year. I'm also listing features that haven't been implemented yet but that make a good chance of ending up in the language. I'll make sure to always mark those features.&lt;/p&gt;

&lt;h3&gt;
  
  
  Array unpacking with string keys
&lt;/h3&gt;

&lt;p&gt;Array unpacking was already allowed in &lt;a href="https://dev.to/blog/new-in-php-74"&gt;PHP 7.4&lt;/a&gt;, but it only worked with numeric keys. The reason string keys weren't supported before is because there wasn't any consensus on how to merge array duplicates. The RFC cleanly solves this by following the semantics of &lt;code&gt;array_merge&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$array1 = ["a" =&amp;gt; 1];

$array2 = ["b" =&amp;gt; 2];

$array = ["a" =&amp;gt; 0, ...$array1, ...$array2];

var_dump($array); // ["a" =&amp;gt; 1, "b" =&amp;gt; 2]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  New &lt;code&gt;array_is_list&lt;/code&gt; function
&lt;/h3&gt;

&lt;p&gt;You've probably had to deal with this once in a while: determine if an array's keys are in numerical order, starting form index 0. Just like &lt;code&gt;json_encode&lt;/code&gt; decides whether an array should be encoded as an array or object.&lt;/p&gt;

&lt;p&gt;PHP 8.1 adds a built-in function to determine whether an array is a list with those semantics, or not:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$list = ["a", "b", "c"];

array_is_list($list); // true

$notAList = [1 =&amp;gt; "a", 2 =&amp;gt; "b", 3 =&amp;gt; "c"];

array_is_list($notAList); // false

$alsoNotAList = ["a" =&amp;gt; "a", "b" =&amp;gt; "b", "c" =&amp;gt; "c"];

array_is_list($alsoNotAList); // false
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Explicit octal integer literal notation
&lt;/h3&gt;

&lt;p&gt;You can now use &lt;code&gt;0o&lt;/code&gt; and &lt;code&gt;0O&lt;/code&gt; to denote octal numbers. The previous notation by prefixing a number with &lt;code&gt;0&lt;/code&gt; still works as well.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;016 === 0o16; // true
016 === 0O16; // true
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Enums
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;This RFC is still under discussion.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Even though there hasn't been a vote yet, this proposal to add enums has been received with enthusiasm. If you're unsure about the value they add, you can read about them &lt;a href="https://dev.to/blog/php-enums"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Adding enums would be a significant improvement in PHP, so I'm for one am very much looking forward seeing this RFC further evolve. To give you a quick preview of what they would look like, here's a code sample:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;enum Status {
  case Pending;
  case Active;
  case Archived;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And this is how they would be used:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class Post
{
    public function __construct(
        private Status $status = Status::Pending;
    ) {}

    public function setStatus(Status $status): void
    {
        // …
    }
}

$post-&amp;gt;setStatus(Status::Active);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Breaking changes
&lt;/h2&gt;

&lt;p&gt;While PHP 8.1 is a minor version, there will be some changes that might technically be a breaking change, and deprecations as well. Let's discuss them one by one.&lt;/p&gt;

&lt;h3&gt;
  
  
  Restrict &lt;code&gt;$GLOBALS&lt;/code&gt; usage
&lt;/h3&gt;

&lt;p&gt;A small change to how &lt;code&gt;$GLOBALS&lt;/code&gt; is used will have a significant impact on the performance of all array operations. Nikita does a fine job explaining the problem and solution in the &lt;a href="https://wiki.php.net/rfc/restrict_globals_usage"&gt;RFC&lt;/a&gt;. The change means that some edge cases aren't possible to do anymore with &lt;code&gt;$GLOBALS&lt;/code&gt;. "&lt;em&gt;What is no longer supported are writes to $GLOBALS taken as a whole. All of the following will generate a compile-time error&lt;/em&gt;":&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$GLOBALS = [];
$GLOBALS += [];
$GLOBALS =&amp;amp; $x;
$x =&amp;amp; $GLOBALS;
unset($GLOBALS);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On top of that, passing &lt;code&gt;$GLOBALS&lt;/code&gt; by reference will generate a runtime error:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;by_ref($GLOBALS); // Run-time error
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nikita analysed the top 2000 packages on packagist, and only found 23 cases that will be affected by this change. We can conclude the impact of this — technically breaking — change will be low, which is why internals decided to add it in PHP 8.1. Remember that most of us will win by this change, given the positive performance impact it has everywhere in our code.&lt;/p&gt;

&lt;h3&gt;
  
  
  Deprecate passing null to non-nullable arguments of internal functions
&lt;/h3&gt;

&lt;p&gt;This change is simple: internal functions currently accept &lt;code&gt;null&lt;/code&gt; for arguments that are non-nullable, this RFC deprecates that behaviour. For example, this is currently possible:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;str_contains("string", null);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In PHP 8.1, these kinds of errors will throw a deprecation warning, in PHP 9 they will be converted to type errors.&lt;/p&gt;




&lt;p&gt;That's it for now, keep in mind I'll regularly update this post during the year, so make sure to &lt;a href="https://stitcher.io/newsletter/subscribe"&gt;subscribe&lt;/a&gt; if you want to be kept in the loop. Are you exited for PHP 8.1? Let me know on &lt;a href="https://twitter.com/brendt_gd"&gt;Twitter&lt;/a&gt;!&lt;/p&gt;

</description>
    </item>
    <item>
      <title>What a good PR looks like</title>
      <dc:creator>Brent Roose</dc:creator>
      <pubDate>Fri, 02 Oct 2020 00:00:00 +0000</pubDate>
      <link>https://dev.to/brendt/what-a-good-pr-looks-like-3lpf</link>
      <guid>https://dev.to/brendt/what-a-good-pr-looks-like-3lpf</guid>
      <description>&lt;p&gt;It's &lt;a href="https://hacktoberfest.digitalocean.com/"&gt;Hacktoberfest&lt;/a&gt;, your chance to contribute to open source and win a t-shirt while at it! Being an open source maintainer &lt;a href="https://github.com/brendt"&gt;myself&lt;/a&gt;, I find it a great initiative, but it comes with responsibility as well. Many people try to be smart and send low-effort, borderline-spam PRs, essentially &lt;a href="https://joel.net/how-one-guy-ruined-hacktoberfest2020-drama"&gt;ruining&lt;/a&gt; a maintainer's day.&lt;/p&gt;

&lt;p&gt;So to help maintainers &lt;em&gt;and&lt;/em&gt; contributors in creating quality open source, here are a few tips!&lt;/p&gt;

&lt;h2&gt;
  
  
  # Start by looking at existing issues and PRs
&lt;/h2&gt;

&lt;p&gt;Even though most PRs are well meant, it's important to first look around the repo for existing issues or PRs addressing the same problem. Someone else might already be working on a similar PR or there might be issues preventing the PR from being made. If you want to help out, start by participating in the discussions already happening, instead of working on your own.&lt;/p&gt;

&lt;h2&gt;
  
  
  # Discuss first
&lt;/h2&gt;

&lt;p&gt;If nothing has been said about your feature, it might be a good idea to discuss it first, instead of going ahead and potentially changing hundreds of lines of code. I'll be the one who has to maintain your PR for the foreseeable future, so it's best to first discuss it with me! I can probably give you some tips about the code base, as well as tell you about our expectations regarding implementation.&lt;/p&gt;

&lt;p&gt;You can choose to open an issue first, or submit a draft PR with a minimal implementation, a proof of concept. I actually really like those draft PRs: it visualises what you want to change, but also indicates that you realise there's more work to do.&lt;/p&gt;

&lt;h2&gt;
  
  
  # Follow the style guide
&lt;/h2&gt;

&lt;p&gt;Speaking of expectations, check whether the repository you're committing to has any code style guide or linter set up. &lt;strong&gt;Follow those rules&lt;/strong&gt;. Don't submit a PR that deliberately uses other styling rules. You're submitting code to another codebase, and that style guide has to be followed.&lt;/p&gt;

&lt;p&gt;A note to maintainers: you can help out here by using GitHub actions to automatically run your linters on PRs.&lt;/p&gt;

&lt;h2&gt;
  
  
  # Document your PR
&lt;/h2&gt;

&lt;p&gt;I'm going to review your code, so I'd like it to be as clear as possible. This starts by writing &lt;a href="https://dev.to/blog/a-programmers-cognitive-load"&gt;clean code&lt;/a&gt;: using proper variable names, maybe even add a doc block here and there; but it's equally important to explain your thought process as well. You could use review comments to clarify specific parts of the code, or you could add some general comments in the PR.&lt;/p&gt;

&lt;h2&gt;
  
  
  # Clean commits
&lt;/h2&gt;

&lt;p&gt;Please try to avoid &lt;code&gt;"wip"&lt;/code&gt; commit messages, please? You don't have to write a book for every commit, and I realise that you might not want to think about them while in the zone; but something like &lt;code&gt;"Refactor XX to YY"&lt;/code&gt; is already infinitely better than &lt;code&gt;"wip"&lt;/code&gt;. If you really want a good commit message, try to have your commits only do one thing, and try to explain &lt;em&gt;why&lt;/em&gt; this commit is necessary.&lt;/p&gt;

&lt;h2&gt;
  
  
  # Only relevant changes
&lt;/h2&gt;

&lt;p&gt;Only submit changes that are relevant within the scope of the PR. You might be tempted to fix another thing or two while at it — and you're allowed to — but keep those changes in a separate PR.&lt;/p&gt;

&lt;p&gt;You can always base a new branch on your PR branch if necessary, and mention in the second PR that it depends on the first one to be merged. I'm happy to merge them for you, in the right order.&lt;/p&gt;

&lt;h2&gt;
  
  
  # Be patient
&lt;/h2&gt;

&lt;p&gt;It might take a while for maintainers to merge your PR. I even confess to have lost track of a few PRs over the past years. A friendly "bump" after a few days is always appreciated, but it still might take some time. Remember that most OSS maintainers are doing this on a voluntary basis, so don't be mad when a PR takes a little longer to merge.&lt;/p&gt;

&lt;h2&gt;
  
  
  # Be friendly
&lt;/h2&gt;

&lt;p&gt;This goes for both maintainers and contributors: don't be a jerk. Sometimes a PR gets declined, sometimes a maintainers looses their patience. Stop and breath, realise it's not the end of the world and move on. Be friendly and respectful.&lt;/p&gt;

&lt;h2&gt;
  
  
  # Don't wait too long to tag
&lt;/h2&gt;

&lt;p&gt;This one is for the maintainers: one of the most frustrating things is a PR getting accepted, and than having to wait another month for a release to be tagged. You shouldn't be afraid of high version numbers, that's what semver is for. Tag the release as soon as possible, and please don't wait another week!&lt;/p&gt;




&lt;p&gt;Do you have any more tips? Let them know via &lt;a href="https://twitter.com/brendt_gd"&gt;Twitter&lt;/a&gt; or &lt;a href="//mailto:brendt@stitcher.io"&gt;email&lt;/a&gt;. Here's already another good read by my Colleague Sebastian, on how to write &lt;a href="https://sebastiandedeyne.com/a-good-issue/"&gt;a good issue&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>opensource</category>
    </item>
    <item>
      <title>PHP 8: before and after</title>
      <dc:creator>Brent Roose</dc:creator>
      <pubDate>Mon, 20 Jul 2020 00:00:00 +0000</pubDate>
      <link>https://dev.to/brendt/php-8-before-and-after-2kol</link>
      <guid>https://dev.to/brendt/php-8-before-and-after-2kol</guid>
      <description>&lt;p&gt;It's only a few months before &lt;a href="https://stitcher.io/blog/new-in-php-8"&gt;PHP 8&lt;/a&gt; will be released, and honestly there are so many good features. In this post I want to share the real-life impact that PHP 8 will have on my own code.&lt;/p&gt;

&lt;h2&gt;
  
  
  # Events subscribers with attributes
&lt;/h2&gt;

&lt;p&gt;I'm going to try not to abuse &lt;a href="https://stitcher.io/blog/attributes-in-php-8"&gt;attributes&lt;/a&gt;, but I think configuring event listeners is an example of an annotation I'll be using extensively.&lt;/p&gt;

&lt;p&gt;You might know that I've been working on &lt;a href="https://stitcher.io/blog/combining-event-sourcing-and-stateful-systems"&gt;event sourced systems&lt;/a&gt; lately, and I can tell you: there's lots of event configuration to do. Take this simple projector, for example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Before

class CartsProjector implements Projector
{
    use ProjectsEvents;

    protected array $handlesEvents = [
        CartStartedEvent::class =&amp;gt; 'onCartStarted',
        CartItemAddedEvent::class =&amp;gt; 'onCartItemAdded',
        CartItemRemovedEvent::class =&amp;gt; 'onCartItemRemoved',
        CartExpiredEvent::class =&amp;gt; 'onCartExpired',
        CartCheckedOutEvent::class =&amp;gt; 'onCartCheckedOut',
        CouponAddedToCartItemEvent::class =&amp;gt; 'onCouponAddedToCartItem',
    ];

    public function onCartStarted(CartStartedEvent $event): void
    { /* … */ }

    public function onCartItemAdded(CartItemAddedEvent $event): void
    { /* … */ }

    public function onCartItemRemoved(CartItemRemovedEvent $event): void
    { /* … */ }

    public function onCartCheckedOut(CartCheckedOutEvent $event): void
    { /* … */ }

    public function onCartExpired(CartExpiredEvent $event): void
    { /* … */ }

    public function onCouponAddedToCartItem(CouponAddedToCartItemEvent $event): void
    { /* … */ }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;PHP 7.4&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;There are two benefits attributes will give me:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Event listener configuration and handlers are put together, I don't have to scroll to the top of the file to know whether a listener is configured correctly.&lt;/li&gt;
&lt;li&gt;I don't have to bother anymore writing and managing method names as strings: your IDE can't autocomplete them, there's no static analysis on typos and method renaming doesn't work.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Luckily, PHP 8 solves these problems:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class CartsProjector implements Projector
{
    use ProjectsEvents;

    @@SubscribesTo(CartStartedEvent::class)
    public function onCartStarted(CartStartedEvent $event): void
    { /* … */ }

    @@SubscribesTo(CartItemAddedEvent::class)
    public function onCartItemAdded(CartItemAddedEvent $event): void
    { /* … */ }

    @@SubscribesTo(CartItemRemovedEvent::class)
    public function onCartItemRemoved(CartItemRemovedEvent $event): void
    { /* … */ }

    @@SubscribesTo(CartCheckedOutEvent::class)
    public function onCartCheckedOut(CartCheckedOutEvent $event): void
    { /* … */ }

    @@SubscribesTo(CartExpiredEvent::class)
    public function onCartExpired(CartExpiredEvent $event): void
    { /* … */ }

    @@SubscribesTo(CouponAddedToCartItemEvent::class)
    public function onCouponAddedToCartItem(CouponAddedToCartItemEvent $event): void
    { /* … */ }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;PHP 8&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  # Static instead of doc blocks
&lt;/h2&gt;

&lt;p&gt;A smaller one, but this one will have a day-by-day impact. I often find myself still needing doc blocks because of two things: static return types en generics. The latter one can't be solved yet, but luckily the first one will in PHP 8!&lt;/p&gt;

&lt;p&gt;When I'd write this in PHP 7.4:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/**
 * @return static
 */
public static function new()
{
    return new static();
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;PHP 7.4&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I'll now be able to write:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public static function new(): static
{
    return new static();
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;PHP 8&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  # DTO's, property promotion and named arguments
&lt;/h2&gt;

&lt;p&gt;If you read my blog, you know I wrote quite a bit about the use of PHP's type system combined with &lt;a href="https://stitcher.io/blog/laravel-beyond-crud-02-working-with-data"&gt;data transfer objects&lt;/a&gt;. Naturally, I use lots of DTOs in my own code, so you can image how happy I am, being able to rewrite this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class CustomerData extends DataTransferObject
{
    public string $name;

    public string $email;

    public int $age;

    public static function fromRequest(
        CustomerRequest $request
    ): self {
        return new self([
            'name' =&amp;gt; $request-&amp;gt;get('name'),
            'email' =&amp;gt; $request-&amp;gt;get('email'),
            'age' =&amp;gt; $request-&amp;gt;get('age'),
        ]);
    }
}

$data = CustomerData::fromRequest($customerRequest);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;PHP 7.4&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;As this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class CustomerData
{
    public function __construct(
        public string $name,
        public string $email,
        public int $age,
    ) {}
}

$data = new CustomerData(...$customerRequest-&amp;gt;validated());
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;PHP 8&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Note the use of both &lt;a href="https://stitcher.io/blog/constructor-promotion-in-php-8"&gt;constructor property promotion&lt;/a&gt;, as well as named arguments. Yes, they can be passed using named arrays and the spread operator!&lt;/p&gt;

&lt;h2&gt;
  
  
  # Enums and the match expression
&lt;/h2&gt;

&lt;p&gt;Do you sometimes find yourself using an enum with some methods on it, that will give a different result based on the enum value?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/**
 * @method static self PENDING()
 * @method static self PAID()
 */
class InvoiceState extends Enum
{
    private const PENDING = 'pending';
    private const PAID = 'paid';

    public function getColour(): string
    {
        return [
            self::PENDING =&amp;gt; 'orange',
            self::PAID =&amp;gt; 'green',
        ][$this-&amp;gt;value] ?? 'gray';   
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;PHP 7.4&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I would argue that for complexer conditions, you're better off using &lt;a href="https://stitcher.io/blog/laravel-beyond-crud-05-states"&gt;the state pattern&lt;/a&gt;, yet there are cases where an enum does suffice. This weird array syntax already is a shorthand for a more verbose conditional:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/**
 * @method static self PENDING()
 * @method static self PAID()
 */
class InvoiceState extends Enum
{
    private const PENDING = 'pending';
    private const PAID = 'paid';

    public function getColour(): string
    {
        if ($this-&amp;gt;value === self::PENDING) {
            return 'orange';
        }

        if ($this-&amp;gt;value === self::PAID) {
            return 'green'
        }

        return 'gray';
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;PHP 7.4 — alternative&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;But with PHP 8, we can use the &lt;a href="https://stitcher.io/blog/php-8-match-or-switch"&gt;&lt;code&gt;match&lt;/code&gt; expression&lt;/a&gt; instead!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/**
 * @method static self PENDING()
 * @method static self PAID()
 */
class InvoiceState extends Enum
{
    private const PENDING = 'pending';
    private const PAID = 'paid';

    public function getColour(): string
    {
        return match ($this-&amp;gt;value) {
            self::PENDING =&amp;gt; 'orange',
            self::PAID =&amp;gt; 'green',
            default =&amp;gt; 'gray',
        };
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;PHP 8&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  # Union types instead of doc blocks
&lt;/h2&gt;

&lt;p&gt;When I mentioned the &lt;code&gt;static&lt;/code&gt; return type before, I forgot another use case where docblock type hints were required: union types. At least, they were required before, because PHP 8 supports them natively!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/**
 * @param string|int $input
 *
 * @return string 
 */
public function sanitize($input): string;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;PHP 7.4&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public function sanitize(string|int $input): string;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;PHP 8&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  # Throw expressions
&lt;/h2&gt;

&lt;p&gt;Before PHP 8, you couldn't use &lt;code&gt;throw&lt;/code&gt; in an expression, meaning you'd have to do explicit checks like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public function (array $input): void
{
    if (! isset($input['bar'])) {
        throw BarIsMissing::new();
    }

    $bar = $input['bar'];

    // …
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;PHP 7.4&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In PHP 8, &lt;code&gt;throw&lt;/code&gt; has become an expression, meaning you can use it like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public function (array $input): void
{
    $bar = $input['bar'] ?? throw BarIsMissing::new();

    // …
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;PHP 8&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;What's your favourite &lt;a href="https://stitcher.io/blog/new-in-php-8"&gt;PHP 8 feature&lt;/a&gt;?&lt;/p&gt;

</description>
      <category>php</category>
    </item>
    <item>
      <title>Don't write your own framework</title>
      <dc:creator>Brent Roose</dc:creator>
      <pubDate>Sat, 13 Jun 2020 00:00:00 +0000</pubDate>
      <link>https://dev.to/brendt/don-t-write-your-own-framework-30nn</link>
      <guid>https://dev.to/brendt/don-t-write-your-own-framework-30nn</guid>
      <description>&lt;p&gt;We were sitting with 5 or 6 backend developers around the large meeting table. It was 10 in the morning on a Monday, and we were all silently working on our laptops. There was a hasty atmosphere, and everyone tried to concentrate on the task ahead.&lt;/p&gt;

&lt;p&gt;Less than 2 hours before, I walked into the office, not yet aware of any harm. I was immediately called to the meeting room at the back, there was no time to sit at my desk. Still I quickly grabbed a coffee, and went to the back where a few other colleagues already gathered.&lt;/p&gt;

&lt;p&gt;With them was our boss, a nice guy; there wasn't any "upper management" culture or anything, we were just colleagues. The other people in the room already knew what was going on, so he explained to me personally.&lt;/p&gt;

&lt;p&gt;There was a bug, in our in-house framework.&lt;/p&gt;

&lt;p&gt;"It sure isn't the first one" — I remember thinking.&lt;/p&gt;

&lt;p&gt;At this point we'd used this custom-built framework for several years; 200 websites were affected, more or less.&lt;/p&gt;

&lt;p&gt;The bug was a stupid mistake — after all, which bug isn't?&lt;/p&gt;

&lt;p&gt;Our framework router would take a URL and filter out repeated slashes, so &lt;code&gt;//admin&lt;/code&gt; would become &lt;code&gt;/admin&lt;/code&gt;. This is, I believe, part of some HTTP spec; at least I was told so, I never double checked. The problem however, was in the authorisation layer: &lt;code&gt;/admin&lt;/code&gt; was a protected URL, but &lt;code&gt;//admin&lt;/code&gt; was not. So the router would resolve &lt;code&gt;//admin&lt;/code&gt; and all its underlying pages to the admin section, and the authoriser wouldn't recognise it as a location you'd need admin privileges for.&lt;/p&gt;

&lt;p&gt;In other words: the admin section of all our websites could be entered without any login, by simply replacing &lt;code&gt;/admin&lt;/code&gt; with &lt;code&gt;//admin&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;I don't remember drinking my coffee after that.&lt;/p&gt;

&lt;p&gt;So we did the only thing we could do: manually update all of our websites, some running a very outdated version of our framework. It took us 3 days to do this with 5 or 6 developers. You can do the math on how much it cost.&lt;/p&gt;

&lt;p&gt;In the end we never actually got to know whether the bug had been exploited: it was discovered by accident by one of our colleagues over the weekend, and we didn't keep access logs longer than a few days. So nobody could tell whether someone had unauthorised access to one of our sites over the past years; let alone know if, and which data had been leaked.&lt;/p&gt;




&lt;p&gt;Don't write your own framework, at least not when you're building websites for paying clients; who trust your work to be professional and secure. Whatever framework you use, make sure it's backed by a large community.&lt;/p&gt;

</description>
      <category>programming</category>
    </item>
    <item>
      <title>The latest PHP version</title>
      <dc:creator>Brent Roose</dc:creator>
      <pubDate>Wed, 03 Jun 2020 04:44:46 +0000</pubDate>
      <link>https://dev.to/brendt/the-latest-php-version-597b</link>
      <guid>https://dev.to/brendt/the-latest-php-version-597b</guid>
      <description>&lt;p&gt;It seems like a simple question with a simple answer: the latest PHP version currently is &lt;a href="https://stitcher.io/blog/new-in-php-74"&gt;PHP 7.4&lt;/a&gt;. However! If you want to know more inside information about how PHP's lifecycle is managed, keep on reading!&lt;/p&gt;

&lt;h2&gt;
  
  
  Levels of support
&lt;/h2&gt;

&lt;p&gt;PHP versions are grouped in three levels of support: active, security fixes only and end of life. The "end of life" versions should be avoided at all costs, usually a version goes into the "end of life" phase after three years. A year before that, it goes into the "security fixes only" phase, where only the most needed security fixes are released, and no more other improvements or bug fixes.&lt;/p&gt;

&lt;p&gt;These are the currently active supported PHP versions:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;tr&gt;
    &lt;td&gt;PHP 7.2&lt;/td&gt;
    &lt;td&gt;Security fixes until November 30, 2020&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
    &lt;td&gt;PHP 7.3&lt;/td&gt;
    &lt;td&gt;Active support until December 6, 2020&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
    &lt;td&gt;PHP 7.4 (current)&lt;/td&gt;
    &lt;td&gt;Active support until November 28, 2021&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;This release cycle guarantees that, usually, only three versions of PHP are supported at any given time, with only two being actively supported.&lt;br&gt;
I say &lt;em&gt;usually&lt;/em&gt; because PHP 5.6 had a year extra of security fixes support, but that has also ended now: PHP 5.6 was supported up until December 31, 2018.&lt;/p&gt;

&lt;h2&gt;
  
  
  A look at the past
&lt;/h2&gt;

&lt;p&gt;So, if you're not running PHP 7.2, 7.3 or 7.4, you're running a version that won't receive any updates anymore. At least none from the official PHP developers. There are in fact companies still working independently on old PHP versions like PHP 5.6. &lt;/p&gt;

&lt;p&gt;These initiatives of course only exist because there's a need for them: PHP 5.6 is somewhat the Windows XP of the PHP world: it was such a popular release at the time, and many older projects aren't able to deal with the breaking changes the new major version of PHP brings. As a sidenote: the new PHP version after PHP 5.6 is PHP 7 and 6 was skipped; but that's a story for another day. &lt;/p&gt;

&lt;p&gt;The PHP 5.* era was the one that set PHP on a course for maturity, a path that would be continued in the 7.* versions, and one that has proven itself over the past years: PHP's performance increased significantly compared to the 5.* versions, the rich community only, and the language syntax and type system kept evolving towards a modern day language.&lt;/p&gt;

&lt;p&gt;Obviously PHP bears the consequences of more than 26 years of legacy with it, but in that time it has also proven itself to be a robust and stable language, despite its reputation.&lt;/p&gt;

&lt;p&gt;About that reputation — PHP is still looked down upon by many who don't know the modern language — PHP is quite a good language these days. Yes, it carries its battle scars, and we'd wish for many legacy things to just go away, but overall it's quite a nice tool; one that has proven itself time and time again.&lt;/p&gt;

&lt;p&gt;These days, the core teams keeps a consistent release cycle: one new release every year, and every 4 or 5 years a new major release. And there are exiting times to come: 2020 will be the year of the new major release, since &lt;a href="https://stitcher.io/blog/new-in-php-8"&gt;PHP 8&lt;/a&gt; is coming by the end of the year!&lt;/p&gt;

&lt;p&gt;Every new release is done in stages: the last months before the general availability — GA, or simply &lt;em&gt;the release&lt;/em&gt; — is focused on testing all the new features and changes. First there are couple of alpha releases, followed by beta releases, followed by release candidates, followed by the final release: GA.&lt;/p&gt;

&lt;p&gt;During the alpha phase, new features are still allowed to be added. But once in beta, the final form of the new version has been decided on. &lt;/p&gt;

&lt;p&gt;These features, by the way, are decided upon by a core committee who votes on RFCs, which stands for &lt;em&gt;request for comments&lt;/em&gt;. These RFCs describe a feature or a change to the language, and are discussed in depth. Everyone is allowed to make RFCs if they want to, but RFCs are of course critically looked at.&lt;/p&gt;

&lt;p&gt;PHP 8 is still in the RFC phase, so things are still changing, but not for long anymore! This is the timeline of alpha, beta, RCs and GA, it looks like this:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;tr&gt;
    &lt;td&gt;Alpha 1&lt;/td&gt;
    &lt;td&gt;June 18, 2020&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
    &lt;td&gt;Alpha 2&lt;/td&gt;
    &lt;td&gt;July 2, 2020&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
    &lt;td&gt;Alpha 3&lt;/td&gt;
    &lt;td&gt;July 16, 2020&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
    &lt;td&gt;Feature freeze&lt;/td&gt;
    &lt;td&gt;July 28, 2020&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
    &lt;td&gt;Beta 1&lt;/td&gt;
    &lt;td&gt;July 30, 2020&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
    &lt;td&gt;Beta 2&lt;/td&gt;
    &lt;td&gt;August 13, 2020&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
    &lt;td&gt;Beta 3&lt;/td&gt;
    &lt;td&gt;August 27, 2020&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
    &lt;td&gt;Release candidate 1&lt;/td&gt;
    &lt;td&gt;September 10, 2020&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
    &lt;td&gt;Release candidate 2&lt;/td&gt;
    &lt;td&gt;September 24, 2020&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
    &lt;td&gt;Release candidate 3&lt;/td&gt;
    &lt;td&gt;October 8, 2020&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
    &lt;td&gt;Release candidate 4&lt;/td&gt;
    &lt;td&gt;October 22, 2020&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
    &lt;td&gt;Release candidate 5&lt;/td&gt;
    &lt;td&gt;November 5, 2020&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
    &lt;td&gt;Release candidate 6&lt;/td&gt;
    &lt;td&gt;November 19, 2020&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
    &lt;td&gt;General availability&lt;/td&gt;
    &lt;td&gt;December 3, 2020&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;As you can see, we're closing in on the first alpha releases.&lt;/p&gt;

&lt;p&gt;It &lt;em&gt;is&lt;/em&gt; possible by the way, for the dates to shift a little bit still, this will depend on how testing goes early on. Speaking of testing: everyone is allowed to do so, it's even encouraged to try stuff out in your own projects, so that enough feedback can be provided to the core team on time.&lt;/p&gt;




&lt;p&gt;I told you there was more to PHP's release cycle than just one active version 😁. My advice for modern-day projects would be this: always make sure to update at the latest a few months after GA. Don't lack behind 2 or 3 versions, or even worse: be stuck in PHP 5 land. &lt;/p&gt;

&lt;p&gt;The updates actually never were that much of a pain, and there's so much to gain: performance improvements, security benefits, new syntax, wider community support. So keep that in mind, and let's look forward to &lt;a href="https://stitcher.io/blog/new-in-php-8"&gt;PHP 8&lt;/a&gt;!&lt;/p&gt;

</description>
      <category>php</category>
    </item>
    <item>
      <title>PHP 8 in 8 code blocks</title>
      <dc:creator>Brent Roose</dc:creator>
      <pubDate>Fri, 15 May 2020 00:00:00 +0000</pubDate>
      <link>https://dev.to/brendt/php-8-in-8-code-blocks-2b81</link>
      <guid>https://dev.to/brendt/php-8-in-8-code-blocks-2b81</guid>
      <description>&lt;p&gt;PHP 8 brings lots of new features, in this list we'll look at the most outstanding ones. If you want a full list and background information, you can read about all things &lt;a href="https://stitcher.io/blog/new-in-php-8"&gt;new in PHP 8&lt;/a&gt;.&lt;/p&gt;






&lt;div class="highlight"&gt;&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nx"&gt;use&lt;/span&gt; &lt;span class="nx"&gt;\Support\Attributes\ListensTo&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ProductSubscriber&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ListensTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ProductCreated&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;onProductCreated&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ProductCreated&lt;/span&gt; &lt;span class="nv"&gt;$event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="cm"&gt;/* … */&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ListensTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ProductDeleted&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;onProductDeleted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ProductDeleted&lt;/span&gt; &lt;span class="nv"&gt;$event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="cm"&gt;/* … */&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Attributes — aka annotations — you can about them in depth in &lt;a href="https://stitcher.io/blog/attributes-in-php-8"&gt;this post&lt;/a&gt;.&lt;/p&gt;






&lt;div class="highlight"&gt;&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Foo&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="nx"&gt;Bar&lt;/span&gt; &lt;span class="nv"&gt;$input&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="kt"&gt;float&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;bar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;mixed&lt;/span&gt; &lt;span class="nv"&gt;$input&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;mixed&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Union types allows for type hinting several types. There's also a new &lt;code&gt;mixed&lt;/code&gt; type which represents &lt;a href="https://stitcher.io/blog/new-in-php-8#new-mixed-type-rfc"&gt;several types&lt;/a&gt; at once.&lt;/p&gt;






&lt;div class="highlight"&gt;&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;Foo&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;bar&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;static&lt;/code&gt; return type is built-in.&lt;/p&gt;






&lt;div class="highlight"&gt;&lt;pre class="highlight ini"&gt;&lt;code&gt;&lt;span class="nn"&gt;[JIT]&lt;/span&gt;
&lt;span class="py"&gt;opcache.jit&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;5&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;a href="https://stitcher.io/blog/php-jit"&gt;The just-in-time compiler&lt;/a&gt; for PHP.&lt;/p&gt;






&lt;div class="highlight"&gt;&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$triggerError&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;MyError&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nv"&gt;$foo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$bar&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'offset'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;OffsetDoesNotExist&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'offset'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;code&gt;throw&lt;/code&gt; can be used in expressions.&lt;/p&gt;






&lt;div class="highlight"&gt;&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Something goes wrong&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;MySpecialException&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;Log&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Something went wrong"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Non-capturing catches: no need to specify an exception variable if you don't need it.&lt;/p&gt;






&lt;div class="highlight"&gt;&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="nv"&gt;$parameterA&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nv"&gt;$parameterB&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;Foo&lt;/span&gt; &lt;span class="nv"&gt;$objectfoo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// …&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Trailing commas are allowed in parameter lists&lt;/p&gt;






&lt;div class="highlight"&gt;&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nx"&gt;str_contains&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'string with lots of words'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'words'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;str_starts_with&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'haystack'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'hay'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;str_ends_with&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'haystack'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'stack'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;New string functions.&lt;/p&gt;




&lt;p&gt;Let's not fool ourselves: 8 code blocks isn't enough to summarise all great new things in PHP 8. If you want a full list, you can find it &lt;a href="https://stitcher.io/blog/new-in-php-8"&gt;on my blog&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;What feature are you looking forward to the most? Let me know on &lt;a href="https://twitter.com/brendt_gd"&gt;Twitter&lt;/a&gt; or via &lt;a href="//mailto:brendt@stitcher.io"&gt;email&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>php</category>
      <category>php8</category>
    </item>
    <item>
      <title>Combining event sourcing and stateful systems</title>
      <dc:creator>Brent Roose</dc:creator>
      <pubDate>Tue, 14 Apr 2020 00:00:00 +0000</pubDate>
      <link>https://dev.to/brendt/combining-event-sourcing-and-stateful-systems-5aie</link>
      <guid>https://dev.to/brendt/combining-event-sourcing-and-stateful-systems-5aie</guid>
      <description>&lt;p&gt;In this two-part series, my colleague &lt;a href="https://twitter.com/freekmurze"&gt;Freek&lt;/a&gt; and I will discuss the architecture of a project we're working on. We will share our insights and answers to problems we encountered along the way. This part will be about the design of the system, while &lt;a href="https://freek.dev/1634-mixing-event-sourcing-in-a-traditional-laravel-app"&gt;Freek's part&lt;/a&gt; will look at the concrete implementation.&lt;/p&gt;

&lt;p&gt;Let's set the scene.&lt;/p&gt;

&lt;p&gt;This project is one of the larger ones we've worked on. In the end it will serve hundreds of thousands of users, it'll handle large amounts of financial transactions, standalone tenant-specific installations need to be created on the fly.&lt;/p&gt;

&lt;p&gt;One key requirement is that the product ordering flow — the core of the business — can be easily reported on, as well as tracked throughout history.&lt;/p&gt;

&lt;p&gt;Besides this front-facing client process, there's also a complex admin panel to manage products. Within this context, there's little to no need for reporting or tracking history of the admin activities; the main goal here is to have an easy-to-use product management system.&lt;/p&gt;

&lt;p&gt;I hope you understand that I deliberately am keeping these terms a little vague because obviously this isn't an open-source project, though I think the concepts of "product management" and "orders" is clear enough for you to understand the design decisions we've made.&lt;/p&gt;

&lt;p&gt;Let’s first discuss an approach of how to design this system based on my &lt;a href="//htttps://stitcher.io/blog/laravel-beyond-crud"&gt;Laravel beyond CRUD&lt;/a&gt; series.&lt;/p&gt;

&lt;p&gt;In such a system there would probably be two domain groups: &lt;code&gt;Product&lt;/code&gt; and &lt;code&gt;Order&lt;/code&gt;, and two applications making use of both these domains: an &lt;code&gt;AdminApplication&lt;/code&gt; and a &lt;code&gt;CustomerApplication&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;A simplified version would look something like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="///resources/img/blog/event-sourcing/es_1.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--j11luFB9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.stitcher.io/resources/img/blog/event-sourcing/es_1.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Having used this architecture successfully in previous projects, we could simply rely on it and call it a day. There are a few downsides with it though, specifically for this new project: we have to keep in mind that reporting and historical tracking are key aspects of the ordering process. We want to treat them as such in our code, and not as a mere side effect.&lt;/p&gt;

&lt;p&gt;For example: we could use our activity log package to keep track of "history messages" about what happened with an order. We could also start writing custom queries on the order and history tables to generate reports.&lt;/p&gt;

&lt;p&gt;However, these solutions only work properly when they are minor side effects of the core business. In this case, they are not. So Freek and I were tasked with figuring out a design for this project that made reporting and historical tracking an easy-to-maintain and easy-to-use, core part of the application.&lt;/p&gt;

&lt;p&gt;Naturally we looked at event sourcing, a wonderful and flexible solution that fulfills the above requirements. Nothing comes for free though: event sourcing requires quite a lot of extra code to be written in order to do otherwise simple things. Where you'd normally have simple CRUD actions manipulating data in the database, you now have to worry about dispatching events, handling them with projectors and reactors, always keeping versioning in mind.&lt;/p&gt;

&lt;p&gt;While it was clear that an event sourced system would solve many of the problems, it would also introduce lots of overhead, even in places where it wouldn't add any value.&lt;/p&gt;

&lt;p&gt;Here's what I mean with that: if we decide to event source the &lt;code&gt;Orders&lt;/code&gt; module, which relies on data from the &lt;code&gt;Products&lt;/code&gt; module, we also need to event source that one, because otherwise we could end up with an invalid state. If &lt;code&gt;Products&lt;/code&gt; weren't event sourced, and one was deleted, we'd couldn't rebuild the &lt;code&gt;Orders&lt;/code&gt; state anymore, since it's missing information.&lt;/p&gt;

&lt;p&gt;So either we event source everything, or find a solution for this problem. You can read about it &lt;a href="https://stitcher.io/blog/combining-event-sourcing-and-stateful-systems#event-source-all-the-things?!"&gt;here&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>ddd</category>
      <category>php</category>
      <category>eventsourcing</category>
    </item>
    <item>
      <title>Benchmarking preloading in PHP 7.4</title>
      <dc:creator>Brent Roose</dc:creator>
      <pubDate>Fri, 10 Jan 2020 11:10:50 +0000</pubDate>
      <link>https://dev.to/brendt/benchmarking-preloading-in-php-7-4-50ng</link>
      <guid>https://dev.to/brendt/benchmarking-preloading-in-php-7-4-50ng</guid>
      <description>&lt;p&gt;I've decided to benchmark PHP's new preloading feature on one of my real-life projects. These are the results:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--YxLdgu1N--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/lgies67fzp93larklnvl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--YxLdgu1N--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/lgies67fzp93larklnvl.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can read about the benchmarking process on my blog: &lt;a href="https://stitcher.io/blog/php-preload-benchmarks"&gt;https://stitcher.io/blog/php-preload-benchmarks&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>php</category>
    </item>
    <item>
      <title>Laravel beyond CRUD</title>
      <dc:creator>Brent Roose</dc:creator>
      <pubDate>Wed, 16 Oct 2019 00:00:00 +0000</pubDate>
      <link>https://dev.to/brendt/laravel-beyond-crud-21ej</link>
      <guid>https://dev.to/brendt/laravel-beyond-crud-21ej</guid>
      <description>&lt;ul&gt;
&lt;li&gt;00. Preface&lt;/li&gt;
&lt;li&gt;&lt;a href="https://stitcher.io/blog/laravel-beyond-crud-01-domain-oriented-laravel"&gt;01. Domains&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://stitcher.io/blog/laravel-beyond-crud-02-working-with-data"&gt;02. Working with data&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;03. Actions: coming next week&lt;/li&gt;
&lt;li&gt;04. Models: coming soon&lt;/li&gt;
&lt;li&gt;More chapters are in the making&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Preface
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;A book for PHP developers working on larger-than-average Laravel projects&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I've been writing and maintaining several larger-than-average web applications for years now. These are projects that take a team of developers to work on it for at least a year, often times longer. They are projects that take more than the well-known Laravel CRUD approach to stay maintainable.&lt;/p&gt;

&lt;p&gt;In this time I've looked at several architectures which would help me and our team improve the maintainability of these projects, as well as help make the development more easy, both for us and our clients: DDD, Hexagonal Architecture, Event Sourcing.&lt;/p&gt;

&lt;p&gt;Because most of these projects were large, yet not ginormous, these paradigms as a whole were almost always overkill. On top of that were we still dealing with fixed deadlines, meaning we couldn't spend ages on fine tuning the architecture.&lt;/p&gt;

&lt;p&gt;In general, these were projects with a development lifespan of six months to one year, with a team of three to six developers working on them simultaneously. After going live, most of these projects are still heavily worked on for years to come.&lt;/p&gt;

&lt;p&gt;In this book, I'll write about the knowledge we gained over the years in designing these projects. I will take a close look at the "Laravel way", and what did and didn't work for us.This book is for you if you're dealing with these larger Laravel projects, and want practical and pragmatic solutions in managing it.&lt;/p&gt;

&lt;p&gt;I will talk about theory, patterns and principles, though everything will be in context of a real-life, working web application.&lt;/p&gt;

&lt;p&gt;The goal of this book is to hand you concrete solutions to real life problems, things you can start doing different in your projects today. Enjoy!&lt;/p&gt;

&lt;h2&gt;
  
  
  About me
&lt;/h2&gt;

&lt;p&gt;My name is Brent, I'm a 25-year old web developer living in Belgium. I've been writing PHP professionally for the past 5 years, and have been programming since I was 13 years old.&lt;/p&gt;

&lt;p&gt;As a professional, I've mainly worked on medium- to large sized web applications and APIs. Right now I work with Laravel at a company called &lt;a href="https://spatie.be"&gt;Spatie&lt;/a&gt;, and before that I worked with both Symfony and company-specific frameworks.&lt;/p&gt;

</description>
      <category>laraval</category>
      <category>php</category>
      <category>ddd</category>
    </item>
    <item>
      <title>A letter to the PHP team</title>
      <dc:creator>Brent Roose</dc:creator>
      <pubDate>Wed, 28 Aug 2019 00:00:00 +0000</pubDate>
      <link>https://dev.to/brendt/a-letter-to-the-php-team-5ddn</link>
      <guid>https://dev.to/brendt/a-letter-to-the-php-team-5ddn</guid>
      <description>&lt;p&gt;I've taken the time to write a letter to the PHP core developers; addressing, what I think are, some serious issues holding PHP back.&lt;/p&gt;

&lt;p&gt;I've addressed two main concerns&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The fear of breaking backwards compatibility&lt;/li&gt;
&lt;li&gt;How communication between the core- and userland developers is flawed&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can read my letter on my blog: &lt;a href="https://stitcher.io/blog/a-letter-to-the-php-team"&gt;https://stitcher.io/blog/a-letter-to-the-php-team&lt;/a&gt;&lt;/p&gt;

</description>
      <category>php</category>
    </item>
    <item>
      <title>Preloading in PHP 7.4</title>
      <dc:creator>Brent Roose</dc:creator>
      <pubDate>Thu, 04 Jul 2019 00:00:00 +0000</pubDate>
      <link>https://dev.to/brendt/preloading-in-php-7-4-o92</link>
      <guid>https://dev.to/brendt/preloading-in-php-7-4-o92</guid>
      <description>&lt;p&gt;PHP 7.4 adds preloading support, a feature that could improve the performance of your code significantly.&lt;/p&gt;

&lt;p&gt;In a nutshell, this is what preloading is about:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;In order to preload files, you need to write a custom PHP script&lt;/li&gt;
&lt;li&gt;This script is executed once on server startup&lt;/li&gt;
&lt;li&gt;All preloaded files are available in memory for all requests&lt;/li&gt;
&lt;li&gt;Changes made to the source file won't have any effect, until the server is restarted&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's look at it in depth.&lt;/p&gt;

&lt;h2&gt;
  
  
  Opcache, but more
&lt;/h2&gt;

&lt;p&gt;While preloading is built on top op opcache, it's not exactly the same. Opcache will take your PHP source files, compile it to "opcodes", and store those compiled files on disk.&lt;/p&gt;

&lt;p&gt;You can think of "opcodes" as a low-level representation of your code, that can be easily interpreted at runtime. So opcache skips the translation step between your source files and what the PHP interpreter actually needs at runtime. A huge win!&lt;/p&gt;

&lt;p&gt;But, there's more to be gained. Opcached files don't know about other files. If you've got a class &lt;code&gt;A&lt;/code&gt; extending from class &lt;code&gt;B&lt;/code&gt;, you'd still need to link them together at runtime. Furthermore, opcache performs checks to see whether the source files were modified, and will invalidate its caches based on that.&lt;/p&gt;

&lt;p&gt;So this is where preloading comes into play: it will not only compile source files to opcodes, but also link related classes, traits and interfaces together. It will then keep this "compiled" blob of runnable code — that is: code usable by the PHP interpreter — in memory.&lt;/p&gt;

&lt;p&gt;When a request arrives at the server, it can now use parts of the codebase that were already loaded in memory, without any overhead.&lt;/p&gt;

&lt;p&gt;So, what "parts of the codebase" are we talking about? Continue to read on &lt;a href="https://stitcher.io/blog/preloading-in-php-74"&gt;https://stitcher.io/blog/preloading-in-php-74&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>php</category>
      <category>preload</category>
    </item>
  </channel>
</rss>
