<?xml version='1.0' encoding='UTF-8'?>
<?xml-stylesheet href="https://sandfox.me/assets/xml/atom.xsl" type="text/xsl media="all"?>
<feed xml:lang="en" xmlns="http://www.w3.org/2005/Atom">
  <title>Sand Fox (Posts about PHP)</title>
  <id>https://sandfox.me/php.xml</id>
  <updated>2026-01-05T10:06:09Z</updated>
  <author>
    <name>Anton Smirnov</name>
  </author>
  <link rel="self" type="application/atom+xml" href="https://sandfox.me/php.xml"/>
  <link rel="alternate" type="text/html" href="https://sandfox.me/php.html"/>
  <generator uri="https://getnikola.com/">Nikola</generator>
  <entry>
    <title>Using PIE in Docker</title>
    <id>https://sandfox.me/php/pie-in-docker.html</id>
    <updated>2026-01-05T12:03:00+02:00</updated>
    <published>2025-10-09T20:51:00+03:00</published>
    <author>
      <name>Anton Smirnov</name>
    </author>
    <link rel="alternate" type="text/html" href="https://sandfox.me/php/pie-in-docker.html"/>
    <summary type="html">&lt;p&gt;As you may know, &lt;a class="reference external" href="https://wiki.php.net/rfc/adopt_pie_deprecate_pecl"&gt;PECL is now soft-deprecated and PIE is the recommended way to install exenetsions&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The current PHP docker images do not package PIE executable.
Luckily there is &lt;a class="reference external" href="https://github.com/php/pie/blob/1.4.x/docs/usage.md"&gt;an instruction in the doc&lt;/a&gt; that says this:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code docker"&gt;&lt;a id="rest_code_29ceeb52606a4e7fbba003622d136951-1" name="rest_code_29ceeb52606a4e7fbba003622d136951-1" href="https://sandfox.me/php/pie-in-docker.html#rest_code_29ceeb52606a4e7fbba003622d136951-1"&gt;&lt;/a&gt;&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;--from&lt;span class="o"&gt;=&lt;/span&gt;ghcr.io/php/pie:bin&lt;span class="w"&gt; &lt;/span&gt;/pie&lt;span class="w"&gt; &lt;/span&gt;/usr/bin/pie
&lt;a id="rest_code_29ceeb52606a4e7fbba003622d136951-2" name="rest_code_29ceeb52606a4e7fbba003622d136951-2" href="https://sandfox.me/php/pie-in-docker.html#rest_code_29ceeb52606a4e7fbba003622d136951-2"&gt;&lt;/a&gt;&lt;span class="k"&gt;RUN&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;pie&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;asgrim/example-pie-extension
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;It works but this solution is bad.
It will import a 6MB PIE executable as a dead weight.
Trying to find a solution to this solution, I stumbled on this blog post: &lt;a class="reference external" href="https://rabbithole.wwwdotorg.org/2021/03/02/1-avoiding-docker-add-copy-layers.html"&gt;rabbithole.wwwdotorg.org&lt;/a&gt;.
Luckily &lt;code class="docutils literal"&gt;RUN &lt;span class="pre"&gt;--mount&lt;/span&gt;&lt;/code&gt; can work with external images instead of stages and files instead of directories.
This allows us to collapse the installation into a single layer:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code docker"&gt;&lt;a id="rest_code_51b85ddbe1e5492e961e9b05a0b7108d-1" name="rest_code_51b85ddbe1e5492e961e9b05a0b7108d-1" href="https://sandfox.me/php/pie-in-docker.html#rest_code_51b85ddbe1e5492e961e9b05a0b7108d-1"&gt;&lt;/a&gt;&lt;span class="k"&gt;RUN&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;--mount&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;bind,from&lt;span class="o"&gt;=&lt;/span&gt;ghcr.io/php/pie:bin,source&lt;span class="o"&gt;=&lt;/span&gt;/pie,target&lt;span class="o"&gt;=&lt;/span&gt;/usr/local/bin/pie&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;a id="rest_code_51b85ddbe1e5492e961e9b05a0b7108d-2" name="rest_code_51b85ddbe1e5492e961e9b05a0b7108d-2" href="https://sandfox.me/php/pie-in-docker.html#rest_code_51b85ddbe1e5492e961e9b05a0b7108d-2"&gt;&lt;/a&gt;&lt;span class="w"&gt;    &lt;/span&gt;pie&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;asgrim/example-pie-extension
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This will make your final image 6MB ligher.&lt;/p&gt;</summary>
    <category term="docker" label="docker"/>
    <category term="pecl" label="pecl"/>
    <category term="pie" label="pie"/>
  </entry>
  <entry>
    <title>Peso Framework</title>
    <id>https://sandfox.me/php/peso.html</id>
    <updated>2025-07-11T06:42:00+03:00</updated>
    <published>2025-07-11T06:42:00+03:00</published>
    <author>
      <name>Anton Smirnov</name>
    </author>
    <link rel="alternate" type="text/html" href="https://sandfox.me/php/peso.html"/>
    <summary type="html">&lt;p&gt;Another thing I've been secretly building is the &lt;a class="reference external" href="https://phpeso.org"&gt;Peso Framework&lt;/a&gt;, a tool to query currency conversion rates.&lt;/p&gt;
&lt;p&gt;It started when I was pissed that &lt;code class="docutils literal"&gt;florianv/exchanger&lt;/code&gt;, a tool I was perfectly happy with previously,
got a broken release (2.8.2) got abandoned for almost a year now, and still isn't fixed as of this post.&lt;/p&gt;
&lt;p&gt;Peso consists of 3 components:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;A service (data source)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;An integration (data consumer)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A glue library (&lt;code class="docutils literal"&gt;peso/core&lt;/code&gt;) that contains the Service contract,
standard request/response objects, and useful tools to develop services and integrations&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A simple example:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code bash"&gt;&lt;a id="rest_code_e87af1df86794908b9c38661569fb51b-1" name="rest_code_e87af1df86794908b9c38661569fb51b-1" href="https://sandfox.me/php/peso.html#rest_code_e87af1df86794908b9c38661569fb51b-1"&gt;&lt;/a&gt;composer&lt;span class="w"&gt; &lt;/span&gt;require&lt;span class="w"&gt; &lt;/span&gt;peso/peso&lt;span class="w"&gt; &lt;/span&gt;peso/ecb-service&lt;span class="w"&gt; &lt;/span&gt;php-http/discovery&lt;span class="w"&gt; &lt;/span&gt;guzzlehttp/guzzle
&lt;/pre&gt;&lt;/div&gt;
&lt;div class="code"&gt;&lt;pre class="code php"&gt;&lt;a id="rest_code_74e3d2110e3b4c1e9ccc7acc5cefc66f-1" name="rest_code_74e3d2110e3b4c1e9ccc7acc5cefc66f-1" href="https://sandfox.me/php/peso.html#rest_code_74e3d2110e3b4c1e9ccc7acc5cefc66f-1"&gt;&lt;/a&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;
&lt;a id="rest_code_74e3d2110e3b4c1e9ccc7acc5cefc66f-2" name="rest_code_74e3d2110e3b4c1e9ccc7acc5cefc66f-2" href="https://sandfox.me/php/peso.html#rest_code_74e3d2110e3b4c1e9ccc7acc5cefc66f-2"&gt;&lt;/a&gt;
&lt;a id="rest_code_74e3d2110e3b4c1e9ccc7acc5cefc66f-3" name="rest_code_74e3d2110e3b4c1e9ccc7acc5cefc66f-3" href="https://sandfox.me/php/peso.html#rest_code_74e3d2110e3b4c1e9ccc7acc5cefc66f-3"&gt;&lt;/a&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nx"&gt;Peso\Peso\CurrencyConverter&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;a id="rest_code_74e3d2110e3b4c1e9ccc7acc5cefc66f-4" name="rest_code_74e3d2110e3b4c1e9ccc7acc5cefc66f-4" href="https://sandfox.me/php/peso.html#rest_code_74e3d2110e3b4c1e9ccc7acc5cefc66f-4"&gt;&lt;/a&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nx"&gt;Peso\Services\EuropeanCentralBankService&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;a id="rest_code_74e3d2110e3b4c1e9ccc7acc5cefc66f-5" name="rest_code_74e3d2110e3b4c1e9ccc7acc5cefc66f-5" href="https://sandfox.me/php/peso.html#rest_code_74e3d2110e3b4c1e9ccc7acc5cefc66f-5"&gt;&lt;/a&gt;
&lt;a id="rest_code_74e3d2110e3b4c1e9ccc7acc5cefc66f-6" name="rest_code_74e3d2110e3b4c1e9ccc7acc5cefc66f-6" href="https://sandfox.me/php/peso.html#rest_code_74e3d2110e3b4c1e9ccc7acc5cefc66f-6"&gt;&lt;/a&gt;&lt;span class="k"&gt;require&lt;/span&gt; &lt;span class="no"&gt;__DIR__&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="s1"&gt;'/vendor/autoload.php'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;a id="rest_code_74e3d2110e3b4c1e9ccc7acc5cefc66f-7" name="rest_code_74e3d2110e3b4c1e9ccc7acc5cefc66f-7" href="https://sandfox.me/php/peso.html#rest_code_74e3d2110e3b4c1e9ccc7acc5cefc66f-7"&gt;&lt;/a&gt;
&lt;a id="rest_code_74e3d2110e3b4c1e9ccc7acc5cefc66f-8" name="rest_code_74e3d2110e3b4c1e9ccc7acc5cefc66f-8" href="https://sandfox.me/php/peso.html#rest_code_74e3d2110e3b4c1e9ccc7acc5cefc66f-8"&gt;&lt;/a&gt;&lt;span class="c1"&gt;// caching omitted for simplicity&lt;/span&gt;
&lt;a id="rest_code_74e3d2110e3b4c1e9ccc7acc5cefc66f-9" name="rest_code_74e3d2110e3b4c1e9ccc7acc5cefc66f-9" href="https://sandfox.me/php/peso.html#rest_code_74e3d2110e3b4c1e9ccc7acc5cefc66f-9"&gt;&lt;/a&gt;&lt;span class="nv"&gt;$peso&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;CurrencyConverter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;EuropeanCentralBankService&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;a id="rest_code_74e3d2110e3b4c1e9ccc7acc5cefc66f-10" name="rest_code_74e3d2110e3b4c1e9ccc7acc5cefc66f-10" href="https://sandfox.me/php/peso.html#rest_code_74e3d2110e3b4c1e9ccc7acc5cefc66f-10"&gt;&lt;/a&gt;
&lt;a id="rest_code_74e3d2110e3b4c1e9ccc7acc5cefc66f-11" name="rest_code_74e3d2110e3b4c1e9ccc7acc5cefc66f-11" href="https://sandfox.me/php/peso.html#rest_code_74e3d2110e3b4c1e9ccc7acc5cefc66f-11"&gt;&lt;/a&gt;&lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$peso&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;getHistoricalExchangeRate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;a id="rest_code_74e3d2110e3b4c1e9ccc7acc5cefc66f-12" name="rest_code_74e3d2110e3b4c1e9ccc7acc5cefc66f-12" href="https://sandfox.me/php/peso.html#rest_code_74e3d2110e3b4c1e9ccc7acc5cefc66f-12"&gt;&lt;/a&gt;    &lt;span class="s1"&gt;'EUR'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// base&lt;/span&gt;
&lt;a id="rest_code_74e3d2110e3b4c1e9ccc7acc5cefc66f-13" name="rest_code_74e3d2110e3b4c1e9ccc7acc5cefc66f-13" href="https://sandfox.me/php/peso.html#rest_code_74e3d2110e3b4c1e9ccc7acc5cefc66f-13"&gt;&lt;/a&gt;    &lt;span class="s1"&gt;'PHP'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// quote&lt;/span&gt;
&lt;a id="rest_code_74e3d2110e3b4c1e9ccc7acc5cefc66f-14" name="rest_code_74e3d2110e3b4c1e9ccc7acc5cefc66f-14" href="https://sandfox.me/php/peso.html#rest_code_74e3d2110e3b4c1e9ccc7acc5cefc66f-14"&gt;&lt;/a&gt;    &lt;span class="s1"&gt;'2025-06-13'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// date (Y-m-d string or DateTime or arokettu/date Date)&lt;/span&gt;
&lt;a id="rest_code_74e3d2110e3b4c1e9ccc7acc5cefc66f-15" name="rest_code_74e3d2110e3b4c1e9ccc7acc5cefc66f-15" href="https://sandfox.me/php/peso.html#rest_code_74e3d2110e3b4c1e9ccc7acc5cefc66f-15"&gt;&lt;/a&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nx"&gt;PHP_EOL&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// '64.706'&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Advantages over the Exchanger:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Caching moved to the Service side making it more effective&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;No way for a service to mistake a historical exchange rate request with a current exchange rate request&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Also currency conversion requests for services that support them&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Ability to add new request types without breaking the backward compatibility&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Services reside in their own separate packages
so the main package is not a huge garbage dump of dead or unsupported services like Cryptonator&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;</summary>
    <category term="currency-conversion" label="currency conversion"/>
    <category term="peso" label="peso"/>
  </entry>
  <entry>
    <title>JSON5 Tools</title>
    <id>https://sandfox.me/php/json5-tools.html</id>
    <updated>2025-07-11T05:46:00+03:00</updated>
    <published>2025-07-11T05:46:00+03:00</published>
    <author>
      <name>Anton Smirnov</name>
    </author>
    <link rel="alternate" type="text/html" href="https://sandfox.me/php/json5-tools.html"/>
    <summary type="html">&lt;p&gt;Presenting a couple of JSON5 tools I built.&lt;/p&gt;
&lt;p&gt;The first one was done a year ago, a docker CLI image to convert JSON5 to JSON:
&lt;a class="reference external" href="https://hub.docker.com/r/arokettu/json5-to-json"&gt;arokettu/json5-to-json&lt;/a&gt;.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code bash"&gt;&lt;a id="rest_code_c6feccbd8aca4ef0b073eec56ac3445c-1" name="rest_code_c6feccbd8aca4ef0b073eec56ac3445c-1" href="https://sandfox.me/php/json5-tools.html#rest_code_c6feccbd8aca4ef0b073eec56ac3445c-1"&gt;&lt;/a&gt;$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"{ hello: 'world' }"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;docker&lt;span class="w"&gt; &lt;/span&gt;run&lt;span class="w"&gt; &lt;/span&gt;-i&lt;span class="w"&gt; &lt;/span&gt;--rm&lt;span class="w"&gt; &lt;/span&gt;arokettu/json5-to-json
&lt;a id="rest_code_c6feccbd8aca4ef0b073eec56ac3445c-2" name="rest_code_c6feccbd8aca4ef0b073eec56ac3445c-2" href="https://sandfox.me/php/json5-tools.html#rest_code_c6feccbd8aca4ef0b073eec56ac3445c-2"&gt;&lt;/a&gt;&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"hello"&lt;/span&gt;:&lt;span class="s2"&gt;"world"&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;A simple tool to convert your configs on the build phase without installing anything into your images.&lt;/p&gt;
&lt;p&gt;The second one is a builder/serializer that is aimed at creating pretty configs in PHP:
&lt;a class="reference external" href="https://packagist.org/packages/arokettu/json5-builder"&gt;arokettu/json5-builder&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;While it can just serialize some data into JSON5,
the goal is to create nice configs with comments and custom formatting.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code php"&gt;&lt;a id="rest_code_f7b14189ca084df3ab5c3454a06d57fc-1" name="rest_code_f7b14189ca084df3ab5c3454a06d57fc-1" href="https://sandfox.me/php/json5-tools.html#rest_code_f7b14189ca084df3ab5c3454a06d57fc-1"&gt;&lt;/a&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;
&lt;a id="rest_code_f7b14189ca084df3ab5c3454a06d57fc-2" name="rest_code_f7b14189ca084df3ab5c3454a06d57fc-2" href="https://sandfox.me/php/json5-tools.html#rest_code_f7b14189ca084df3ab5c3454a06d57fc-2"&gt;&lt;/a&gt;
&lt;a id="rest_code_f7b14189ca084df3ab5c3454a06d57fc-3" name="rest_code_f7b14189ca084df3ab5c3454a06d57fc-3" href="https://sandfox.me/php/json5-tools.html#rest_code_f7b14189ca084df3ab5c3454a06d57fc-3"&gt;&lt;/a&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nx"&gt;Arokettu\Json5\Json5Encoder&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;a id="rest_code_f7b14189ca084df3ab5c3454a06d57fc-4" name="rest_code_f7b14189ca084df3ab5c3454a06d57fc-4" href="https://sandfox.me/php/json5-tools.html#rest_code_f7b14189ca084df3ab5c3454a06d57fc-4"&gt;&lt;/a&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nx"&gt;Arokettu\Json5\Values\CommentDecorator&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;a id="rest_code_f7b14189ca084df3ab5c3454a06d57fc-5" name="rest_code_f7b14189ca084df3ab5c3454a06d57fc-5" href="https://sandfox.me/php/json5-tools.html#rest_code_f7b14189ca084df3ab5c3454a06d57fc-5"&gt;&lt;/a&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nx"&gt;Arokettu\Json5\Values\HexInteger&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;a id="rest_code_f7b14189ca084df3ab5c3454a06d57fc-6" name="rest_code_f7b14189ca084df3ab5c3454a06d57fc-6" href="https://sandfox.me/php/json5-tools.html#rest_code_f7b14189ca084df3ab5c3454a06d57fc-6"&gt;&lt;/a&gt;
&lt;a id="rest_code_f7b14189ca084df3ab5c3454a06d57fc-7" name="rest_code_f7b14189ca084df3ab5c3454a06d57fc-7" href="https://sandfox.me/php/json5-tools.html#rest_code_f7b14189ca084df3ab5c3454a06d57fc-7"&gt;&lt;/a&gt;&lt;span class="k"&gt;require&lt;/span&gt; &lt;span class="no"&gt;__DIR__&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="s1"&gt;'/../vendor/autoload.php'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;a id="rest_code_f7b14189ca084df3ab5c3454a06d57fc-8" name="rest_code_f7b14189ca084df3ab5c3454a06d57fc-8" href="https://sandfox.me/php/json5-tools.html#rest_code_f7b14189ca084df3ab5c3454a06d57fc-8"&gt;&lt;/a&gt;
&lt;a id="rest_code_f7b14189ca084df3ab5c3454a06d57fc-9" name="rest_code_f7b14189ca084df3ab5c3454a06d57fc-9" href="https://sandfox.me/php/json5-tools.html#rest_code_f7b14189ca084df3ab5c3454a06d57fc-9"&gt;&lt;/a&gt;&lt;span class="nv"&gt;$config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;CommentDecorator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;a id="rest_code_f7b14189ca084df3ab5c3454a06d57fc-10" name="rest_code_f7b14189ca084df3ab5c3454a06d57fc-10" href="https://sandfox.me/php/json5-tools.html#rest_code_f7b14189ca084df3ab5c3454a06d57fc-10"&gt;&lt;/a&gt;    &lt;span class="p"&gt;[&lt;/span&gt;
&lt;a id="rest_code_f7b14189ca084df3ab5c3454a06d57fc-11" name="rest_code_f7b14189ca084df3ab5c3454a06d57fc-11" href="https://sandfox.me/php/json5-tools.html#rest_code_f7b14189ca084df3ab5c3454a06d57fc-11"&gt;&lt;/a&gt;        &lt;span class="s1"&gt;'bareKeys'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'&amp;lt;- Look, no quotes!'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;a id="rest_code_f7b14189ca084df3ab5c3454a06d57fc-12" name="rest_code_f7b14189ca084df3ab5c3454a06d57fc-12" href="https://sandfox.me/php/json5-tools.html#rest_code_f7b14189ca084df3ab5c3454a06d57fc-12"&gt;&lt;/a&gt;        &lt;span class="s1"&gt;'value'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;CommentDecorator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;a id="rest_code_f7b14189ca084df3ab5c3454a06d57fc-13" name="rest_code_f7b14189ca084df3ab5c3454a06d57fc-13" href="https://sandfox.me/php/json5-tools.html#rest_code_f7b14189ca084df3ab5c3454a06d57fc-13"&gt;&lt;/a&gt;            &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;HexInteger&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mh"&gt;0xFFF&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;a id="rest_code_f7b14189ca084df3ab5c3454a06d57fc-14" name="rest_code_f7b14189ca084df3ab5c3454a06d57fc-14" href="https://sandfox.me/php/json5-tools.html#rest_code_f7b14189ca084df3ab5c3454a06d57fc-14"&gt;&lt;/a&gt;            &lt;span class="nx"&gt;commentAfter&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'This is a very important value'&lt;/span&gt;
&lt;a id="rest_code_f7b14189ca084df3ab5c3454a06d57fc-15" name="rest_code_f7b14189ca084df3ab5c3454a06d57fc-15" href="https://sandfox.me/php/json5-tools.html#rest_code_f7b14189ca084df3ab5c3454a06d57fc-15"&gt;&lt;/a&gt;         &lt;span class="p"&gt;),&lt;/span&gt;
&lt;a id="rest_code_f7b14189ca084df3ab5c3454a06d57fc-16" name="rest_code_f7b14189ca084df3ab5c3454a06d57fc-16" href="https://sandfox.me/php/json5-tools.html#rest_code_f7b14189ca084df3ab5c3454a06d57fc-16"&gt;&lt;/a&gt;        &lt;span class="s1"&gt;'notAvailableInJSON'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;NAN&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;INF&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;a id="rest_code_f7b14189ca084df3ab5c3454a06d57fc-17" name="rest_code_f7b14189ca084df3ab5c3454a06d57fc-17" href="https://sandfox.me/php/json5-tools.html#rest_code_f7b14189ca084df3ab5c3454a06d57fc-17"&gt;&lt;/a&gt;        &lt;span class="s1"&gt;'end'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'auto trailing comma -&amp;gt;'&lt;/span&gt;
&lt;a id="rest_code_f7b14189ca084df3ab5c3454a06d57fc-18" name="rest_code_f7b14189ca084df3ab5c3454a06d57fc-18" href="https://sandfox.me/php/json5-tools.html#rest_code_f7b14189ca084df3ab5c3454a06d57fc-18"&gt;&lt;/a&gt;    &lt;span class="p"&gt;],&lt;/span&gt;
&lt;a id="rest_code_f7b14189ca084df3ab5c3454a06d57fc-19" name="rest_code_f7b14189ca084df3ab5c3454a06d57fc-19" href="https://sandfox.me/php/json5-tools.html#rest_code_f7b14189ca084df3ab5c3454a06d57fc-19"&gt;&lt;/a&gt;    &lt;span class="nx"&gt;commentBefore&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'This is my cool JSON5 config!'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;a id="rest_code_f7b14189ca084df3ab5c3454a06d57fc-20" name="rest_code_f7b14189ca084df3ab5c3454a06d57fc-20" href="https://sandfox.me/php/json5-tools.html#rest_code_f7b14189ca084df3ab5c3454a06d57fc-20"&gt;&lt;/a&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;a id="rest_code_f7b14189ca084df3ab5c3454a06d57fc-21" name="rest_code_f7b14189ca084df3ab5c3454a06d57fc-21" href="https://sandfox.me/php/json5-tools.html#rest_code_f7b14189ca084df3ab5c3454a06d57fc-21"&gt;&lt;/a&gt;
&lt;a id="rest_code_f7b14189ca084df3ab5c3454a06d57fc-22" name="rest_code_f7b14189ca084df3ab5c3454a06d57fc-22" href="https://sandfox.me/php/json5-tools.html#rest_code_f7b14189ca084df3ab5c3454a06d57fc-22"&gt;&lt;/a&gt;&lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="nx"&gt;Json5Encoder&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="na"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$config&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;div class="code"&gt;&lt;pre class="code js"&gt;&lt;a id="rest_code_80782c7f27d6453da4531df6477dd67b-1" name="rest_code_80782c7f27d6453da4531df6477dd67b-1" href="https://sandfox.me/php/json5-tools.html#rest_code_80782c7f27d6453da4531df6477dd67b-1"&gt;&lt;/a&gt;&lt;span class="c1"&gt;// This is my cool JSON5 config!&lt;/span&gt;
&lt;a id="rest_code_80782c7f27d6453da4531df6477dd67b-2" name="rest_code_80782c7f27d6453da4531df6477dd67b-2" href="https://sandfox.me/php/json5-tools.html#rest_code_80782c7f27d6453da4531df6477dd67b-2"&gt;&lt;/a&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;a id="rest_code_80782c7f27d6453da4531df6477dd67b-3" name="rest_code_80782c7f27d6453da4531df6477dd67b-3" href="https://sandfox.me/php/json5-tools.html#rest_code_80782c7f27d6453da4531df6477dd67b-3"&gt;&lt;/a&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;bareKeys&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;- Look, no quotes!"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;a id="rest_code_80782c7f27d6453da4531df6477dd67b-4" name="rest_code_80782c7f27d6453da4531df6477dd67b-4" href="https://sandfox.me/php/json5-tools.html#rest_code_80782c7f27d6453da4531df6477dd67b-4"&gt;&lt;/a&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0xFFF&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// This is a very important value&lt;/span&gt;
&lt;a id="rest_code_80782c7f27d6453da4531df6477dd67b-5" name="rest_code_80782c7f27d6453da4531df6477dd67b-5" href="https://sandfox.me/php/json5-tools.html#rest_code_80782c7f27d6453da4531df6477dd67b-5"&gt;&lt;/a&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;notAvailableInJSON&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
&lt;a id="rest_code_80782c7f27d6453da4531df6477dd67b-6" name="rest_code_80782c7f27d6453da4531df6477dd67b-6" href="https://sandfox.me/php/json5-tools.html#rest_code_80782c7f27d6453da4531df6477dd67b-6"&gt;&lt;/a&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kc"&gt;NaN&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;a id="rest_code_80782c7f27d6453da4531df6477dd67b-7" name="rest_code_80782c7f27d6453da4531df6477dd67b-7" href="https://sandfox.me/php/json5-tools.html#rest_code_80782c7f27d6453da4531df6477dd67b-7"&gt;&lt;/a&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kc"&gt;Infinity&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;a id="rest_code_80782c7f27d6453da4531df6477dd67b-8" name="rest_code_80782c7f27d6453da4531df6477dd67b-8" href="https://sandfox.me/php/json5-tools.html#rest_code_80782c7f27d6453da4531df6477dd67b-8"&gt;&lt;/a&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;a id="rest_code_80782c7f27d6453da4531df6477dd67b-9" name="rest_code_80782c7f27d6453da4531df6477dd67b-9" href="https://sandfox.me/php/json5-tools.html#rest_code_80782c7f27d6453da4531df6477dd67b-9"&gt;&lt;/a&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;end&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"auto trailing comma -&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;a id="rest_code_80782c7f27d6453da4531df6477dd67b-10" name="rest_code_80782c7f27d6453da4531df6477dd67b-10" href="https://sandfox.me/php/json5-tools.html#rest_code_80782c7f27d6453da4531df6477dd67b-10"&gt;&lt;/a&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;</summary>
    <category term="config" label="config"/>
    <category term="docker" label="docker"/>
    <category term="json5" label="json5"/>
  </entry>
  <entry>
    <title>Do Not Use Exception Class Directly</title>
    <id>https://sandfox.me/php/do-not-use-exception.html</id>
    <updated>2025-10-09T20:57:00+03:00</updated>
    <published>2024-11-18T23:08:00+02:00</published>
    <author>
      <name>Anton Smirnov</name>
    </author>
    <link rel="alternate" type="text/html" href="https://sandfox.me/php/do-not-use-exception.html"/>
    <summary type="html">&lt;aside class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;This post is slightly outdated and needs to be revised to align with PHP's internal policies.
&lt;a class="reference external" href="https://github.com/php/policies/blob/main/coding-standards-and-naming.rst#throwables"&gt;https://github.com/php/policies/blob/main/coding-standards-and-naming.rst#throwables&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;While they are aimed at extensions, userspace libraries should benefit from them too.&lt;/p&gt;
&lt;/aside&gt;
&lt;p&gt;It is a bad practice to use the &lt;code class="docutils literal"&gt;Exception&lt;/code&gt; class directly in PHP.
That means 2 points:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Do not throw &lt;code class="docutils literal"&gt;Exception&lt;/code&gt; directly&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Do not catch &lt;code class="docutils literal"&gt;Exception&lt;/code&gt; directly&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Subclassing &lt;code class="docutils literal"&gt;Exception&lt;/code&gt; is not a direct use in this context.&lt;/p&gt;
&lt;section id="do-not-throw-exception"&gt;
&lt;h2&gt;Do not throw &lt;code class="docutils literal"&gt;Exception&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;There are a lot of specific &lt;code class="docutils literal"&gt;Exception&lt;/code&gt; descendants in PHP.
&lt;a class="reference external" href="https://www.php.net/manual/en/spl.exceptions.php"&gt;See documentation for the full list.&lt;/a&gt;
It's not necessary to use and remember all of them, many have unclear use cases,
but at very least you should separate your exceptions into &lt;code class="docutils literal"&gt;RuntimeException&lt;/code&gt; and &lt;code class="docutils literal"&gt;LogicException&lt;/code&gt;.
As the doc says, &lt;code class="docutils literal"&gt;LogicException&lt;/code&gt; means code misuse.
Throw &lt;code class="docutils literal"&gt;LogicException&lt;/code&gt; in cases when the upstream must be fixed because it uses your code incorrectly.
Throw &lt;code class="docutils literal"&gt;RuntimeException&lt;/code&gt; in cases that are not predictable by the upstream,
like service failures or invalid user input.&lt;/p&gt;
&lt;p&gt;In case you use exceptions for flow control, you need your own custom exceptions anyway.
In this case you can extend the base &lt;code class="docutils literal"&gt;Exception&lt;/code&gt;, extending &lt;code class="docutils literal"&gt;Exception&lt;/code&gt; directly is not a sin,
especially if your exceptions are not error conditions.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="do-not-catch-exception"&gt;
&lt;h2&gt;Do not catch &lt;code class="docutils literal"&gt;Exception&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Assuming you follow the previous point, there is no need to catch &lt;code class="docutils literal"&gt;Exception&lt;/code&gt;'s.&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;If you don't guard against a specific situation, catch all &lt;code class="docutils literal"&gt;RuntimeException&lt;/code&gt;'s.
&lt;code class="docutils literal"&gt;LogicException&lt;/code&gt;'s should go to your logger.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In a global error handler that writes your logs, you need to catch Errors too,
so you need to go even further and catch &lt;code class="docutils literal"&gt;Throwable&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If you use exceptions for flow control (please don't haha) you already catching your own exceptions,
and if you follow the previous point,
they are already separated from actual error conditions and won't be caught mistakenly by a wrong level.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Notable exceptions to the rule:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;You use PHP below 7.0 and don't have &lt;code class="docutils literal"&gt;Throwable&lt;/code&gt;.
Well, it's 2024 already so this is another call for you to upgrade.
Otherwise assume point 2 allows you to catch a base &lt;code class="docutils literal"&gt;Exception&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You use a library that throws plain &lt;code class="docutils literal"&gt;Exception&lt;/code&gt; instances.
Well, bad for you, but maybe it's a good idea to report this thing as a problem.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;</summary>
    <category term="good-practices" label="good practices"/>
    <category term="opinion" label="opinion"/>
  </entry>
  <entry>
    <title>De-hybridize Torrent</title>
    <id>https://sandfox.me/php/torrent-dehybridization.html</id>
    <updated>2023-11-10T11:08:00+02:00</updated>
    <published>2023-11-10T11:08:00+02:00</published>
    <author>
      <name>Anton Smirnov</name>
    </author>
    <link rel="alternate" type="text/html" href="https://sandfox.me/php/torrent-dehybridization.html"/>
    <summary type="html">&lt;p&gt;A feature that may be desired for some anti-V2 trackers.
While I would like to see the torrent community going the other way around,
some trackers choose not to allow version 2 torrents and sometimes even hybrids.&lt;/p&gt;
&lt;p&gt;The &lt;a class="reference external" href="https://sandfox.dev/php/torrent-file.html"&gt;torrent file library&lt;/a&gt; now allows cleaning unnecessary or undesired metadata versions from a torrent file.&lt;/p&gt;
&lt;aside class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;The process will change the infohash value so it's not for a casual case.
The trackers that process torrent files on their side, like setting the private flag,
a process that changes infohashes anyway, would benefit most from using this feature.&lt;/p&gt;
&lt;/aside&gt;
&lt;p&gt;The intended use and the primary future scope is actually the other way around:
the ability to remove version 1 metadata to make use of easy mutability of version 2 torrents
to add or remove files in existing torrent structures.&lt;/p&gt;
&lt;aside class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;Mutability of torrent files does not mean that you can replace data in an existing torrent.
Updated torrents will have different infohash values and be considered a different torrent in the network.
But often creation of such updates without having any original files downloaded can be very beneficial.&lt;/p&gt;
&lt;/aside&gt;</summary>
    <category term="libraries" label="libraries"/>
    <category term="torrent" label="torrent"/>
    <category term="torrent-file" label="torrent file"/>
  </entry>
  <entry>
    <title>PHP Requirements on Packagist</title>
    <id>https://sandfox.me/php/choosing-php-version-packagist.html</id>
    <updated>2023-10-29T01:28:00+03:00</updated>
    <published>2023-10-29T01:28:00+03:00</published>
    <author>
      <name>Anton Smirnov</name>
    </author>
    <link rel="alternate" type="text/html" href="https://sandfox.me/php/choosing-php-version-packagist.html"/>
    <summary type="html">&lt;div&gt;&lt;p&gt;A followup for &lt;a class="reference external" href="https://sandfox.me/php/choosing-php-version.html"&gt;the previous post&lt;/a&gt;: the minimum required PHP versions in packages on the &lt;a class="reference external" href="https://packagist.org"&gt;Packagist&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://sandfox.me/php/choosing-php-version-packagist.html"&gt;Read more…&lt;/a&gt; (1 min remaining to read)&lt;/p&gt;&lt;/div&gt;</summary>
    <category term="libraries" label="libraries"/>
    <category term="packagist" label="packagist"/>
  </entry>
  <entry>
    <title>How to Choose a Minimum PHP Requirement</title>
    <id>https://sandfox.me/php/choosing-php-version.html</id>
    <updated>2023-12-05T18:13:00+02:00</updated>
    <published>2023-10-29T00:29:00+03:00</published>
    <author>
      <name>Anton Smirnov</name>
    </author>
    <link rel="alternate" type="text/html" href="https://sandfox.me/php/choosing-php-version.html"/>
    <summary type="html">&lt;div&gt;&lt;p&gt;As a library developer I often face a problem what should be a minimum PHP requirement.
Here are some of my principles.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://sandfox.me/php/choosing-php-version.html"&gt;Read more…&lt;/a&gt; (4 min remaining to read)&lt;/p&gt;&lt;/div&gt;</summary>
    <category term="libraries" label="libraries"/>
    <category term="packagist" label="packagist"/>
  </entry>
  <entry>
    <title>UUID Library (and ULID to UUID migration)</title>
    <id>https://sandfox.me/php/uuid.html</id>
    <updated>2023-07-14T05:48:00+03:00</updated>
    <published>2023-07-14T05:48:00+03:00</published>
    <author>
      <name>Anton Smirnov</name>
    </author>
    <link rel="alternate" type="text/html" href="https://sandfox.me/php/uuid.html"/>
    <summary type="html">&lt;p&gt;I created &lt;a class="reference external" href="https://sandfox.dev/php/uuid.html"&gt;a UUID and ULID library&lt;/a&gt; with &lt;a class="reference external" href="https://sandfox.dev/php/uuid/doctrine.html"&gt;Doctrine support&lt;/a&gt;.
Well, who didn't :D&lt;/p&gt;
&lt;p&gt;The main scenario for myself was a possible migration for a project from ULIDs to UUIDs
since UUIDs got a little bit of support in MySQL 8.&lt;/p&gt;
&lt;aside class="admonition warning"&gt;
&lt;p class="admonition-title"&gt;Warning&lt;/p&gt;
&lt;p&gt;The conversion is lossy (of a few bits), if you want to do the same, first run a simulation
that you won't get collisions. (You shouldn't if the generation was random enough but who knows)&lt;/p&gt;
&lt;/aside&gt;
&lt;p&gt;Example code:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code php"&gt;&lt;a id="rest_code_dabea84a0180415393c677e49f3faa6a-1" name="rest_code_dabea84a0180415393c677e49f3faa6a-1" href="https://sandfox.me/php/uuid.html#rest_code_dabea84a0180415393c677e49f3faa6a-1"&gt;&lt;/a&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;
&lt;a id="rest_code_dabea84a0180415393c677e49f3faa6a-2" name="rest_code_dabea84a0180415393c677e49f3faa6a-2" href="https://sandfox.me/php/uuid.html#rest_code_dabea84a0180415393c677e49f3faa6a-2"&gt;&lt;/a&gt;
&lt;a id="rest_code_dabea84a0180415393c677e49f3faa6a-3" name="rest_code_dabea84a0180415393c677e49f3faa6a-3" href="https://sandfox.me/php/uuid.html#rest_code_dabea84a0180415393c677e49f3faa6a-3"&gt;&lt;/a&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nx"&gt;Arokettu\Uuid\UuidParser&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;a id="rest_code_dabea84a0180415393c677e49f3faa6a-4" name="rest_code_dabea84a0180415393c677e49f3faa6a-4" href="https://sandfox.me/php/uuid.html#rest_code_dabea84a0180415393c677e49f3faa6a-4"&gt;&lt;/a&gt;
&lt;a id="rest_code_dabea84a0180415393c677e49f3faa6a-5" name="rest_code_dabea84a0180415393c677e49f3faa6a-5" href="https://sandfox.me/php/uuid.html#rest_code_dabea84a0180415393c677e49f3faa6a-5"&gt;&lt;/a&gt;&lt;span class="c1"&gt;// Just a random ULID&lt;/span&gt;
&lt;a id="rest_code_dabea84a0180415393c677e49f3faa6a-6" name="rest_code_dabea84a0180415393c677e49f3faa6a-6" href="https://sandfox.me/php/uuid.html#rest_code_dabea84a0180415393c677e49f3faa6a-6"&gt;&lt;/a&gt;&lt;span class="nv"&gt;$ulid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;UuidParser&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="na"&gt;fromBase32&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'01H44RDYXJPFCF895N3BBXCZRC'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;a id="rest_code_dabea84a0180415393c677e49f3faa6a-7" name="rest_code_dabea84a0180415393c677e49f3faa6a-7" href="https://sandfox.me/php/uuid.html#rest_code_dabea84a0180415393c677e49f3faa6a-7"&gt;&lt;/a&gt;&lt;span class="nb"&gt;var_dump&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$ulid&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;isUuidV7Compatible&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt; &lt;span class="c1"&gt;// false&lt;/span&gt;
&lt;a id="rest_code_dabea84a0180415393c677e49f3faa6a-8" name="rest_code_dabea84a0180415393c677e49f3faa6a-8" href="https://sandfox.me/php/uuid.html#rest_code_dabea84a0180415393c677e49f3faa6a-8"&gt;&lt;/a&gt;&lt;span class="c1"&gt;// UnexpectedValueException: This ULID cannot be converted to UUID v7 losslessly&lt;/span&gt;
&lt;a id="rest_code_dabea84a0180415393c677e49f3faa6a-9" name="rest_code_dabea84a0180415393c677e49f3faa6a-9" href="https://sandfox.me/php/uuid.html#rest_code_dabea84a0180415393c677e49f3faa6a-9"&gt;&lt;/a&gt;&lt;span class="c1"&gt;// $uuid = $ulid-&amp;gt;toUuidV7();&lt;/span&gt;
&lt;a id="rest_code_dabea84a0180415393c677e49f3faa6a-10" name="rest_code_dabea84a0180415393c677e49f3faa6a-10" href="https://sandfox.me/php/uuid.html#rest_code_dabea84a0180415393c677e49f3faa6a-10"&gt;&lt;/a&gt;&lt;span class="nv"&gt;$uuid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$ulid&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;toUuidV7&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;lossy&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;a id="rest_code_dabea84a0180415393c677e49f3faa6a-11" name="rest_code_dabea84a0180415393c677e49f3faa6a-11" href="https://sandfox.me/php/uuid.html#rest_code_dabea84a0180415393c677e49f3faa6a-11"&gt;&lt;/a&gt;&lt;span class="c1"&gt;// note digit 13 becoming '7' and digit 17 moving into [89ab] range&lt;/span&gt;
&lt;a id="rest_code_dabea84a0180415393c677e49f3faa6a-12" name="rest_code_dabea84a0180415393c677e49f3faa6a-12" href="https://sandfox.me/php/uuid.html#rest_code_dabea84a0180415393c677e49f3faa6a-12"&gt;&lt;/a&gt;&lt;span class="nb"&gt;var_dump&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$uuid&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;    &lt;span class="c1"&gt;// 01890986-fbb2-73d8-b424-b51ad7d67f0c&lt;/span&gt;
&lt;a id="rest_code_dabea84a0180415393c677e49f3faa6a-13" name="rest_code_dabea84a0180415393c677e49f3faa6a-13" href="https://sandfox.me/php/uuid.html#rest_code_dabea84a0180415393c677e49f3faa6a-13"&gt;&lt;/a&gt;&lt;span class="nb"&gt;var_dump&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$ulid&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;toRfc4122&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;   &lt;span class="c1"&gt;// 01890986-fbb2-b3d8-f424-b51ad7d67f0c&lt;/span&gt;
&lt;a id="rest_code_dabea84a0180415393c677e49f3faa6a-14" name="rest_code_dabea84a0180415393c677e49f3faa6a-14" href="https://sandfox.me/php/uuid.html#rest_code_dabea84a0180415393c677e49f3faa6a-14"&gt;&lt;/a&gt;&lt;span class="nb"&gt;var_dump&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$uuid&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;toBase32&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;    &lt;span class="c1"&gt;// 01H44RDYXJEFCB895N3BBXCZRC&lt;/span&gt;
&lt;a id="rest_code_dabea84a0180415393c677e49f3faa6a-15" name="rest_code_dabea84a0180415393c677e49f3faa6a-15" href="https://sandfox.me/php/uuid.html#rest_code_dabea84a0180415393c677e49f3faa6a-15"&gt;&lt;/a&gt;&lt;span class="nb"&gt;var_dump&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$ulid&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;    &lt;span class="c1"&gt;// 01H44RDYXJPFCF895N3BBXCZRC&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;</summary>
    <category term="ulid" label="ulid"/>
    <category term="uuid" label="uuid"/>
  </entry>
  <entry>
    <title>March Packages on Packagist</title>
    <id>https://sandfox.me/php/arithmetics-clock-torrent.html</id>
    <updated>2023-03-31T04:05:00+03:00</updated>
    <published>2023-03-31T04:05:00+03:00</published>
    <author>
      <name>Anton Smirnov</name>
    </author>
    <link rel="alternate" type="text/html" href="https://sandfox.me/php/arithmetics-clock-torrent.html"/>
    <summary type="html">&lt;p&gt;I'm continuing to publish useless nih junk on the Packagist:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://packagist.org/packages/arokettu/arithmetic-parser"&gt;arokettu/arithmetic-parser&lt;/a&gt;:
A very configurable arithmetic parser and calculator.
You can define your own set of functions and operators.
You can even disable multiplication if you want to!&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://packagist.org/packages/arokettu/clock"&gt;arokettu/clock&lt;/a&gt;:
A set of PSR-20 clock implementations.
Everyone has these implemented so why not me? :D&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://packagist.org/packages/arokettu/system-clock"&gt;arokettu/system-clock&lt;/a&gt;:
All these PSR-20 clock packages usually contain a ton of clocks for testing purposes but
most of the production code needs only &lt;code class="docutils literal"&gt;new &lt;span class="pre"&gt;DateTimeImmutable('now')&lt;/span&gt;&lt;/code&gt;
so I extracted SystemClock to a separate package that has only SystemClock.php and composer.json
for the smallest possible package (if you don't count uglifying it js-like)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://packagist.org/packages/arokettu/kilo-mega"&gt;arokettu/kilo-mega&lt;/a&gt;:
This one was actually released on February but I've forgot to write about it.
It's a simple formatter for metric prefixes.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code php"&gt;&lt;a id="rest_code_f4b87a90072349b28b4e2a22794b72f0-1" name="rest_code_f4b87a90072349b28b4e2a22794b72f0-1" href="https://sandfox.me/php/arithmetics-clock-torrent.html#rest_code_f4b87a90072349b28b4e2a22794b72f0-1"&gt;&lt;/a&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;
&lt;a id="rest_code_f4b87a90072349b28b4e2a22794b72f0-2" name="rest_code_f4b87a90072349b28b4e2a22794b72f0-2" href="https://sandfox.me/php/arithmetics-clock-torrent.html#rest_code_f4b87a90072349b28b4e2a22794b72f0-2"&gt;&lt;/a&gt;&lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="nx"&gt;format_metric&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;suffix&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'W'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 1.0 kW&lt;/span&gt;
&lt;a id="rest_code_f4b87a90072349b28b4e2a22794b72f0-3" name="rest_code_f4b87a90072349b28b4e2a22794b72f0-3" href="https://sandfox.me/php/arithmetics-clock-torrent.html#rest_code_f4b87a90072349b28b4e2a22794b72f0-3"&gt;&lt;/a&gt;&lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="nx"&gt;format_bytes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1234&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 1.2 KiB&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Also a new significant release:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://packagist.org/packages/arokettu/torrent-file"&gt;arokettu/torrent-file&lt;/a&gt;:
Torrent file class got file listing classes for v1 and v2 metadata in 5.0 release.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;</summary>
    <category term="bittorrent" label="bittorrent"/>
    <category term="clock" label="clock"/>
    <category term="libraries" label="libraries"/>
    <category term="math" label="math"/>
    <category term="packagist" label="packagist"/>
    <category term="psr" label="psr"/>
  </entry>
  <entry>
    <title>Moving packages to Arokettu</title>
    <id>https://sandfox.me/php/arokettu-namespace.html</id>
    <updated>2023-01-15T02:58:00+02:00</updated>
    <published>2023-01-15T02:58:00+02:00</published>
    <author>
      <name>Anton Smirnov</name>
    </author>
    <link rel="alternate" type="text/html" href="https://sandfox.me/php/arokettu-namespace.html"/>
    <summary type="html">&lt;p&gt;Just finished moving my old composer packages from &lt;code class="docutils literal"&gt;sandfoxme/*&lt;/code&gt; to &lt;code class="docutils literal"&gt;arokettu/*&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Full list:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal"&gt;&lt;span class="pre"&gt;composer-viz&lt;/span&gt;&lt;/code&gt;
(&lt;a class="reference external" href="https://packagist.org/packages/sandfoxme/composer-viz"&gt;old&lt;/a&gt;,
&lt;a class="reference external" href="https://packagist.org/packages/arokettu/composer-viz"&gt;new&lt;/a&gt;):
the only one I moved a year ago&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal"&gt;bencode&lt;/code&gt;
(&lt;a class="reference external" href="https://packagist.org/packages/sandfoxme/bencode"&gt;old&lt;/a&gt;,
&lt;a class="reference external" href="https://packagist.org/packages/arokettu/bencode"&gt;new&lt;/a&gt;)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal"&gt;monsterid&lt;/code&gt;
(&lt;a class="reference external" href="https://packagist.org/packages/sandfoxme/monsterid"&gt;old&lt;/a&gt;,
&lt;a class="reference external" href="https://packagist.org/packages/arokettu/monsterid"&gt;new&lt;/a&gt;)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal"&gt;&lt;span class="pre"&gt;phpstorm-metadata-export&lt;/span&gt;&lt;/code&gt;
(&lt;a class="reference external" href="https://packagist.org/packages/sandfoxme/phpstorm-metadata-export"&gt;old&lt;/a&gt;,
&lt;a class="reference external" href="https://packagist.org/packages/arokettu/phpstorm-metadata-export"&gt;new&lt;/a&gt;)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal"&gt;&lt;span class="pre"&gt;private-access&lt;/span&gt;&lt;/code&gt;
(&lt;a class="reference external" href="https://packagist.org/packages/sandfoxme/private-access"&gt;old&lt;/a&gt;,
&lt;a class="reference external" href="https://packagist.org/packages/arokettu/private-access"&gt;new&lt;/a&gt;)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal"&gt;&lt;span class="pre"&gt;torrent-file&lt;/span&gt;&lt;/code&gt;
(&lt;a class="reference external" href="https://packagist.org/packages/sandfoxme/torrent-file"&gt;old&lt;/a&gt;,
&lt;a class="reference external" href="https://packagist.org/packages/arokettu/torrent-file"&gt;new&lt;/a&gt;)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I tried to make the migration process as smooth as possible.
I'm sorry for the inconvenience it might have caused.&lt;/p&gt;</summary>
    <category term="libraries" label="libraries"/>
    <category term="packagist" label="packagist"/>
  </entry>
  <entry>
    <title>Installing Composer in Docker the 2020-s Way</title>
    <id>https://sandfox.me/php/install-composer-in-docker-2.html</id>
    <updated>2023-01-11T10:14:00+02:00</updated>
    <published>2023-01-11T10:14:00+02:00</published>
    <author>
      <name>Anton Smirnov</name>
    </author>
    <link rel="alternate" type="text/html" href="https://sandfox.me/php/install-composer-in-docker-2.html"/>
    <summary type="html">&lt;p&gt;While &lt;a class="reference external" href="https://sandfox.me/php/install-composer-in-docker.html"&gt;the original way&lt;/a&gt; is still valid, in Docker it's now easier to copy the Composer executable from its Docker image.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code docker"&gt;&lt;a id="rest_code_5eb445805680483b8babe0f51e986482-1" name="rest_code_5eb445805680483b8babe0f51e986482-1" href="https://sandfox.me/php/install-composer-in-docker-2.html#rest_code_5eb445805680483b8babe0f51e986482-1"&gt;&lt;/a&gt;&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;--from&lt;span class="o"&gt;=&lt;/span&gt;composer:latest&lt;span class="w"&gt; &lt;/span&gt;/usr/bin/composer&lt;span class="w"&gt; &lt;/span&gt;/usr/local/bin/composer
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;or for PHP &amp;lt; 7.2.5&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code docker"&gt;&lt;a id="rest_code_a24ad818437246bdb6956d7ffef7ab82-1" name="rest_code_a24ad818437246bdb6956d7ffef7ab82-1" href="https://sandfox.me/php/install-composer-in-docker-2.html#rest_code_a24ad818437246bdb6956d7ffef7ab82-1"&gt;&lt;/a&gt;&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;--from&lt;span class="o"&gt;=&lt;/span&gt;composer:2.2&lt;span class="w"&gt; &lt;/span&gt;/usr/bin/composer&lt;span class="w"&gt; &lt;/span&gt;/usr/local/bin/composer
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Please note that without the installer, dependencies won't be checked, so you also need to install git and/or zip,
and preferably optional dependencies like mbstring too.&lt;/p&gt;
&lt;p&gt;Found accidentally &lt;a class="reference external" href="https://stackoverflow.com/a/58694421"&gt;on the Stack Overflow&lt;/a&gt;.
There is also &lt;a class="reference external" href="https://stackoverflow.com/a/68600278"&gt;another interesting and underliked method&lt;/a&gt; for the case
when you don't want to keep the composer executable and cache files in your image.&lt;/p&gt;</summary>
    <category term="composer" label="composer"/>
    <category term="docker" label="docker"/>
  </entry>
  <entry>
    <title>OpenSpout</title>
    <id>https://sandfox.me/php/openspout.html</id>
    <updated>2022-12-22T16:32:00+02:00</updated>
    <published>2022-12-22T16:32:00+02:00</published>
    <author>
      <name>Anton Smirnov</name>
    </author>
    <link rel="alternate" type="text/html" href="https://sandfox.me/php/openspout.html"/>
    <summary type="html">&lt;p&gt;I have recently found myself in a situation when 3 out of 4 libraries that I used to work with Excel files were abandoned:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://packagist.org/packages/akeneo-labs/spreadsheet-parser"&gt;akeneo-labs/spreadsheet-parser&lt;/a&gt;
(streaming reader) had no commits in 4 years&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://packagist.org/packages/mk-j/php_xlsxwriter"&gt;mk-j/php_xlsxwriter&lt;/a&gt;
(streaming writer) had no commits in 2 years&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://packagist.org/packages/box/spout"&gt;box/spout&lt;/a&gt;
(streaming reader/writer) is formally abandoned&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Luckily there exists a community fork of Spout called &lt;a class="reference external" href="https://packagist.org/packages/openspout/openspout"&gt;OpenSpout&lt;/a&gt; and it can replace them all.
It seems pretty popular with 1 mln downloads and 229 stars but it's still less popular than the original
and I managed to find it only by navigating the forks of Spout so I think it just needs more exposure.&lt;/p&gt;</summary>
    <category term="excel" label="excel"/>
    <category term="spreadsheet" label="spreadsheet"/>
  </entry>
  <entry>
    <title>PHP 8.2 and my achievement</title>
    <id>https://sandfox.me/php/php-82-my-achievements.html</id>
    <updated>2022-12-10T13:11:00+02:00</updated>
    <published>2022-12-10T13:11:00+02:00</published>
    <author>
      <name>Anton Smirnov</name>
    </author>
    <link rel="alternate" type="text/html" href="https://sandfox.me/php/php-82-my-achievements.html"/>
    <summary type="html">&lt;p&gt;A small step for the community may still be a huge leap for specific people,
like Pierrick Charron and Sergey Panteleev who became this version release managers.
I would like to congratulate them with a successful release.&lt;/p&gt;
&lt;p&gt;This moon-in-reverse scale leap also happened to me:
&lt;a class="reference external" href="https://github.com/php/php-src/pull/9213"&gt;I got my first MR accepted to the PHP itself&lt;/a&gt;.
It's the second C-based project that I contributed professionally, and the only huge one.
The first one was &lt;a class="reference external" href="https://sandfox.me/ruby/journald-native.html"&gt;my systemd-journal lib wrapper&lt;/a&gt;.&lt;/p&gt;</summary>
    <category term="php-82" label="php 8.2"/>
  </entry>
  <entry>
    <title>PHP 8.2 and my libraries</title>
    <id>https://sandfox.me/php/php-82-my-libs.html</id>
    <updated>2022-12-10T12:54:00+02:00</updated>
    <published>2022-12-10T12:54:00+02:00</published>
    <author>
      <name>Anton Smirnov</name>
    </author>
    <link rel="alternate" type="text/html" href="https://sandfox.me/php/php-82-my-libs.html"/>
    <summary type="html">&lt;p&gt;I have re-tested all my libraries for compatibility with PHP 8.2.
Luckily due to small amount of changes and, well, me not using some bad practices,
they are all compatible with the new release.&lt;/p&gt;
&lt;p&gt;Only MonsterID &lt;a class="reference external" href="https://github.com/arokettu/monsterid/releases/tag/2.2.0"&gt;had a new release&lt;/a&gt; to leverage the new Random Extension.&lt;/p&gt;</summary>
    <category term="php-82" label="php 8.2"/>
  </entry>
  <entry>
    <title>PHP 8.2 Released</title>
    <id>https://sandfox.me/php/php-82-released.html</id>
    <updated>2022-12-10T12:50:00+02:00</updated>
    <published>2022-12-10T12:50:00+02:00</published>
    <author>
      <name>Anton Smirnov</name>
    </author>
    <link rel="alternate" type="text/html" href="https://sandfox.me/php/php-82-released.html"/>
    <summary type="html">&lt;div&gt;&lt;p&gt;PHP 8.2 has been released.
It's a relatively small release by new features.
I already covered &lt;a class="reference external" href="https://sandfox.me/php/php-82-early-look.html"&gt;some of them&lt;/a&gt;.
Here are things that I would like to highlight:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://sandfox.me/php/php-82-released.html"&gt;Read more…&lt;/a&gt; (1 min remaining to read)&lt;/p&gt;&lt;/div&gt;</summary>
    <category term="php-82" label="php 8.2"/>
  </entry>
  <entry>
    <title>Unsigned</title>
    <id>https://sandfox.me/php/unsigned.html</id>
    <updated>2022-09-06T20:54:00+03:00</updated>
    <published>2022-09-06T20:54:00+03:00</published>
    <author>
      <name>Anton Smirnov</name>
    </author>
    <link rel="alternate" type="text/html" href="https://sandfox.me/php/unsigned.html"/>
    <summary type="html">&lt;p&gt;Unsigned is a fixed (but arbitrary) length unsigned integer arithmetic library for native PHP.
It was created as a helper for the &lt;a class="reference external" href="https://sandfox.me/php/random-polyfill.html"&gt;Random Extension Polyfill&lt;/a&gt; to remove hard dependency on the GMP.
It may be useful for weird arithmetic with shifts and unsigned overflows that is used in RNGS, encryptors, hashes, etc.
(But it won't be cryptographically secure! Time based attacks are quite possible because of some optimizations)
Performance greatly depends on the PHP version, with PHP 8.0+ it performs quite nicely, only slightly slower than GMP.&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://sandfox.dev/php/unsigned.html"&gt;https://sandfox.dev/php/unsigned.html&lt;/a&gt;&lt;/p&gt;</summary>
    <category term="arithmetic" label="arithmetic"/>
    <category term="lib" label="lib"/>
  </entry>
  <entry>
    <title>Polyfill for Random Extension</title>
    <id>https://sandfox.me/php/random-polyfill.html</id>
    <updated>2022-07-23T19:52:00+03:00</updated>
    <published>2022-07-23T19:52:00+03:00</published>
    <author>
      <name>Anton Smirnov</name>
    </author>
    <link rel="alternate" type="text/html" href="https://sandfox.me/php/random-polyfill.html"/>
    <summary type="html">&lt;p&gt;Announcing my new library, a polyfill for the new sexy &lt;code class="docutils literal"&gt;&lt;span class="pre"&gt;ext-random&lt;/span&gt;&lt;/code&gt; from PHP 8.2
&lt;a class="reference external" href="https://sandfox.me/php/php-82-early-look.html"&gt;that I mentioned a couple of posts ago.&lt;/a&gt;
It requires PHP 7.1+ and the GMP extension.&lt;/p&gt;
&lt;p&gt;There will be some limitations with the compatibility but it's already usable for most simple use cases.
Grab it here: &lt;a class="reference external" href="https://sandfox.dev/php/random-polyfill.html"&gt;https://sandfox.dev/php/random-polyfill.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Many thanks to &lt;a class="reference external" href="https://github.com/zeriyoshi"&gt;Go Kudo&lt;/a&gt; for his work on the original extension.&lt;/p&gt;</summary>
    <category term="ext-random" label="ext-random"/>
    <category term="php-82" label="php 8.2"/>
  </entry>
  <entry>
    <title>Early Look at PHP 8.2</title>
    <id>https://sandfox.me/php/php-82-early-look.html</id>
    <updated>2022-06-22T02:23:00+03:00</updated>
    <published>2022-06-22T02:23:00+03:00</published>
    <author>
      <name>Anton Smirnov</name>
    </author>
    <link rel="alternate" type="text/html" href="https://sandfox.me/php/php-82-early-look.html"/>
    <summary type="html">&lt;div&gt;&lt;p&gt;It's a month before the feature freeze so we can predict what the release will look like.
So far it seems like an underwhelming release without any killer features.
It still has very nice language improvements.&lt;/p&gt;
&lt;p&gt;These are the things I would like to highlight:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://sandfox.me/php/php-82-early-look.html"&gt;Read more…&lt;/a&gt; (1 min remaining to read)&lt;/p&gt;&lt;/div&gt;</summary>
    <category term="php-82" label="php 8.2"/>
  </entry>
  <entry>
    <title>License Manager for Composer</title>
    <id>https://sandfox.me/php/composer-license-manager.html</id>
    <updated>2022-06-22T02:12:00+03:00</updated>
    <published>2022-06-22T02:12:00+03:00</published>
    <author>
      <name>Anton Smirnov</name>
    </author>
    <link rel="alternate" type="text/html" href="https://sandfox.me/php/composer-license-manager.html"/>
    <summary type="html">&lt;p&gt;I found myself in a need to filter away some licenses for my dependencies (AGPL, I'm looking at you).
I've found a well known plugin for that: &lt;a class="reference external" href="https://packagist.org/packages/metasyntactical/composer-plugin-license-check"&gt;metasyntactical/composer-plugin-license-check&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The problem that I found with it is that it doesn't prevent you from installing blacklisted packages.
I mean it was designed to do that but fails on Composer 2.0+.&lt;/p&gt;
&lt;p&gt;I started investigating for the ways to fix that but ended up with a feature complete plugin.
It also offers some more flexibility in the config.&lt;/p&gt;
&lt;p&gt;Grab it here: &lt;a class="reference external" href="https://sandfox.dev/php/composer-license-manager.html"&gt;https://sandfox.dev/php/composer-license-manager.html&lt;/a&gt;&lt;/p&gt;</summary>
    <category term="composer" label="composer"/>
    <category term="license" label="license"/>
  </entry>
  <entry>
    <title>PHP 5: if (\false)</title>
    <id>https://sandfox.me/php/php-5-false.html</id>
    <updated>2022-01-07T23:07:00+02:00</updated>
    <published>2022-01-07T23:07:00+02:00</published>
    <author>
      <name>Anton Smirnov</name>
    </author>
    <link rel="alternate" type="text/html" href="https://sandfox.me/php/php-5-false.html"/>
    <summary type="html">&lt;p&gt;I was wondering why the typical class alias boilerplate code uses this weird backslash in
&lt;code class="docutils literal"&gt;if (\false)&lt;/code&gt; like &lt;a class="reference external" href="https://github.com/twigphp/Twig/blob/v2.7.0/lib/Twig/Function.php"&gt;here&lt;/a&gt; for example.&lt;/p&gt;
&lt;p&gt;It turns out this code &lt;a class="reference external" href="https://3v4l.org/eW70X"&gt;will wish you a happy debugging in PHP 5.3-5.6&lt;/a&gt;:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code php"&gt;&lt;a id="rest_code_70a0898568a142b7bbdb0cb3d66454fc-1" name="rest_code_70a0898568a142b7bbdb0cb3d66454fc-1" href="https://sandfox.me/php/php-5-false.html#rest_code_70a0898568a142b7bbdb0cb3d66454fc-1"&gt;&lt;/a&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;
&lt;a id="rest_code_70a0898568a142b7bbdb0cb3d66454fc-2" name="rest_code_70a0898568a142b7bbdb0cb3d66454fc-2" href="https://sandfox.me/php/php-5-false.html#rest_code_70a0898568a142b7bbdb0cb3d66454fc-2"&gt;&lt;/a&gt;
&lt;a id="rest_code_70a0898568a142b7bbdb0cb3d66454fc-3" name="rest_code_70a0898568a142b7bbdb0cb3d66454fc-3" href="https://sandfox.me/php/php-5-false.html#rest_code_70a0898568a142b7bbdb0cb3d66454fc-3"&gt;&lt;/a&gt;&lt;span class="k"&gt;namespace&lt;/span&gt; &lt;span class="nx"&gt;ns&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;a id="rest_code_70a0898568a142b7bbdb0cb3d66454fc-4" name="rest_code_70a0898568a142b7bbdb0cb3d66454fc-4" href="https://sandfox.me/php/php-5-false.html#rest_code_70a0898568a142b7bbdb0cb3d66454fc-4"&gt;&lt;/a&gt;
&lt;a id="rest_code_70a0898568a142b7bbdb0cb3d66454fc-5" name="rest_code_70a0898568a142b7bbdb0cb3d66454fc-5" href="https://sandfox.me/php/php-5-false.html#rest_code_70a0898568a142b7bbdb0cb3d66454fc-5"&gt;&lt;/a&gt;&lt;span class="nb"&gt;define&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'ns\\false'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;a id="rest_code_70a0898568a142b7bbdb0cb3d66454fc-6" name="rest_code_70a0898568a142b7bbdb0cb3d66454fc-6" href="https://sandfox.me/php/php-5-false.html#rest_code_70a0898568a142b7bbdb0cb3d66454fc-6"&gt;&lt;/a&gt;
&lt;a id="rest_code_70a0898568a142b7bbdb0cb3d66454fc-7" name="rest_code_70a0898568a142b7bbdb0cb3d66454fc-7" href="https://sandfox.me/php/php-5-false.html#rest_code_70a0898568a142b7bbdb0cb3d66454fc-7"&gt;&lt;/a&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;a id="rest_code_70a0898568a142b7bbdb0cb3d66454fc-8" name="rest_code_70a0898568a142b7bbdb0cb3d66454fc-8" href="https://sandfox.me/php/php-5-false.html#rest_code_70a0898568a142b7bbdb0cb3d66454fc-8"&gt;&lt;/a&gt;    &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Happy Debugging"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;PHP_EOL&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;a id="rest_code_70a0898568a142b7bbdb0cb3d66454fc-9" name="rest_code_70a0898568a142b7bbdb0cb3d66454fc-9" href="https://sandfox.me/php/php-5-false.html#rest_code_70a0898568a142b7bbdb0cb3d66454fc-9"&gt;&lt;/a&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Not a very useful knowledge now but an interesting history fact.&lt;/p&gt;</summary>
    <category term="php-5" label="php 5"/>
    <category term="til" label="til"/>
  </entry>
  <entry>
    <title>PHP 8.1 Syntax Showcase</title>
    <id>https://sandfox.me/php/php-81-showcase.html</id>
    <updated>2021-11-30T19:37:00+02:00</updated>
    <published>2021-11-30T19:37:00+02:00</published>
    <author>
      <name>Anton Smirnov</name>
    </author>
    <link rel="alternate" type="text/html" href="https://sandfox.me/php/php-81-showcase.html"/>
    <summary type="html">&lt;p&gt;PHP 8.1 was released when I was suffering from COVID so I'm a bit late.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code php"&gt;&lt;a id="rest_code_65ce550b1282488e9d157d392fa3675e-1" name="rest_code_65ce550b1282488e9d157d392fa3675e-1" href="https://sandfox.me/php/php-81-showcase.html#rest_code_65ce550b1282488e9d157d392fa3675e-1"&gt;&lt;/a&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;
&lt;a id="rest_code_65ce550b1282488e9d157d392fa3675e-2" name="rest_code_65ce550b1282488e9d157d392fa3675e-2" href="https://sandfox.me/php/php-81-showcase.html#rest_code_65ce550b1282488e9d157d392fa3675e-2"&gt;&lt;/a&gt;
&lt;a id="rest_code_65ce550b1282488e9d157d392fa3675e-3" name="rest_code_65ce550b1282488e9d157d392fa3675e-3" href="https://sandfox.me/php/php-81-showcase.html#rest_code_65ce550b1282488e9d157d392fa3675e-3"&gt;&lt;/a&gt;&lt;span class="nx"&gt;enum&lt;/span&gt; &lt;span class="nx"&gt;Status&lt;/span&gt;
&lt;a id="rest_code_65ce550b1282488e9d157d392fa3675e-4" name="rest_code_65ce550b1282488e9d157d392fa3675e-4" href="https://sandfox.me/php/php-81-showcase.html#rest_code_65ce550b1282488e9d157d392fa3675e-4"&gt;&lt;/a&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;a id="rest_code_65ce550b1282488e9d157d392fa3675e-5" name="rest_code_65ce550b1282488e9d157d392fa3675e-5" href="https://sandfox.me/php/php-81-showcase.html#rest_code_65ce550b1282488e9d157d392fa3675e-5"&gt;&lt;/a&gt;    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="nx"&gt;OK&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;a id="rest_code_65ce550b1282488e9d157d392fa3675e-6" name="rest_code_65ce550b1282488e9d157d392fa3675e-6" href="https://sandfox.me/php/php-81-showcase.html#rest_code_65ce550b1282488e9d157d392fa3675e-6"&gt;&lt;/a&gt;    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="nx"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;a id="rest_code_65ce550b1282488e9d157d392fa3675e-7" name="rest_code_65ce550b1282488e9d157d392fa3675e-7" href="https://sandfox.me/php/php-81-showcase.html#rest_code_65ce550b1282488e9d157d392fa3675e-7"&gt;&lt;/a&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;a id="rest_code_65ce550b1282488e9d157d392fa3675e-8" name="rest_code_65ce550b1282488e9d157d392fa3675e-8" href="https://sandfox.me/php/php-81-showcase.html#rest_code_65ce550b1282488e9d157d392fa3675e-8"&gt;&lt;/a&gt;
&lt;a id="rest_code_65ce550b1282488e9d157d392fa3675e-9" name="rest_code_65ce550b1282488e9d157d392fa3675e-9" href="https://sandfox.me/php/php-81-showcase.html#rest_code_65ce550b1282488e9d157d392fa3675e-9"&gt;&lt;/a&gt;&lt;span class="p"&gt;#[&lt;/span&gt;&lt;span class="nd"&gt;SomeAttr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;SomeNestedAttr&lt;/span&gt;&lt;span class="p"&gt;())]&lt;/span&gt;
&lt;a id="rest_code_65ce550b1282488e9d157d392fa3675e-10" name="rest_code_65ce550b1282488e9d157d392fa3675e-10" href="https://sandfox.me/php/php-81-showcase.html#rest_code_65ce550b1282488e9d157d392fa3675e-10"&gt;&lt;/a&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TestTest&lt;/span&gt;
&lt;a id="rest_code_65ce550b1282488e9d157d392fa3675e-11" name="rest_code_65ce550b1282488e9d157d392fa3675e-11" href="https://sandfox.me/php/php-81-showcase.html#rest_code_65ce550b1282488e9d157d392fa3675e-11"&gt;&lt;/a&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;a id="rest_code_65ce550b1282488e9d157d392fa3675e-12" name="rest_code_65ce550b1282488e9d157d392fa3675e-12" href="https://sandfox.me/php/php-81-showcase.html#rest_code_65ce550b1282488e9d157d392fa3675e-12"&gt;&lt;/a&gt;    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="fm"&gt;__construct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;a id="rest_code_65ce550b1282488e9d157d392fa3675e-13" name="rest_code_65ce550b1282488e9d157d392fa3675e-13" href="https://sandfox.me/php/php-81-showcase.html#rest_code_65ce550b1282488e9d157d392fa3675e-13"&gt;&lt;/a&gt;        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nx"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;Status&lt;/span&gt; &lt;span class="nv"&gt;$status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Status&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="na"&gt;OK&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;a id="rest_code_65ce550b1282488e9d157d392fa3675e-14" name="rest_code_65ce550b1282488e9d157d392fa3675e-14" href="https://sandfox.me/php/php-81-showcase.html#rest_code_65ce550b1282488e9d157d392fa3675e-14"&gt;&lt;/a&gt;        &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;Logger&lt;/span&gt; &lt;span class="nv"&gt;$logger&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;FileLogger&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;perm&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="nx"&gt;o644&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;a id="rest_code_65ce550b1282488e9d157d392fa3675e-15" name="rest_code_65ce550b1282488e9d157d392fa3675e-15" href="https://sandfox.me/php/php-81-showcase.html#rest_code_65ce550b1282488e9d157d392fa3675e-15"&gt;&lt;/a&gt;    &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;a id="rest_code_65ce550b1282488e9d157d392fa3675e-16" name="rest_code_65ce550b1282488e9d157d392fa3675e-16" href="https://sandfox.me/php/php-81-showcase.html#rest_code_65ce550b1282488e9d157d392fa3675e-16"&gt;&lt;/a&gt;
&lt;a id="rest_code_65ce550b1282488e9d157d392fa3675e-17" name="rest_code_65ce550b1282488e9d157d392fa3675e-17" href="https://sandfox.me/php/php-81-showcase.html#rest_code_65ce550b1282488e9d157d392fa3675e-17"&gt;&lt;/a&gt;    &lt;span class="nd"&gt;public&lt;/span&gt; &lt;span class="nd"&gt;function&lt;/span&gt; &lt;span class="nd"&gt;process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Iterator&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nx"&gt;Countable&lt;/span&gt; &lt;span class="nv"&gt;$value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;a id="rest_code_65ce550b1282488e9d157d392fa3675e-18" name="rest_code_65ce550b1282488e9d157d392fa3675e-18" href="https://sandfox.me/php/php-81-showcase.html#rest_code_65ce550b1282488e9d157d392fa3675e-18"&gt;&lt;/a&gt;    &lt;span class="p"&gt;{&lt;/span&gt;
&lt;a id="rest_code_65ce550b1282488e9d157d392fa3675e-19" name="rest_code_65ce550b1282488e9d157d392fa3675e-19" href="https://sandfox.me/php/php-81-showcase.html#rest_code_65ce550b1282488e9d157d392fa3675e-19"&gt;&lt;/a&gt;        &lt;span class="nd"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;count&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;a id="rest_code_65ce550b1282488e9d157d392fa3675e-20" name="rest_code_65ce550b1282488e9d157d392fa3675e-20" href="https://sandfox.me/php/php-81-showcase.html#rest_code_65ce550b1282488e9d157d392fa3675e-20"&gt;&lt;/a&gt;            &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;a id="rest_code_65ce550b1282488e9d157d392fa3675e-21" name="rest_code_65ce550b1282488e9d157d392fa3675e-21" href="https://sandfox.me/php/php-81-showcase.html#rest_code_65ce550b1282488e9d157d392fa3675e-21"&gt;&lt;/a&gt;        &lt;span class="p"&gt;}&lt;/span&gt;
&lt;a id="rest_code_65ce550b1282488e9d157d392fa3675e-22" name="rest_code_65ce550b1282488e9d157d392fa3675e-22" href="https://sandfox.me/php/php-81-showcase.html#rest_code_65ce550b1282488e9d157d392fa3675e-22"&gt;&lt;/a&gt;    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;a id="rest_code_65ce550b1282488e9d157d392fa3675e-23" name="rest_code_65ce550b1282488e9d157d392fa3675e-23" href="https://sandfox.me/php/php-81-showcase.html#rest_code_65ce550b1282488e9d157d392fa3675e-23"&gt;&lt;/a&gt;
&lt;a id="rest_code_65ce550b1282488e9d157d392fa3675e-24" name="rest_code_65ce550b1282488e9d157d392fa3675e-24" href="https://sandfox.me/php/php-81-showcase.html#rest_code_65ce550b1282488e9d157d392fa3675e-24"&gt;&lt;/a&gt;    &lt;span class="nd"&gt;public&lt;/span&gt; &lt;span class="nd"&gt;function&lt;/span&gt; &lt;span class="nd"&gt;error&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nd"&gt;never&lt;/span&gt;
&lt;a id="rest_code_65ce550b1282488e9d157d392fa3675e-25" name="rest_code_65ce550b1282488e9d157d392fa3675e-25" href="https://sandfox.me/php/php-81-showcase.html#rest_code_65ce550b1282488e9d157d392fa3675e-25"&gt;&lt;/a&gt;    &lt;span class="p"&gt;{&lt;/span&gt;
&lt;a id="rest_code_65ce550b1282488e9d157d392fa3675e-26" name="rest_code_65ce550b1282488e9d157d392fa3675e-26" href="https://sandfox.me/php/php-81-showcase.html#rest_code_65ce550b1282488e9d157d392fa3675e-26"&gt;&lt;/a&gt;        &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Error!'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;a id="rest_code_65ce550b1282488e9d157d392fa3675e-27" name="rest_code_65ce550b1282488e9d157d392fa3675e-27" href="https://sandfox.me/php/php-81-showcase.html#rest_code_65ce550b1282488e9d157d392fa3675e-27"&gt;&lt;/a&gt;        &lt;span class="nd"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;a id="rest_code_65ce550b1282488e9d157d392fa3675e-28" name="rest_code_65ce550b1282488e9d157d392fa3675e-28" href="https://sandfox.me/php/php-81-showcase.html#rest_code_65ce550b1282488e9d157d392fa3675e-28"&gt;&lt;/a&gt;    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;a id="rest_code_65ce550b1282488e9d157d392fa3675e-29" name="rest_code_65ce550b1282488e9d157d392fa3675e-29" href="https://sandfox.me/php/php-81-showcase.html#rest_code_65ce550b1282488e9d157d392fa3675e-29"&gt;&lt;/a&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;a id="rest_code_65ce550b1282488e9d157d392fa3675e-30" name="rest_code_65ce550b1282488e9d157d392fa3675e-30" href="https://sandfox.me/php/php-81-showcase.html#rest_code_65ce550b1282488e9d157d392fa3675e-30"&gt;&lt;/a&gt;
&lt;a id="rest_code_65ce550b1282488e9d157d392fa3675e-31" name="rest_code_65ce550b1282488e9d157d392fa3675e-31" href="https://sandfox.me/php/php-81-showcase.html#rest_code_65ce550b1282488e9d157d392fa3675e-31"&gt;&lt;/a&gt;&lt;span class="nv"&gt;$test&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nd"&gt;new&lt;/span&gt; &lt;span class="nd"&gt;TestTest&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;a id="rest_code_65ce550b1282488e9d157d392fa3675e-32" name="rest_code_65ce550b1282488e9d157d392fa3675e-32" href="https://sandfox.me/php/php-81-showcase.html#rest_code_65ce550b1282488e9d157d392fa3675e-32"&gt;&lt;/a&gt;
&lt;a id="rest_code_65ce550b1282488e9d157d392fa3675e-33" name="rest_code_65ce550b1282488e9d157d392fa3675e-33" href="https://sandfox.me/php/php-81-showcase.html#rest_code_65ce550b1282488e9d157d392fa3675e-33"&gt;&lt;/a&gt;&lt;span class="nv"&gt;$arr1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'a'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nd"&gt;new&lt;/span&gt; &lt;span class="nd"&gt;ArrayObject&lt;/span&gt;&lt;span class="p"&gt;()];&lt;/span&gt;
&lt;a id="rest_code_65ce550b1282488e9d157d392fa3675e-34" name="rest_code_65ce550b1282488e9d157d392fa3675e-34" href="https://sandfox.me/php/php-81-showcase.html#rest_code_65ce550b1282488e9d157d392fa3675e-34"&gt;&lt;/a&gt;&lt;span class="nv"&gt;$arr2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'b'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;ArrayIterator&lt;/span&gt;&lt;span class="p"&gt;()];&lt;/span&gt;
&lt;a id="rest_code_65ce550b1282488e9d157d392fa3675e-35" name="rest_code_65ce550b1282488e9d157d392fa3675e-35" href="https://sandfox.me/php/php-81-showcase.html#rest_code_65ce550b1282488e9d157d392fa3675e-35"&gt;&lt;/a&gt;
&lt;a id="rest_code_65ce550b1282488e9d157d392fa3675e-36" name="rest_code_65ce550b1282488e9d157d392fa3675e-36" href="https://sandfox.me/php/php-81-showcase.html#rest_code_65ce550b1282488e9d157d392fa3675e-36"&gt;&lt;/a&gt;&lt;span class="nv"&gt;$result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;array_map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$test&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="nv"&gt;$arr1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="nv"&gt;$arr2&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;</summary>
    <category term="php-81" label="php 8.1"/>
  </entry>
  <entry>
    <title>Torrent File 2.2</title>
    <id>https://sandfox.me/php/torrent-file-22.html</id>
    <updated>2021-11-30T19:30:00+02:00</updated>
    <published>2021-11-30T19:30:00+02:00</published>
    <author>
      <name>Anton Smirnov</name>
    </author>
    <link rel="alternate" type="text/html" href="https://sandfox.me/php/torrent-file-22.html"/>
    <summary type="html">&lt;p&gt;The &lt;a class="reference external" href="https://sandfox.dev/php/torrent-file.html"&gt;torrent file library&lt;/a&gt; got its biggest update.
Versions 2.2 / 3.0 added support for:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="http://bittorrent.org/beps/bep_0005.html"&gt;BEP-5&lt;/a&gt;: DHT nodes list&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="http://bittorrent.org/beps/bep_0017.html"&gt;BEP-17&lt;/a&gt;: HTTP seed urls&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="http://bittorrent.org/beps/bep_0019.html"&gt;BEP-19&lt;/a&gt;: WebSeed urls&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="http://bittorrent.org/beps/bep_0047.html"&gt;BEP-47&lt;/a&gt;: sha1 sums, executable files, symlinks, padding&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Big cleanup to support torrent v2 metadata (&lt;a class="reference external" href="http://bittorrent.org/beps/bep_0052.html"&gt;BEP-52&lt;/a&gt;) in 2.3 / 3.1&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;</summary>
    <category term="torrent" label="torrent"/>
  </entry>
  <entry>
    <title>CVE-2021-41106</title>
    <id>https://sandfox.me/php/jwt-cve.html</id>
    <updated>2021-09-30T02:12:00+03:00</updated>
    <published>2021-09-30T02:12:00+03:00</published>
    <author>
      <name>Anton Smirnov</name>
    </author>
    <link rel="alternate" type="text/html" href="https://sandfox.me/php/jwt-cve.html"/>
    <summary type="html">&lt;p&gt;Nice, now I have my first CVE :D
The one I've found, not the one I've created :D&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;GitHub: &lt;a class="reference external" href="https://github.com/advisories/GHSA-7322-jrq4-x5hf"&gt;https://github.com/advisories/GHSA-7322-jrq4-x5hf&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;CVE: &lt;a class="reference external" href="https://www.cve.org/CVERecord?id=CVE-2021-41106"&gt;https://www.cve.org/CVERecord?id=CVE-2021-41106&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;NVD: &lt;a class="reference external" href="https://nvd.nist.gov/vuln/detail/CVE-2021-41106"&gt;https://nvd.nist.gov/vuln/detail/CVE-2021-41106&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you're using &lt;code class="docutils literal"&gt;lcobucci/jwt&lt;/code&gt;, please upgrade.&lt;/p&gt;</summary>
    <category term="jwt" label="jwt"/>
    <category term="security" label="security"/>
  </entry>
  <entry>
    <title>IsResource</title>
    <id>https://sandfox.me/php/is-resource.html</id>
    <updated>2021-09-28T04:42:00+03:00</updated>
    <published>2021-09-28T04:42:00+03:00</published>
    <author>
      <name>Anton Smirnov</name>
    </author>
    <link rel="alternate" type="text/html" href="https://sandfox.me/php/is-resource.html"/>
    <summary type="html">&lt;p&gt;Inspired by &lt;a class="reference external" href="https://externals.io/message/116127"&gt;a recent discussion in the PHP Internals&lt;/a&gt;, I decided to provide a userland solution.
Check this:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code php"&gt;&lt;a id="rest_code_a324640a84f34c27b4e5bfe2b2ae5de3-1" name="rest_code_a324640a84f34c27b4e5bfe2b2ae5de3-1" href="https://sandfox.me/php/is-resource.html#rest_code_a324640a84f34c27b4e5bfe2b2ae5de3-1"&gt;&lt;/a&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;
&lt;a id="rest_code_a324640a84f34c27b4e5bfe2b2ae5de3-2" name="rest_code_a324640a84f34c27b4e5bfe2b2ae5de3-2" href="https://sandfox.me/php/is-resource.html#rest_code_a324640a84f34c27b4e5bfe2b2ae5de3-2"&gt;&lt;/a&gt;
&lt;a id="rest_code_a324640a84f34c27b4e5bfe2b2ae5de3-3" name="rest_code_a324640a84f34c27b4e5bfe2b2ae5de3-3" href="https://sandfox.me/php/is-resource.html#rest_code_a324640a84f34c27b4e5bfe2b2ae5de3-3"&gt;&lt;/a&gt;&lt;span class="nv"&gt;$hash&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;hash_init&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'md5'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;a id="rest_code_a324640a84f34c27b4e5bfe2b2ae5de3-4" name="rest_code_a324640a84f34c27b4e5bfe2b2ae5de3-4" href="https://sandfox.me/php/is-resource.html#rest_code_a324640a84f34c27b4e5bfe2b2ae5de3-4"&gt;&lt;/a&gt;
&lt;a id="rest_code_a324640a84f34c27b4e5bfe2b2ae5de3-5" name="rest_code_a324640a84f34c27b4e5bfe2b2ae5de3-5" href="https://sandfox.me/php/is-resource.html#rest_code_a324640a84f34c27b4e5bfe2b2ae5de3-5"&gt;&lt;/a&gt;&lt;span class="c1"&gt;// vanilla functions:&lt;/span&gt;
&lt;a id="rest_code_a324640a84f34c27b4e5bfe2b2ae5de3-6" name="rest_code_a324640a84f34c27b4e5bfe2b2ae5de3-6" href="https://sandfox.me/php/is-resource.html#rest_code_a324640a84f34c27b4e5bfe2b2ae5de3-6"&gt;&lt;/a&gt;&lt;span class="nb"&gt;is_resource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$hash&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// true in PHP &amp;lt;= 7.1, false in PHP &amp;gt;= 7.2&lt;/span&gt;
&lt;a id="rest_code_a324640a84f34c27b4e5bfe2b2ae5de3-7" name="rest_code_a324640a84f34c27b4e5bfe2b2ae5de3-7" href="https://sandfox.me/php/is-resource.html#rest_code_a324640a84f34c27b4e5bfe2b2ae5de3-7"&gt;&lt;/a&gt;&lt;span class="nb"&gt;get_resource_type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$hash&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// "Hash Context" in PHP &amp;lt;= 7.1, various errors otherwise&lt;/span&gt;
&lt;a id="rest_code_a324640a84f34c27b4e5bfe2b2ae5de3-8" name="rest_code_a324640a84f34c27b4e5bfe2b2ae5de3-8" href="https://sandfox.me/php/is-resource.html#rest_code_a324640a84f34c27b4e5bfe2b2ae5de3-8"&gt;&lt;/a&gt;
&lt;a id="rest_code_a324640a84f34c27b4e5bfe2b2ae5de3-9" name="rest_code_a324640a84f34c27b4e5bfe2b2ae5de3-9" href="https://sandfox.me/php/is-resource.html#rest_code_a324640a84f34c27b4e5bfe2b2ae5de3-9"&gt;&lt;/a&gt;&lt;span class="c1"&gt;// library functions:&lt;/span&gt;
&lt;a id="rest_code_a324640a84f34c27b4e5bfe2b2ae5de3-10" name="rest_code_a324640a84f34c27b4e5bfe2b2ae5de3-10" href="https://sandfox.me/php/is-resource.html#rest_code_a324640a84f34c27b4e5bfe2b2ae5de3-10"&gt;&lt;/a&gt;&lt;span class="nx"&gt;\Arokettu\IsResource\is_resource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$hash&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// true&lt;/span&gt;
&lt;a id="rest_code_a324640a84f34c27b4e5bfe2b2ae5de3-11" name="rest_code_a324640a84f34c27b4e5bfe2b2ae5de3-11" href="https://sandfox.me/php/is-resource.html#rest_code_a324640a84f34c27b4e5bfe2b2ae5de3-11"&gt;&lt;/a&gt;&lt;span class="nx"&gt;\Arokettu\IsResource\get_resource_type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$hash&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// "Hash Context"&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Get it on my dev portal: &lt;a class="reference external" href="https://sandfox.dev/php/is-resource.html"&gt;https://sandfox.dev/php/is-resource.html&lt;/a&gt;&lt;/p&gt;</summary>
    <category term="is_resource" label="is_resource"/>
    <category term="php-8" label="php 8"/>
    <category term="php-81" label="php 8.1"/>
  </entry>
  <entry>
    <title>Pseudolocale Lib for PHP</title>
    <id>https://sandfox.me/php/pseudolocale.html</id>
    <updated>2021-01-27T04:20:00+02:00</updated>
    <published>2021-01-27T04:20:00+02:00</published>
    <author>
      <name>Anton Smirnov</name>
    </author>
    <link rel="alternate" type="text/html" href="https://sandfox.me/php/pseudolocale.html"/>
    <summary type="html">&lt;p&gt;I haven't found a good standalone &lt;a class="reference external" href="https://en.wikipedia.org/wiki/Pseudolocalization"&gt;pseudolocalization&lt;/a&gt; library for PHP so I wrote my own.&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://sandfox.dev/php/pseudolocale.html"&gt;https://sandfox.dev/php/pseudolocale.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Or if you're using Symfony Components or you don't mind using huge libraries for simple tasks,
there is one good alternative: &lt;code class="docutils literal"&gt;PseudoLocalizationTranslator&lt;/code&gt; in the &lt;a class="reference external" href="https://symfony.com/doc/current/translation.html"&gt;Symfony Translation Component&lt;/a&gt; since version 5.2.&lt;/p&gt;</summary>
    <category term="i18n" label="i18n"/>
    <category term="php" label="php"/>
    <category term="pseudolocale" label="pseudolocale"/>
  </entry>
  <entry>
    <title>PHP 8.0 Comparison Change</title>
    <id>https://sandfox.me/php/php-8-comparison.html</id>
    <updated>2020-10-22T23:00:00+03:00</updated>
    <published>2020-10-22T23:00:00+03:00</published>
    <author>
      <name>Anton Smirnov</name>
    </author>
    <link rel="alternate" type="text/html" href="https://sandfox.me/php/php-8-comparison.html"/>
    <summary type="html">&lt;div&gt;&lt;p&gt;Another new thing in PHP 8.0 will be slightly less madness in non strict value comparison.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://sandfox.me/php/php-8-comparison.html"&gt;Read more…&lt;/a&gt; (1 min remaining to read)&lt;/p&gt;&lt;/div&gt;</summary>
    <category term="php-8" label="php 8"/>
  </entry>
  <entry>
    <title>OOP in PHP 4 and 8</title>
    <id>https://sandfox.me/php/php-4-oop-in-8.html</id>
    <updated>2020-10-02T15:03:00+03:00</updated>
    <published>2020-10-02T15:03:00+03:00</published>
    <author>
      <name>Anton Smirnov</name>
    </author>
    <link rel="alternate" type="text/html" href="https://sandfox.me/php/php-4-oop-in-8.html"/>
    <summary type="html">&lt;p&gt;Deprecation of class name constructors means that you no longer can write OOP code
that works both in PHP 4 and PHP 8 without some hackery.
&lt;a class="reference external" href="https://3v4l.org/ZBTcC"&gt;This works however&lt;/a&gt;:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code php"&gt;&lt;a id="rest_code_bbfa8ee3aef94ed1a131e0c2ee0477a0-1" name="rest_code_bbfa8ee3aef94ed1a131e0c2ee0477a0-1" href="https://sandfox.me/php/php-4-oop-in-8.html#rest_code_bbfa8ee3aef94ed1a131e0c2ee0477a0-1"&gt;&lt;/a&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;
&lt;a id="rest_code_bbfa8ee3aef94ed1a131e0c2ee0477a0-2" name="rest_code_bbfa8ee3aef94ed1a131e0c2ee0477a0-2" href="https://sandfox.me/php/php-4-oop-in-8.html#rest_code_bbfa8ee3aef94ed1a131e0c2ee0477a0-2"&gt;&lt;/a&gt;
&lt;a id="rest_code_bbfa8ee3aef94ed1a131e0c2ee0477a0-3" name="rest_code_bbfa8ee3aef94ed1a131e0c2ee0477a0-3" href="https://sandfox.me/php/php-4-oop-in-8.html#rest_code_bbfa8ee3aef94ed1a131e0c2ee0477a0-3"&gt;&lt;/a&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;WorksIn4And8&lt;/span&gt;
&lt;a id="rest_code_bbfa8ee3aef94ed1a131e0c2ee0477a0-4" name="rest_code_bbfa8ee3aef94ed1a131e0c2ee0477a0-4" href="https://sandfox.me/php/php-4-oop-in-8.html#rest_code_bbfa8ee3aef94ed1a131e0c2ee0477a0-4"&gt;&lt;/a&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;a id="rest_code_bbfa8ee3aef94ed1a131e0c2ee0477a0-5" name="rest_code_bbfa8ee3aef94ed1a131e0c2ee0477a0-5" href="https://sandfox.me/php/php-4-oop-in-8.html#rest_code_bbfa8ee3aef94ed1a131e0c2ee0477a0-5"&gt;&lt;/a&gt;    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;$int&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;a id="rest_code_bbfa8ee3aef94ed1a131e0c2ee0477a0-6" name="rest_code_bbfa8ee3aef94ed1a131e0c2ee0477a0-6" href="https://sandfox.me/php/php-4-oop-in-8.html#rest_code_bbfa8ee3aef94ed1a131e0c2ee0477a0-6"&gt;&lt;/a&gt;
&lt;a id="rest_code_bbfa8ee3aef94ed1a131e0c2ee0477a0-7" name="rest_code_bbfa8ee3aef94ed1a131e0c2ee0477a0-7" href="https://sandfox.me/php/php-4-oop-in-8.html#rest_code_bbfa8ee3aef94ed1a131e0c2ee0477a0-7"&gt;&lt;/a&gt;    &lt;span class="c1"&gt;// Regular method in PHP 4&lt;/span&gt;
&lt;a id="rest_code_bbfa8ee3aef94ed1a131e0c2ee0477a0-8" name="rest_code_bbfa8ee3aef94ed1a131e0c2ee0477a0-8" href="https://sandfox.me/php/php-4-oop-in-8.html#rest_code_bbfa8ee3aef94ed1a131e0c2ee0477a0-8"&gt;&lt;/a&gt;    &lt;span class="c1"&gt;// Constructor in 5-8&lt;/span&gt;
&lt;a id="rest_code_bbfa8ee3aef94ed1a131e0c2ee0477a0-9" name="rest_code_bbfa8ee3aef94ed1a131e0c2ee0477a0-9" href="https://sandfox.me/php/php-4-oop-in-8.html#rest_code_bbfa8ee3aef94ed1a131e0c2ee0477a0-9"&gt;&lt;/a&gt;    &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="fm"&gt;__construct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;a id="rest_code_bbfa8ee3aef94ed1a131e0c2ee0477a0-10" name="rest_code_bbfa8ee3aef94ed1a131e0c2ee0477a0-10" href="https://sandfox.me/php/php-4-oop-in-8.html#rest_code_bbfa8ee3aef94ed1a131e0c2ee0477a0-10"&gt;&lt;/a&gt;    &lt;span class="p"&gt;{&lt;/span&gt;
&lt;a id="rest_code_bbfa8ee3aef94ed1a131e0c2ee0477a0-11" name="rest_code_bbfa8ee3aef94ed1a131e0c2ee0477a0-11" href="https://sandfox.me/php/php-4-oop-in-8.html#rest_code_bbfa8ee3aef94ed1a131e0c2ee0477a0-11"&gt;&lt;/a&gt;        &lt;span class="nb"&gt;error_log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'__construct()'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;a id="rest_code_bbfa8ee3aef94ed1a131e0c2ee0477a0-12" name="rest_code_bbfa8ee3aef94ed1a131e0c2ee0477a0-12" href="https://sandfox.me/php/php-4-oop-in-8.html#rest_code_bbfa8ee3aef94ed1a131e0c2ee0477a0-12"&gt;&lt;/a&gt;        &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;int&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$int&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;a id="rest_code_bbfa8ee3aef94ed1a131e0c2ee0477a0-13" name="rest_code_bbfa8ee3aef94ed1a131e0c2ee0477a0-13" href="https://sandfox.me/php/php-4-oop-in-8.html#rest_code_bbfa8ee3aef94ed1a131e0c2ee0477a0-13"&gt;&lt;/a&gt;    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;a id="rest_code_bbfa8ee3aef94ed1a131e0c2ee0477a0-14" name="rest_code_bbfa8ee3aef94ed1a131e0c2ee0477a0-14" href="https://sandfox.me/php/php-4-oop-in-8.html#rest_code_bbfa8ee3aef94ed1a131e0c2ee0477a0-14"&gt;&lt;/a&gt;
&lt;a id="rest_code_bbfa8ee3aef94ed1a131e0c2ee0477a0-15" name="rest_code_bbfa8ee3aef94ed1a131e0c2ee0477a0-15" href="https://sandfox.me/php/php-4-oop-in-8.html#rest_code_bbfa8ee3aef94ed1a131e0c2ee0477a0-15"&gt;&lt;/a&gt;    &lt;span class="c1"&gt;// Constructor in PHP 4&lt;/span&gt;
&lt;a id="rest_code_bbfa8ee3aef94ed1a131e0c2ee0477a0-16" name="rest_code_bbfa8ee3aef94ed1a131e0c2ee0477a0-16" href="https://sandfox.me/php/php-4-oop-in-8.html#rest_code_bbfa8ee3aef94ed1a131e0c2ee0477a0-16"&gt;&lt;/a&gt;    &lt;span class="c1"&gt;// Constructor overridden by __construct in 5-7&lt;/span&gt;
&lt;a id="rest_code_bbfa8ee3aef94ed1a131e0c2ee0477a0-17" name="rest_code_bbfa8ee3aef94ed1a131e0c2ee0477a0-17" href="https://sandfox.me/php/php-4-oop-in-8.html#rest_code_bbfa8ee3aef94ed1a131e0c2ee0477a0-17"&gt;&lt;/a&gt;    &lt;span class="c1"&gt;// Regular method in PHP 8&lt;/span&gt;
&lt;a id="rest_code_bbfa8ee3aef94ed1a131e0c2ee0477a0-18" name="rest_code_bbfa8ee3aef94ed1a131e0c2ee0477a0-18" href="https://sandfox.me/php/php-4-oop-in-8.html#rest_code_bbfa8ee3aef94ed1a131e0c2ee0477a0-18"&gt;&lt;/a&gt;    &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;WorksIn4And8&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;a id="rest_code_bbfa8ee3aef94ed1a131e0c2ee0477a0-19" name="rest_code_bbfa8ee3aef94ed1a131e0c2ee0477a0-19" href="https://sandfox.me/php/php-4-oop-in-8.html#rest_code_bbfa8ee3aef94ed1a131e0c2ee0477a0-19"&gt;&lt;/a&gt;    &lt;span class="p"&gt;{&lt;/span&gt;
&lt;a id="rest_code_bbfa8ee3aef94ed1a131e0c2ee0477a0-20" name="rest_code_bbfa8ee3aef94ed1a131e0c2ee0477a0-20" href="https://sandfox.me/php/php-4-oop-in-8.html#rest_code_bbfa8ee3aef94ed1a131e0c2ee0477a0-20"&gt;&lt;/a&gt;        &lt;span class="nb"&gt;error_log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'WorksIn4And8()'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;a id="rest_code_bbfa8ee3aef94ed1a131e0c2ee0477a0-21" name="rest_code_bbfa8ee3aef94ed1a131e0c2ee0477a0-21" href="https://sandfox.me/php/php-4-oop-in-8.html#rest_code_bbfa8ee3aef94ed1a131e0c2ee0477a0-21"&gt;&lt;/a&gt;        &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;__construct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$int&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;a id="rest_code_bbfa8ee3aef94ed1a131e0c2ee0477a0-22" name="rest_code_bbfa8ee3aef94ed1a131e0c2ee0477a0-22" href="https://sandfox.me/php/php-4-oop-in-8.html#rest_code_bbfa8ee3aef94ed1a131e0c2ee0477a0-22"&gt;&lt;/a&gt;    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;a id="rest_code_bbfa8ee3aef94ed1a131e0c2ee0477a0-23" name="rest_code_bbfa8ee3aef94ed1a131e0c2ee0477a0-23" href="https://sandfox.me/php/php-4-oop-in-8.html#rest_code_bbfa8ee3aef94ed1a131e0c2ee0477a0-23"&gt;&lt;/a&gt;
&lt;a id="rest_code_bbfa8ee3aef94ed1a131e0c2ee0477a0-24" name="rest_code_bbfa8ee3aef94ed1a131e0c2ee0477a0-24" href="https://sandfox.me/php/php-4-oop-in-8.html#rest_code_bbfa8ee3aef94ed1a131e0c2ee0477a0-24"&gt;&lt;/a&gt;    &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getInt&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;a id="rest_code_bbfa8ee3aef94ed1a131e0c2ee0477a0-25" name="rest_code_bbfa8ee3aef94ed1a131e0c2ee0477a0-25" href="https://sandfox.me/php/php-4-oop-in-8.html#rest_code_bbfa8ee3aef94ed1a131e0c2ee0477a0-25"&gt;&lt;/a&gt;    &lt;span class="p"&gt;{&lt;/span&gt;
&lt;a id="rest_code_bbfa8ee3aef94ed1a131e0c2ee0477a0-26" name="rest_code_bbfa8ee3aef94ed1a131e0c2ee0477a0-26" href="https://sandfox.me/php/php-4-oop-in-8.html#rest_code_bbfa8ee3aef94ed1a131e0c2ee0477a0-26"&gt;&lt;/a&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;int&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;a id="rest_code_bbfa8ee3aef94ed1a131e0c2ee0477a0-27" name="rest_code_bbfa8ee3aef94ed1a131e0c2ee0477a0-27" href="https://sandfox.me/php/php-4-oop-in-8.html#rest_code_bbfa8ee3aef94ed1a131e0c2ee0477a0-27"&gt;&lt;/a&gt;    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;a id="rest_code_bbfa8ee3aef94ed1a131e0c2ee0477a0-28" name="rest_code_bbfa8ee3aef94ed1a131e0c2ee0477a0-28" href="https://sandfox.me/php/php-4-oop-in-8.html#rest_code_bbfa8ee3aef94ed1a131e0c2ee0477a0-28"&gt;&lt;/a&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;a id="rest_code_bbfa8ee3aef94ed1a131e0c2ee0477a0-29" name="rest_code_bbfa8ee3aef94ed1a131e0c2ee0477a0-29" href="https://sandfox.me/php/php-4-oop-in-8.html#rest_code_bbfa8ee3aef94ed1a131e0c2ee0477a0-29"&gt;&lt;/a&gt;
&lt;a id="rest_code_bbfa8ee3aef94ed1a131e0c2ee0477a0-30" name="rest_code_bbfa8ee3aef94ed1a131e0c2ee0477a0-30" href="https://sandfox.me/php/php-4-oop-in-8.html#rest_code_bbfa8ee3aef94ed1a131e0c2ee0477a0-30"&gt;&lt;/a&gt;&lt;span class="nv"&gt;$obj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;WorksIn4And8&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;48&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;a id="rest_code_bbfa8ee3aef94ed1a131e0c2ee0477a0-31" name="rest_code_bbfa8ee3aef94ed1a131e0c2ee0477a0-31" href="https://sandfox.me/php/php-4-oop-in-8.html#rest_code_bbfa8ee3aef94ed1a131e0c2ee0477a0-31"&gt;&lt;/a&gt;
&lt;a id="rest_code_bbfa8ee3aef94ed1a131e0c2ee0477a0-32" name="rest_code_bbfa8ee3aef94ed1a131e0c2ee0477a0-32" href="https://sandfox.me/php/php-4-oop-in-8.html#rest_code_bbfa8ee3aef94ed1a131e0c2ee0477a0-32"&gt;&lt;/a&gt;&lt;span class="nb"&gt;var_dump&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$obj&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;getInt&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;</summary>
    <category term="php-4" label="php 4"/>
    <category term="php-8" label="php 8"/>
  </entry>
  <entry>
    <title>PHP 8.0 Syntax Showcase</title>
    <id>https://sandfox.me/php/php-8-showcase.html</id>
    <updated>2020-09-30T16:54:00+03:00</updated>
    <published>2020-09-30T16:54:00+03:00</published>
    <author>
      <name>Anton Smirnov</name>
    </author>
    <link rel="alternate" type="text/html" href="https://sandfox.me/php/php-8-showcase.html"/>
    <summary type="html">&lt;p&gt;Since RC1 is released today, I decided to make a small demonstration of PHP 8.0 syntax features.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code php"&gt;&lt;a id="rest_code_0e3bb01a1fec49f1ac572ad98c170ced-1" name="rest_code_0e3bb01a1fec49f1ac572ad98c170ced-1" href="https://sandfox.me/php/php-8-showcase.html#rest_code_0e3bb01a1fec49f1ac572ad98c170ced-1"&gt;&lt;/a&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;
&lt;a id="rest_code_0e3bb01a1fec49f1ac572ad98c170ced-2" name="rest_code_0e3bb01a1fec49f1ac572ad98c170ced-2" href="https://sandfox.me/php/php-8-showcase.html#rest_code_0e3bb01a1fec49f1ac572ad98c170ced-2"&gt;&lt;/a&gt;
&lt;a id="rest_code_0e3bb01a1fec49f1ac572ad98c170ced-3" name="rest_code_0e3bb01a1fec49f1ac572ad98c170ced-3" href="https://sandfox.me/php/php-8-showcase.html#rest_code_0e3bb01a1fec49f1ac572ad98c170ced-3"&gt;&lt;/a&gt;&lt;span class="p"&gt;#[&lt;/span&gt;&lt;span class="nd"&gt;FuncAttribute&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;a id="rest_code_0e3bb01a1fec49f1ac572ad98c170ced-4" name="rest_code_0e3bb01a1fec49f1ac572ad98c170ced-4" href="https://sandfox.me/php/php-8-showcase.html#rest_code_0e3bb01a1fec49f1ac572ad98c170ced-4"&gt;&lt;/a&gt;&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;SplHeap&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="nx"&gt;ArrayObject&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="k"&gt;null&lt;/span&gt; &lt;span class="nv"&gt;$object&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;mixed&lt;/span&gt; &lt;span class="nv"&gt;$value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ArrayAccess&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="k"&gt;false&lt;/span&gt;
&lt;a id="rest_code_0e3bb01a1fec49f1ac572ad98c170ced-5" name="rest_code_0e3bb01a1fec49f1ac572ad98c170ced-5" href="https://sandfox.me/php/php-8-showcase.html#rest_code_0e3bb01a1fec49f1ac572ad98c170ced-5"&gt;&lt;/a&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;a id="rest_code_0e3bb01a1fec49f1ac572ad98c170ced-6" name="rest_code_0e3bb01a1fec49f1ac572ad98c170ced-6" href="https://sandfox.me/php/php-8-showcase.html#rest_code_0e3bb01a1fec49f1ac572ad98c170ced-6"&gt;&lt;/a&gt;    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$object&lt;/span&gt;&lt;span class="o"&gt;?-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;count&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;a id="rest_code_0e3bb01a1fec49f1ac572ad98c170ced-7" name="rest_code_0e3bb01a1fec49f1ac572ad98c170ced-7" href="https://sandfox.me/php/php-8-showcase.html#rest_code_0e3bb01a1fec49f1ac572ad98c170ced-7"&gt;&lt;/a&gt;        &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;RuntimeException&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
&lt;a id="rest_code_0e3bb01a1fec49f1ac572ad98c170ced-8" name="rest_code_0e3bb01a1fec49f1ac572ad98c170ced-8" href="https://sandfox.me/php/php-8-showcase.html#rest_code_0e3bb01a1fec49f1ac572ad98c170ced-8"&gt;&lt;/a&gt;        &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$object&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;a id="rest_code_0e3bb01a1fec49f1ac572ad98c170ced-9" name="rest_code_0e3bb01a1fec49f1ac572ad98c170ced-9" href="https://sandfox.me/php/php-8-showcase.html#rest_code_0e3bb01a1fec49f1ac572ad98c170ced-9"&gt;&lt;/a&gt;    &lt;span class="p"&gt;};&lt;/span&gt;
&lt;a id="rest_code_0e3bb01a1fec49f1ac572ad98c170ced-10" name="rest_code_0e3bb01a1fec49f1ac572ad98c170ced-10" href="https://sandfox.me/php/php-8-showcase.html#rest_code_0e3bb01a1fec49f1ac572ad98c170ced-10"&gt;&lt;/a&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;a id="rest_code_0e3bb01a1fec49f1ac572ad98c170ced-11" name="rest_code_0e3bb01a1fec49f1ac572ad98c170ced-11" href="https://sandfox.me/php/php-8-showcase.html#rest_code_0e3bb01a1fec49f1ac572ad98c170ced-11"&gt;&lt;/a&gt;
&lt;a id="rest_code_0e3bb01a1fec49f1ac572ad98c170ced-12" name="rest_code_0e3bb01a1fec49f1ac572ad98c170ced-12" href="https://sandfox.me/php/php-8-showcase.html#rest_code_0e3bb01a1fec49f1ac572ad98c170ced-12"&gt;&lt;/a&gt;&lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;a id="rest_code_0e3bb01a1fec49f1ac572ad98c170ced-13" name="rest_code_0e3bb01a1fec49f1ac572ad98c170ced-13" href="https://sandfox.me/php/php-8-showcase.html#rest_code_0e3bb01a1fec49f1ac572ad98c170ced-13"&gt;&lt;/a&gt;    &lt;span class="nx"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;object&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;ArrayObject&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;a id="rest_code_0e3bb01a1fec49f1ac572ad98c170ced-14" name="rest_code_0e3bb01a1fec49f1ac572ad98c170ced-14" href="https://sandfox.me/php/php-8-showcase.html#rest_code_0e3bb01a1fec49f1ac572ad98c170ced-14"&gt;&lt;/a&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;RuntimeException&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;a id="rest_code_0e3bb01a1fec49f1ac572ad98c170ced-15" name="rest_code_0e3bb01a1fec49f1ac572ad98c170ced-15" href="https://sandfox.me/php/php-8-showcase.html#rest_code_0e3bb01a1fec49f1ac572ad98c170ced-15"&gt;&lt;/a&gt;    &lt;span class="c1"&gt;// ignore&lt;/span&gt;
&lt;a id="rest_code_0e3bb01a1fec49f1ac572ad98c170ced-16" name="rest_code_0e3bb01a1fec49f1ac572ad98c170ced-16" href="https://sandfox.me/php/php-8-showcase.html#rest_code_0e3bb01a1fec49f1ac572ad98c170ced-16"&gt;&lt;/a&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;</summary>
    <category term="php-8" label="php 8"/>
  </entry>
  <entry>
    <title>Method Calls with Arbitrary Names</title>
    <id>https://sandfox.me/php/curly-braces-call.html</id>
    <updated>2020-07-24T07:20:00+03:00</updated>
    <published>2020-07-24T07:20:00+03:00</published>
    <author>
      <name>Anton Smirnov</name>
    </author>
    <link rel="alternate" type="text/html" href="https://sandfox.me/php/curly-braces-call.html"/>
    <summary type="html">&lt;div&gt;&lt;p&gt;A discovery of the day.
Many people know that you can define and read an object property with an arbitrary name:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code php"&gt;&lt;a id="rest_code_95c90a7cf8bf4e8295617ba796887f31-1" name="rest_code_95c90a7cf8bf4e8295617ba796887f31-1" href="https://sandfox.me/php/curly-braces-call.html#rest_code_95c90a7cf8bf4e8295617ba796887f31-1"&gt;&lt;/a&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;
&lt;a id="rest_code_95c90a7cf8bf4e8295617ba796887f31-2" name="rest_code_95c90a7cf8bf4e8295617ba796887f31-2" href="https://sandfox.me/php/curly-braces-call.html#rest_code_95c90a7cf8bf4e8295617ba796887f31-2"&gt;&lt;/a&gt;
&lt;a id="rest_code_95c90a7cf8bf4e8295617ba796887f31-3" name="rest_code_95c90a7cf8bf4e8295617ba796887f31-3" href="https://sandfox.me/php/curly-braces-call.html#rest_code_95c90a7cf8bf4e8295617ba796887f31-3"&gt;&lt;/a&gt;&lt;span class="nv"&gt;$s&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="k"&gt;stdClass&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;a id="rest_code_95c90a7cf8bf4e8295617ba796887f31-4" name="rest_code_95c90a7cf8bf4e8295617ba796887f31-4" href="https://sandfox.me/php/curly-braces-call.html#rest_code_95c90a7cf8bf4e8295617ba796887f31-4"&gt;&lt;/a&gt;&lt;span class="nv"&gt;$s&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s1"&gt;'any string here'&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;123&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;a id="rest_code_95c90a7cf8bf4e8295617ba796887f31-5" name="rest_code_95c90a7cf8bf4e8295617ba796887f31-5" href="https://sandfox.me/php/curly-braces-call.html#rest_code_95c90a7cf8bf4e8295617ba796887f31-5"&gt;&lt;/a&gt;&lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$s&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s1"&gt;'any string here'&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt; &lt;span class="c1"&gt;// 123&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="https://sandfox.me/php/curly-braces-call.html"&gt;Read more…&lt;/a&gt; (1 min remaining to read)&lt;/p&gt;&lt;/div&gt;</summary>
  </entry>
  <entry>
    <title>I released the first PHP 8 library ever</title>
    <id>https://sandfox.me/php/first-php-8-library.html</id>
    <updated>2020-07-03T22:12:00+03:00</updated>
    <published>2020-07-03T22:12:00+03:00</published>
    <author>
      <name>Anton Smirnov</name>
    </author>
    <link rel="alternate" type="text/html" href="https://sandfox.me/php/first-php-8-library.html"/>
    <summary type="html">&lt;p&gt;At least among the libraries listed on the Packagist.
On this Tuesday &lt;a class="reference external" href="https://packagist.org/packages/sandfoxme/bencode"&gt;sandfoxme/bencode&lt;/a&gt; was updated to 2.0 that requires PHP 8 as a minimum.
While it was meant mostly as an experiment and a joke,
it allowed me to try some new features like &lt;code class="docutils literal"&gt;Stringable&lt;/code&gt; interface and remove some old compatibility handling
thanks to &lt;code class="docutils literal"&gt;mbstring.func_overload&lt;/code&gt; being finally removed.&lt;/p&gt;</summary>
    <category term="php-8" label="php 8"/>
  </entry>
  <entry>
    <title>sabre/xml</title>
    <id>https://sandfox.me/php/sabre-xml.html</id>
    <updated>2020-06-10T00:00:00+03:00</updated>
    <published>2020-06-10T00:00:00+03:00</published>
    <author>
      <name>Anton Smirnov</name>
    </author>
    <link rel="alternate" type="text/html" href="https://sandfox.me/php/sabre-xml.html"/>
    <summary type="html">&lt;div&gt;&lt;p&gt;An awesome discovery of today was made in an article titled &lt;a class="reference external" href="https://evertpot.com/an-xml-library-you-may-not-hate/"&gt;An XML library for PHP you may not hate&lt;/a&gt;.
As an unexpected twist I really didn't hate it, in fact it helped me to solve a problem that I had.
It is called &lt;a class="reference external" href="https://sabre.io/xml/"&gt;sabre/xml&lt;/a&gt; and it's a part of the &lt;a class="reference external" href="https://sabre.io/"&gt;sabre/dav&lt;/a&gt; project.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://sandfox.me/php/sabre-xml.html"&gt;Read more…&lt;/a&gt; (2 min remaining to read)&lt;/p&gt;&lt;/div&gt;</summary>
    <category term="sabredav" label="sabre/dav"/>
    <category term="xml" label="xml"/>
  </entry>
  <entry>
    <title>Install Composer in Docker</title>
    <id>https://sandfox.me/php/install-composer-in-docker.html</id>
    <updated>2023-01-11T10:14:00+02:00</updated>
    <published>2020-04-02T11:26:00+03:00</published>
    <author>
      <name>Anton Smirnov</name>
    </author>
    <link rel="alternate" type="text/html" href="https://sandfox.me/php/install-composer-in-docker.html"/>
    <summary type="html">&lt;div&gt;&lt;aside class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;You can still use it to install Composer programmatically but for Docker there is &lt;a class="reference external" href="https://sandfox.me/php/install-composer-in-docker-2.html"&gt;an easier way now&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;p&gt;Here is a small snippet adapted from the &lt;a class="reference external" href="https://getcomposer.org/doc/faqs/how-to-install-composer-programmatically.md"&gt;official instruction&lt;/a&gt;:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code docker"&gt;&lt;a id="rest_code_d2574b6827e048f5a7cb28a7a5547108-1" name="rest_code_d2574b6827e048f5a7cb28a7a5547108-1" href="https://sandfox.me/php/install-composer-in-docker.html#rest_code_d2574b6827e048f5a7cb28a7a5547108-1"&gt;&lt;/a&gt;&lt;span class="k"&gt;RUN&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;php&lt;span class="w"&gt; &lt;/span&gt;-r&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"copy('https://composer.github.io/installer.sig', '/tmp/composer.sig');"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;a id="rest_code_d2574b6827e048f5a7cb28a7a5547108-2" name="rest_code_d2574b6827e048f5a7cb28a7a5547108-2" href="https://sandfox.me/php/install-composer-in-docker.html#rest_code_d2574b6827e048f5a7cb28a7a5547108-2"&gt;&lt;/a&gt;&lt;span class="w"&gt;    &lt;/span&gt;php&lt;span class="w"&gt; &lt;/span&gt;-r&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"copy('https://getcomposer.org/installer', '/tmp/composer-setup.php');"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;a id="rest_code_d2574b6827e048f5a7cb28a7a5547108-3" name="rest_code_d2574b6827e048f5a7cb28a7a5547108-3" href="https://sandfox.me/php/install-composer-in-docker.html#rest_code_d2574b6827e048f5a7cb28a7a5547108-3"&gt;&lt;/a&gt;&lt;span class="w"&gt;    &lt;/span&gt;php&lt;span class="w"&gt; &lt;/span&gt;-r&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'$expected = file_get_contents("/tmp/composer.sig"); $actual = hash_file("sha384", "/tmp/composer-setup.php"); exit(intval(!hash_equals($expected, $actual)));'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;a id="rest_code_d2574b6827e048f5a7cb28a7a5547108-4" name="rest_code_d2574b6827e048f5a7cb28a7a5547108-4" href="https://sandfox.me/php/install-composer-in-docker.html#rest_code_d2574b6827e048f5a7cb28a7a5547108-4"&gt;&lt;/a&gt;&lt;span class="w"&gt;    &lt;/span&gt;php&lt;span class="w"&gt; &lt;/span&gt;/tmp/composer-setup.php&lt;span class="w"&gt; &lt;/span&gt;--install-dir&lt;span class="o"&gt;=&lt;/span&gt;/usr/local/bin&lt;span class="w"&gt; &lt;/span&gt;--filename&lt;span class="o"&gt;=&lt;/span&gt;composer&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;a id="rest_code_d2574b6827e048f5a7cb28a7a5547108-5" name="rest_code_d2574b6827e048f5a7cb28a7a5547108-5" href="https://sandfox.me/php/install-composer-in-docker.html#rest_code_d2574b6827e048f5a7cb28a7a5547108-5"&gt;&lt;/a&gt;&lt;span class="w"&gt;    &lt;/span&gt;chmod&lt;span class="w"&gt; &lt;/span&gt;+x&lt;span class="w"&gt; &lt;/span&gt;/usr/local/bin/composer&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;a id="rest_code_d2574b6827e048f5a7cb28a7a5547108-6" name="rest_code_d2574b6827e048f5a7cb28a7a5547108-6" href="https://sandfox.me/php/install-composer-in-docker.html#rest_code_d2574b6827e048f5a7cb28a7a5547108-6"&gt;&lt;/a&gt;&lt;span class="w"&gt;    &lt;/span&gt;rm&lt;span class="w"&gt; &lt;/span&gt;/tmp/composer-setup.php&lt;span class="w"&gt; &lt;/span&gt;/tmp/composer.sig
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;It doesn't require a script file, doesn't deal with environment variables, and doesn't depend on the shell.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://sandfox.me/php/install-composer-in-docker.html"&gt;Read more…&lt;/a&gt; (1 min remaining to read)&lt;/p&gt;&lt;/div&gt;</summary>
    <category term="composer" label="composer"/>
    <category term="docker" label="docker"/>
  </entry>
  <entry>
    <title>PHP 7.4: Splat Inconsistency</title>
    <id>https://sandfox.me/php/splat-inconsistency.html</id>
    <updated>2019-08-29T21:52:00+03:00</updated>
    <published>2019-08-29T21:52:00+03:00</published>
    <author>
      <name>Anton Smirnov</name>
    </author>
    <link rel="alternate" type="text/html" href="https://sandfox.me/php/splat-inconsistency.html"/>
    <summary type="html">&lt;div&gt;&lt;p&gt;PHP 7.4 has this great new feature: splat operator now works in array expressions.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://sandfox.me/php/splat-inconsistency.html"&gt;Read more…&lt;/a&gt; (1 min remaining to read)&lt;/p&gt;&lt;/div&gt;</summary>
    <category term="php-74" label="php 7.4"/>
    <category term="splat-operator" label="splat operator"/>
    <category term="wtf" label="wtf?"/>
  </entry>
  <entry>
    <title>Encryptor</title>
    <id>https://sandfox.me/php/php-encryptor.html</id>
    <updated>2019-08-24T03:50:00+03:00</updated>
    <published>2019-08-24T03:50:00+03:00</published>
    <author>
      <name>Anton Smirnov</name>
    </author>
    <link rel="alternate" type="text/html" href="https://sandfox.me/php/php-encryptor.html"/>
    <summary type="html">&lt;p&gt;Created a simple cli file encryptor using &lt;a class="reference external" href="https://libsodium.gitbook.io/"&gt;libsodium&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The app can create a password-protected file encoded with &lt;a class="reference external" href="https://en.wikipedia.org/wiki/Salsa20"&gt;XSalsa20&lt;/a&gt; and &lt;a class="reference external" href="https://en.wikipedia.org/wiki/Argon2"&gt;Argon2id&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;See my dev portal: &lt;a class="reference external" href="https://sandfox.dev/php/encryptor.html"&gt;https://sandfox.dev/php/encryptor.html&lt;/a&gt;&lt;/p&gt;</summary>
    <category term="argon2id" label="argon2id"/>
    <category term="encryption" label="encryption"/>
    <category term="sodium" label="sodium"/>
    <category term="xsalsa20" label="xsalsa20"/>
  </entry>
  <entry>
    <title>Composer Yaml</title>
    <id>https://sandfox.me/php/composer-yaml.html</id>
    <updated>2019-04-19T22:00:00+03:00</updated>
    <published>2019-04-19T22:00:00+03:00</published>
    <author>
      <name>Anton Smirnov</name>
    </author>
    <link rel="alternate" type="text/html" href="https://sandfox.me/php/composer-yaml.html"/>
    <summary type="html">&lt;p&gt;My new library to allow composer to read config from YAML file.
There is some demand in comments for composer config but &lt;a class="reference external" href="https://github.com/composer/composer/issues/440"&gt;the developers are not interested&lt;/a&gt;
and most 3rd party attempts to solve it are limited to yaml2json converters.&lt;/p&gt;
&lt;p&gt;I tried a slightly different approach.
There is a command in the composer itself that changes the way the config is read: &lt;code class="docutils literal"&gt;composer global&lt;/code&gt;.
During its execution it changes current working directory, resets composer state, and forces the composer
to read config from another directory.&lt;/p&gt;
&lt;p&gt;What I tried to do:
I put yaml2json converter in place of &lt;code class="docutils literal"&gt;global&lt;/code&gt;'s directory changing code, and it seems it worked.
Of course, some things got broken like any command that tries to change composer.json will no longer have any effect,
however many people don't use them and it may be an acceptable tradeoff for using yml-based config.&lt;/p&gt;
&lt;p&gt;You can find the project on my new dev website: &lt;a class="reference external" href="https://sandfox.dev/php/composer-yaml.html"&gt;https://sandfox.dev/php/composer-yaml.html&lt;/a&gt;&lt;/p&gt;</summary>
    <category term="composer" label="composer"/>
    <category term="yaml" label="yaml"/>
  </entry>
  <entry>
    <title>Private Composer Repo with GitLab and Satis</title>
    <id>https://sandfox.me/php/satis-gitlab.html</id>
    <updated>2024-05-01T21:05:00+03:00</updated>
    <published>2018-03-09T16:44:00+02:00</published>
    <author>
      <name>Anton Smirnov</name>
    </author>
    <link rel="alternate" type="text/html" href="https://sandfox.me/php/satis-gitlab.html"/>
    <summary type="html">&lt;div&gt;&lt;p&gt;You can easily create your own composer repository using Satis and GitLab.
I will use global &lt;a class="reference external" href="https://gitlab.com"&gt;https://gitlab.com&lt;/a&gt; but it should be most useful for private corporate GitLab installations.
You will need CI and Pages&lt;/p&gt;
&lt;p&gt;&lt;a href="https://sandfox.me/php/satis-gitlab.html"&gt;Read more…&lt;/a&gt; (1 min remaining to read)&lt;/p&gt;&lt;/div&gt;</summary>
    <category term="composer" label="composer"/>
    <category term="gitlab" label="gitlab"/>
    <category term="satis" label="satis"/>
  </entry>
  <entry>
    <title>PhpStorm Advanced Metadata Exporter</title>
    <id>https://sandfox.me/php/phpstorm-metadata.html</id>
    <updated>2018-03-06T07:54:00+02:00</updated>
    <published>2018-03-06T07:54:00+02:00</published>
    <author>
      <name>Anton Smirnov</name>
    </author>
    <link rel="alternate" type="text/html" href="https://sandfox.me/php/phpstorm-metadata.html"/>
    <summary type="html">&lt;p&gt;As a Silex user I liked &lt;a class="reference external" href="https://github.com/Sorien/silex-pimple-dumper"&gt;Pimple Container Dumper&lt;/a&gt; that worked with &lt;a class="reference external" href="https://github.com/Sorien/silex-idea-plugin"&gt;Silex Idea Plugin&lt;/a&gt; to enable code completion
for Pimple DI in PhpStorm. But now with Silex EOL'd I have to move to Slim.&lt;/p&gt;
&lt;p&gt;I've found no such projects so I had to write my own. Here it is: &lt;a class="reference external" href="https://sandfox.dev/php/phpstorm-metadata-export.html"&gt;sandfoxme/phpstorm-metadata-export&lt;/a&gt;.
It currently supports exporting data from Pimple and has 3 integration middlewares: for Slim, for Silex and
for Psr-15 compatible frameworks.&lt;/p&gt;
&lt;p&gt;P.S. Code completion support for ArrayAccess containers seem to be currently broken
in PhpStorm (&lt;a class="reference external" href="https://youtrack.jetbrains.com/issue/WI-33309"&gt;WI-33309&lt;/a&gt;, &lt;a class="reference external" href="https://youtrack.jetbrains.com/issue/WI-35503"&gt;WI-35503&lt;/a&gt;).
So I don't currently recommend replacing Silex Idea Plugin with this library unless you use Pimple in Psr-11 compliant
way (like Slim does by default)&lt;/p&gt;</summary>
    <category term="code-completion" label="code completion"/>
    <category term="phpstorm" label="phpstorm"/>
    <category term="pimple" label="pimple"/>
    <category term="silex" label="silex"/>
    <category term="slim" label="slim"/>
  </entry>
  <entry>
    <title>Composer Viz</title>
    <id>https://sandfox.me/php/composer-viz.html</id>
    <updated>2017-08-06T12:12:00+03:00</updated>
    <published>2017-08-06T12:12:00+03:00</published>
    <author>
      <name>Anton Smirnov</name>
    </author>
    <link rel="alternate" type="text/html" href="https://sandfox.me/php/composer-viz.html"/>
    <summary type="html">&lt;p&gt;A tool inspired by &lt;a class="reference external" href="https://bundler.io/v1.3/bundle_viz.html"&gt;&lt;code class="docutils literal"&gt;bundle viz&lt;/code&gt; command&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Just look at its selfie:&lt;/p&gt;
&lt;p&gt;&lt;img alt="selfie" class="invert-when-dark" src="https://sandfox.me/images/php/composer-viz/selfie.svg" style="width: 100%;"&gt;&lt;/p&gt;
&lt;p&gt;Get it on my dev site: &lt;a class="reference external" href="https://sandfox.dev/php/composer-viz.html"&gt;https://sandfox.dev/php/composer-viz.html&lt;/a&gt;&lt;/p&gt;</summary>
    <category term="bundler" label="bundler"/>
    <category term="composer" label="composer"/>
    <category term="graphviz" label="graphviz"/>
  </entry>
  <entry>
    <title>PHP Access Private Methods and Fields</title>
    <id>https://sandfox.me/php/php-private-access.html</id>
    <updated>2016-11-16T21:00:00+02:00</updated>
    <published>2016-11-16T21:00:00+02:00</published>
    <author>
      <name>Anton Smirnov</name>
    </author>
    <link rel="alternate" type="text/html" href="https://sandfox.me/php/php-private-access.html"/>
    <summary type="html">&lt;div&gt;&lt;p&gt;These two simple functions can come in handy as helpers for something like &lt;a class="reference external" href="http://psysh.org/"&gt;PsySH&lt;/a&gt;.
PHP &amp;gt;= 7.0 is required.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://sandfox.me/php/php-private-access.html"&gt;Read more…&lt;/a&gt; (1 min remaining to read)&lt;/p&gt;&lt;/div&gt;</summary>
    <category term="debug" label="debug"/>
  </entry>
</feed>
