<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <title><![CDATA[Roman Pronskiy]]></title>
    <link href="https://pronskiy.com/atom.xml" rel="self"/>
    <link href="https://pronskiy.com/"/>
    <updated>2026-09-05T20:59:45+00:00</updated>
    <id>https://pronskiy.com/</id>
        <generator uri="http://sculpin.io/">Sculpin</generator>
            <entry>
            <title type="html"><![CDATA[Turn Any PHP Script into a Native Single-File Binary]]></title>
            <link href="https://pronskiy.com/blog/php-script-as-binary/"/>
            <updated>2023-10-25T00:00:00+00:00</updated>
            <id>https://pronskiy.com/blog/php-script-as-binary/</id>
            <content type="html"><![CDATA[<p>For years, I've dreamed of being able to create PHP CLI scripts that can be easily distributed without requiring users to have PHP installed on their machines.</p>

<p>But a scripting language needs an interpreter, they said. Not anymore! PHP still can't be compiled for real, there is a trick you can use.</p>

<h2 id="tl%3Bdr">TL;DR</h2>

<ul>
<li>There is a project <a href="https://github.com/crazywhalecc/static-php-cli">crazywhalecc/static-php-cli</a>  that allows you to compile PHP statically.</li>
<li>Under the hood it uses <a href="https://github.com/dixyes/phpmicro">dixyes/phpmicro</a> – it is a special static PHP binary which you can “glue” to any PHP script.</li>
<li>What remains is to build the application in PHAR and attach a statically-compiled interpreter binary to it.</li>
</ul>

<h2 id="show-me-the-code%21">Show me the code!</h2>

<p>Here's a minimal PoC.</p>

<p>First, let’s download a pre-built <em>phpmicro</em> binary from the <em>static-php-cli</em> website. Since I’m on macOS, I’m using the following link:</p>

<pre><code class="Bash">curl -O https://dl.static-php.dev/static-php-cli/common/php-8.2.10-micro-macos-aarch64.tar.gz

tar -xvf php-8.2.10-micro-macos-aarch64.tar.gz
</code></pre>

<p>Now let’s create a simple application in <code>index.php</code>:</p>

<pre><code class="php">&lt;?php

echo "hello world";
</code></pre>

<p>And we are ready to glue it with a PHP binary:</p>

<pre><code class="Bash">cat ./micro.sfx index.php &gt; indexbin &amp;&amp; chmod 0755 ./indexbin
</code></pre>

<p>And voilà! Run it:</p>

<pre><code class="Bash">./indexbin
</code></pre>

<figure>
  <img src="/assets/img/blog/phin.gif" alt=""/>
  <figcaption></figcaption>
</figure>

<h2 id="poc-is-nice%2C-but-will-this-work-for-real-cli-applications%3F">PoC is nice, but will this work for real CLI applications?</h2>

<p>Yes, but there may be challenges.</p>

<p>For a real CLI app, you would most likely need to pack the app in a PHAR file. For this, you'd typically use <a href="https://github.com/box-project/box">box-project/box</a>.</p>

<p>I successfully created a basic "hello world" application with this method. You can find it in this repo:
<a href="https://github.com/pronskiy/phin">github.com/pronskiy/phin</a></p>

<p>However, when I attempted to integrate something more substantial like <code>symfony/console</code>, I encountered an error:</p>

<pre><code>zend_mm_heap corrupted
Abort trap: 6
</code></pre>

<p>It looks fixable, but I haven't looked into exactly what causes it yet.</p>

<p>There will probably be other difficulties with more complex applications.</p>

<h2 id="what-about-platform-support%3F-linux-%2F-macos-%2F-windows-%3F">What about platform support? Linux / macOS / Windows ?</h2>

<p>In the PoC above, I just download the <em>phpmicro</em> archive from here:
<a href="https://dl.static-php.dev/static-php-cli/common/">https://dl.static-php.dev/static-php-cli/common/</a></p>

<p>But for real-world applications, you would want to build it on a CI for all platforms at once.</p>

<p>Micro-php is compatible with the popular Linux, macOS, and Windows platforms. Yet, as of now, GitHub Actions doesn't offer free builds for the ARM architecture, like macOS on M1/M2. But alternative CI/CD providers are available, or you could opt for a paid solution.</p>

<p>On a side note, pooling resources in a single repository to fund micro-php builds might be a viable solution. ;-).</p>

<h2 id="future-prospects-of-this-method%3F">Future prospects of this method?</h2>

<p>Ideally, all of this can be organized as a ready-made GitHub Action, which you simply add to your repository, and for each release of your CLI-app you will get binaries for all platforms. Users would be able to download and use your CLI binaries without additional dependencies.</p>

<blockquote>
  <p><a href="https://github.com/crazywhalecc/static-php-cli">Static-php-cli</a> is <a href="https://twitter.com/dunglas/status/1696448021234438518">used</a> in <a href="https://github.com/dunglas/frankenphp">FrankenPHP</a>. Notably, Kevin Dunglas, the author of FrankenPHP, actively contributes to static-php-cli.</p>
</blockquote>
]]></content>
        </entry>
            <entry>
            <title type="html"><![CDATA[Generics via Attributes in PHP &amp;mdash; Can We Have Them?]]></title>
            <link href="https://pronskiy.com/blog/generics-via-attributes-in-php/"/>
            <updated>2022-10-31T00:00:00+00:00</updated>
            <id>https://pronskiy.com/blog/generics-via-attributes-in-php/</id>
            <content type="html"><![CDATA[<p><strong>tl;dr:</strong> How about using generics in PHP attributes?</p>

<pre><code class="php">#[&lt;T&gt;]
class Stack
{
    public function push(#[&lt;T&gt;] mixed $item): void
    {
    }

    public function pop(): #[&lt;T&gt;] mixed
    {
    }
}
</code></pre>

<p>Native generics. Will they be in PHP or not? Does PHP need them at all? We'll leave this speculation for the next time, but today let's discuss what generics might look like in PHP attributes.</p>

<figure>
  <img src="https://pbs.twimg.com/media/Ffk5-9LWAAcZhwI?format=jpg" alt="Meme: Why can't we have generics in PHP?" width="300"/>
  <figcaption><a href="https://twitter.com/brendt_gd/status/1583360505766285314">https://twitter.com/brendt_gd/status/1583360505766285314</a></figcaption>
</figure>

<h2 id="status-phpdoc-quo">Status-PHPDoc-quo</h2>

<p>Nikita Popov did a comprehensive research on generics in PHP and shared detailed results <a href="https://github.com/PHPGenerics/php-generics-rfc/issues/45">here</a>. Nikita also wrote a summary on Reddit during an <a href="https://www.reddit.com/r/PHP/comments/j65968/ama_with_the_phpstorm_team_from_jetbrains_on/">AMA with the PhpStorm team</a>:</p>

<iframe id="reddit-embed" src="https://www.redditmedia.com/r/PHP/comments/j65968/ama_with_the_phpstorm_team_from_jetbrains_on/g83skiz/?depth=1&amp;showmore=false&amp;embed=true&amp;showmedia=false" sandbox="allow-scripts allow-same-origin allow-popups" style="border: none;" height="200" width="640" scrolling="no"></iframe>

<p>The conclusion that Nikita came to is that there are only three ways to implement generics, and none of them will work in PHP. Or rather, it is possible to implement them, but each of them has significant drawbacks.</p>

<p>Nevertheless, the implementation of erased quasi-generics already exists today. I'm talking about PHPDoc annotations.</p>

<p>Although there is no official standard, the popular static analyzers <a href="https://phpstan.org/">PHPStan</a> and <a href="https://psalm.dev/">Psalm</a>, as well as <a href="https://blog.jetbrains.com/phpstorm/2021/12/phpstorm-2021-3-release/#more_for_generics">PhpStorm</a>, support a syntax that can generally be called well-established.</p>

<figure>
  <img src="https://blog.jetbrains.com/wp-content/uploads/2021/12/generics_contructor.gif" alt=""/>
  <figcaption></figcaption>
</figure>

<p>What prevents people from using generics via annotations? I just posed this question on Twitter. They are, after all, essentially erased generics, pretty much like in Python, for instance.</p>

<p>There were some constructive and substantive concerns raised in the replies:</p>

<blockquote class="twitter-tweet"><p lang="en" dir="ltr">Nothing stops me from using phpdoc generics, &amp; I use them, but without native language support, I can?t enforce them on downstream users of my libraries, so I still have to write a lot of validation code to check types.<br><br>I think this would also be a problem with erased generics.</p>&mdash; Ben Ramsey @ramsey@phpc.social (@ramsey) <a href="https://twitter.com/ramsey/status/1582461944401133568?ref_src=twsrc%5Etfw">October 18, 2022</a></blockquote>

<p>There were also comments about the usability of such generics. But what annoys me, and what the Twitter mob didn't note, is that in modern PHP code you have to use both attributes and PHPDoc annotations simultaneously.</p>

<h2 id="generics%2C-why-no-attributes%3F">Generics, why no attributes?</h2>

<p>The PHPDoc annotations are unstructured strings. They were <a href="https://wiki.php.net/rfc/attributes_v2">meant to be</a> replaced by attributes, which are part of the language, and set a strict format for metadata in PHP.</p>

<p>However, in the case of generics, the attributes look terrible:</p>

<pre><code class="php">/** @template T of object */
class Queue
{
    /** @var array&lt;int,T&gt; */
    private array $queue = [];

    /** @param T $item */
    public function add($item): void {}

    /** @return T */
    public function next() {}
}

// The same with current attributes =&gt; 

#[Template("T", "object")]
class Queue
{
    #[Type("array&lt;int,T&gt;")] 
    private array $queue = [];

    public function add(#[Type("T")] $item): void {}

    #[Type("T")]
    public function next() {}
}
</code></pre>

<p>In addition, the attributes only work on declarations but not on call-site. Consequently, you cannot do this:</p>

<pre><code class="php">/** @var Queue&lt;Person&gt; $personQueue */
$personQueue = new Queue();

// The same with current attributes =&gt;

#[Type("Queue&lt;Person&gt;")]
$personQueue = new Queue();
</code></pre>

<h2 id="generics-in-attributes-syntax-rfc">Generics in attributes syntax RFC</h2>

<p>What if generics looked prettier but remained in attributes?</p>

<pre><code class="php">#[&lt;T&gt;]
class Stack
{
    public function push(#[&lt;T&gt;] mixed $item): void
    {
    }

    public function pop(): #[&lt;T&gt;] mixed
    {
    }
}
</code></pre>

<h3 id="pros%3A">Pros:</h3>

<ul>
<li>PHP code remains untouched and BC breaks are not added</li>
<li>The code becomes cleaner and prettier (subjectively)</li>
<li>Static analyzers work as with PHPDoc</li>
<li>Information about generics is available in the language itself (!)</li>
</ul>

<h3 id="cons%3A">Cons:</h3>

<ul>
<li>Type information still in two places</li>
<li>Hacky syntax (?)</li>
<li>What else?</li>
</ul>

<h2 id="why-not-all-the-way-native-generics-with-%60%60%3F">Why not all the way native generics with <code>&lt;T&gt;</code>?</h2>

<p>Adding native erased generics we get to the inconsistency that some types are not checked at runtime. The attributes never gave a promise to change runtime behavior.</p>

<h2 id="but-what-about-runtime-checks%3F">But what about runtime checks?</h2>

<p>Since generics information is contained in attributes, it is available at runtime! This means that type checks <em>can</em> be implemented in userland in PHP. Such checks will probably be slower than the native ones, but the main advantage is that they can be entirely optional!</p>

<p>That means you can have early runtime checks in your local and test environments. For production you can disable such runtime checks and get performance boost there.</p>

<h2 id="%F0%9F%9A%A7-static-analysis-poc">🚧 Static Analysis PoC</h2>

<p><strike>Here is a fork of Nikita's PHP parser that demonstrates this concept. And here is the PHPStan fork with the ability to use this syntax.</strike></p>

<h2 id="what-do-you-think%3F">What do you think?</h2>

<ul>
<li>How do you like this syntax?</li>
<li>What problems do you see with this?</li>
<li>What are other benefits and drawbacks?</li>
</ul>

<hr />

<p><br></p>

<p>Many thanks to Dave Liddament whose talk at the <a href="https://twitter.com/phpconference">International PHP Conference</a> in Munich inspired this idea. It literally came up during our discussion after Dave's talk:</p>

<blockquote class="twitter-tweet"><p lang="en" dir="ltr">It seems PHP generics is a hot topic at the moment. <a href="https://twitter.com/pronskiy?ref_src=twsrc%5Etfw">@pronskiy</a> following on from our conversation at IPC, has the syntax #&lt;&gt; been suggested? <br><br>Would this work for adding type information for static analysis?<br><br>See more in gist: <a href="https://t.co/IOzSGgt1Xo">https://t.co/IOzSGgt1Xo</a><br><br>1/n <a href="https://t.co/BHkqP3cr07">https://t.co/BHkqP3cr07</a> <a href="https://t.co/g2eIzm1ndT">pic.twitter.com/g2eIzm1ndT</a></p>&mdash; Dave Liddament (@DaveLiddament) <a href="https://twitter.com/DaveLiddament/status/1586726336961339392?ref_src=twsrc%5Etfw">October 30, 2022</a></blockquote>

<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
<div
    class="thread-container"
    data-reddit-thread=""
    data-reddit-search="PHP"
    data-reddit-max-depth="5"
    data-reddit-show-content="true"
    data-reddit-show-controls="true"
></div>
<script>window.REDDITIFY_PROXY_URL = 'https://redditify-proxy.root-8f3.workers.dev';</script>
<link rel="stylesheet" href="https://unpkg.com/redditify/dist/redditify.css">
<script src="https://unpkg.com/redditify/dist/redditify.min.js"></script>
]]></content>
        </entry>
    </feed>