PHP-PDS: Interview on Voices of the ElePHPant

My good friend Cal Evans interviewed me about the PHP-PDS initiative and its first offering, pds/skeleton last week; here it is for you to enjoy.


While we’re here, you might want to check out his virtual user group Nomad PHP, and the series of one-day virtual training conferences at DayCamp4Developers, because you’ll probably learn something useful there.

PECL Request Extension: Beta 1 Released!

I am happy to announce that the PECL extension for server-side request and response objects has reached beta status! (Documentation here.)

This release adds four new read-only properties to the ServerRequest object:

  • $forwarded is an array representation of $_SERVER['HTTP_FORWARDED'] (cf. the Forwarded HTTP Extension),

  • $forwardedFor is an array computed from treating $_SERVER['HTTP_X_FORWARDED_FOR'] as comma-separated values.

  • $forwardedHost is the $_SERVER['HTTP_X_FORWARDED_HOST'] value, and

  • $forwardedProto is $_SERVER['HTTP_X_FORWARDED_PROTO'] value.

If you use trusted proxies a lot in your work, you can use those values to compute the “real” client IP address in your application.

This completes the intended initial functionality of the extension. You should install it and try it out, because it might be make your work easier.

Package Development Standards: “pds/skeleton” Now Open For Review!

The new Package Development Standards initiative is proud to present its first publication, pds/skeleton (and the related research) for public review. If you are a package author, you are invited to post your comments and criticisms of the publication as issues on the relevant Github repository.

The pds/skeleton publication describes a set of standard top-level PHP package directories and files. If you are an author of more than three packages on Packagist, chances are you already follow the standard! That’s because PDS initiative researches the PHP package ecosystem to recognize commonly adopted development practices. (See this list of over than 47,000 packages; if your package is there, it has been tentatively noted as already compliant.)

The public review period will last at least 2 weeks, perhaps longer. If there are no substantial errors revealed during that time, the standard will advance to “beta” status for adoption, and then to “stable” if no further errors are discovered in use.

Meanwhile, if you review the publication and determine that your package follows it, you should add pds/skeleton to your Composer “require-dev” block, because that will help the initiative track formal adoption rates.

PHP file_get_contents() HTTPS/SSL error on Mac OS

Problem on Mac OS Sierra (10.12.x): Using file_get_contents() for an https resource fails with error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed.

This solution appears to be legit, although I am not primarily a security guy, so real security folks should chime in if they seem something untoward:

% sudo mkdir -p /usr/local/libressl/etc/ssl/certs
% sudo curl -o /usr/local/libressl/etc/ssl/cert.pem

This creates the default_cert_file directories and imports the latest certificate store from

Source: PHP on macOS Sierra can’t access SSL data –

Independent Packages and Subtree Splits

You’ll sometimes see a PHP package hosted in a Github repository with the heading or subtitle “[READ ONLY] Subtree Split”. This indicates that the package is actually copied from another codebase (usually a framework) and is not intended to be worked on separately from that other codebase.

As such, a “subtree split” is not necessarily a sign of an independent package. Using a subtree split to publish a package says to me that the authors’ concentration is on the framework-as-a-whole, not on the package in-and-of- itself.

For example, Symfony does subtree splits for its components, as does Laravel for its Illuminate components. Those packages from the frameworks are not developed independently; they only move forward as part of the whole framework.

In these cases, you often end up with composer.json in the framework origin directories, which is not something I generally expect. Further, the framework subdirectories may have their own src/tests/docs/etc. directories. They are there so that the subtree split can have them available at their own top level, but in the origin framework, it is again something I find unexpected.

I say: if you’re going to advertise independent packages, actually write them independently. Let them be their own thing. Aura has done it that way since its beginning, and Zend Framework converted to that approach in version 3. Then you can compose the truly independent packages into a framework, instead of subtree-splitting your framework into pseudo-independent packages that are still bound to the origin framework development and release process.

PHP ssh2.sftp opendir/readdir fix

This bug related to the PECL ssh2 extension bit us yesterday, so this post is a public service announcement that will (hopefully) save you from writing your own workaround like I almost did.

Problem: PHP 5.6.28 (and apparently 7.0.13) introduced a security fix to URL parsing, that caused the string interpolation of the $sftp resource handle to no-longer be recognized as a valid URL. In turn, that causes opendir(), readdir(), etc. to fail when you use an $sftp resource in the path string, after an upgrade to one of those PHP versions.

Solution: Instead of using "ssh2.sftp://$sftp" as a stream path, convert $sftp to an integer like so: "ssh2.sftp://" . intval($sftp) . "/". Then it will work just fine.

Thanks to the people who fixed the URL parsing security flaw, thanks to the people who wrote the PECL ssh2 extension, and thanks to the people who provided the fix.

Conserving On The Wrong Resource

(This is a blog post I’ve had in a “write-me!” folder for years; I am now publishing it in its unfinished form to get it off my mind.)

Programmers are acutely aware of their limited resources: CPU, memory, storage, requests-per-second, screen space, line length, and so on. If programmers are aware of a resource constraint, they conserve on it; sometimes they call this “optimizing.”

Are you aware of a loop? Then you try to “optimize” it, or conserve on it, e.g. by not using a count() in the loop declaration.

Are you aware of the number of lines? You might try to conserve on the number of lines, perhaps by removing blank lines (especially in docblocks).

Are you aware of aware of the size of an array, or the number of objects in the system, and so on? You try to conserve on those, to reduce their number.

But this is sometimes a trap, because you conserve or optimize on a low value
resource you are aware of, at the cost of not conserving on a high-value resource you are not aware of. For example, optimizing a for loop by not using count() in its declaration will have little impact if the loop is executing queries against an SQL database.

Lesson: conserve on high-value resources that you may not be aware of, not low-value ones that are obvious but of little consequence.

The PHP 7 “Request” Extension

tl;dr: The new request extension provides server-side request and response objects for PHP 7. Use it as a replacement object for request superglobals and response functions. An equivalent PHP 5 version is available in userland as pmjones/request.

You’re tired of dealing with the $_GET, $_POST, etc. superglobals in your PHP 7 application. You wish $_FILES was easer to deal with. You’d prefer to wrap them all in an object to pass around to your class methods, so they’d be easier to test. And as long as they’re all in an object, it might be nice to have parsed representations of the various incoming headers. Preferably, you’d like for it to be read-only, so that the various libraries you use can’t modify superglobal state out from under you.

Likewise, seeing the “Cannot modify header information – headers already sent” warning is getting on your nerves. You’d like to get away from using header(), setcookie(), and the rest. You know they’re hard to inspect, and they’re hard to test. What would be great is to have all that response work wrapped in another object that you can pass around, and inspect or modify it before sending the response back to the client.

You could maybe adopt a framework, but why do that for your custom project? Just a pair of server-side request and response objects would make your life so much easer. Why can’t there be set of internal PHP classes for that?

Well, now there is. You can install the request extension from John Boehr and myself to get ServerRequest and ServerReponse objects as if PHP itself provided them.


After you install the extension, you can issue $request = new ServerRequest(), and then:

Instead of ...                          ... use:
--------------------------------------- ---------------------------------------
$_COOKIE                                $request->cookie
$_ENV                                   $request->env
$_GET                                   $request->get
$_FILES                                 $request->files
$_POST                                  $request->post
$_SERVER                                $request->server
$_SERVER['REQUEST_METHOD']              $request->method
$_SERVER['HTTP_HEADER_NAME']            $request->headers['header-name']
file_get_contents('php://input')        $request->content
$_SERVER['HTTP_CONTENT_LENGTH']         $request->contentLength
$_SERVER['HTTP_CONTENT_MD5']            $request->contentMd5
$_SERVER['PHP_AUTH_PW']                 $request->authPw
$_SERVER['PHP_AUTH_TYPE']               $request->authType
$_SERVER['PHP_AUTH_USER']               $request->authUser


Instead of parsing ...                  ... use:
--------------------------------------- ---------------------------------------
isset($_SERVER['key'])                  $request->server['key'] ?? 'default'
  ? $_SERVER['key']                     (good for all superglobals)
  : 'default';
$_FILES to look more like $_POST        $request->uploads
$_SERVER['HTTP_CONTENT_TYPE']           $request->contentType and
$_SERVER['HTTP_ACCEPT']                 $request->accept
$_SERVER['HTTP_ACCEPT_CHARSET']         $request->acceptCharset
$_SERVER['HTTP_ACCEPT_ENCODING']        $request->acceptEncoding
$_SERVER['HTTP_ACCEPT_LANGUAGE']        $request->acceptLanguage
$_SERVER['PHP_AUTH_DIGEST']             $request->authDigest
$_SERVER['HTTP_X_REQUESTED_WITH']       $request->xhr
  == 'XmlHttpRequest'

Those properties are all read-only, so there’s no chance of them being changed without you knowing. (There are some true immutables for application-related values as well; see the documentation.)


For responses, you can issue $response = new ServerResponse(), and then:

Instead of ...                          ... use:
--------------------------------------- ---------------------------------------
header('Foo: bar', true);               $response->setHeader('Foo', 'bar');
header('Foo: bar', false);              $response->addHeader('Foo', 'bar');
setcookie('foo', 'bar');                $response->setCookie('foo', 'bar');
setrawcookie('foo', 'bar');             $response->setRawCookie('foo', 'bar');
echo $content;                          $response->setContent($content);

You can inspect the $response object, and then call $response->send() to
send it to the client.

Working with JSON?

// instead of ...
header('Content-Type: application/json')
echo json_encode($value);

// .. use:

Sending a $file for download?

// instead of ...
header('Content-Type: application/octet-stream');
header('Content-Transfer-Encoding: binary');
    'Content-Disposition: attachment;filename="'
    . rawurlencode(basename($file)) . '"'
$fh = fopen($file, 'rb+');

// use:
$fh = fopen($file, 'rb+');
$response->setContentDownload($fh, basename($file));

Building a complex header? Pass an array instead of a string:

$response->setHeader('Cache-Control', [
    'max-age' => '123',
    's-maxage' => '456',
]); // Cache-Control: public, max-age=123, s-maxage=456, no-cache

$response->setHeader('X-Whatever', [
    'bar' => [
        'baz' => 'dib',
        'gir' => 'irk',
    'qux' => 'quux',
]); // X-Whatever: foo, bar;baz=dib;zim;gir=irk, qux=quux

Find Out More

You can read the rest of the documentation at to discover more convenient functionality. And if you’re stuck on PHP 5.x for now, the extension has a userland version installable via Composer as pmjones/request.

Try out the request extension today, because a pair of server-side request and response objects will make your life a lot easier.

Avoiding Quasi-Immutable Objects in PHP

tl;dr: Immutability in PHP is most practical when the object properties are scalars or nulls. Using streams, objects, or arrays as properties makes it very difficult, sometimes impossible, to preserve immutablity.

One of the tactics in Domain Driven Design is to use Value Objects. A Value Object has no identifier attached to it; only the combination of the values of its properties gives it any identification. If you change any of the properties in any way, the modification must return an entirely new instance of the Value Object.

This kind of behavior means the Value Object is “immutable.” That is, the particular instance is not allowed to change, though you can get back a new instance with modified values. The code for an immutable object looks something like this:

class ImmutableFoo
    protected $bar;

    public function __construct($bar)
        $this->bar = $bar;

    public function getBar()
        return $this->bar;

    public function withBar($newBar)
        $clone = clone $this;
        $clone->bar = $newBar;
        return $clone;

(Note how $bar is accessible only through a method, not as a public property.)

When you create an ImmutableFoo instance, you cannot change the value of $bar after instantiation. Instead, you can only get back a new instance with the new value of $bar by calling withBar():

$foo = new ImmutableFoo('a');
$newFoo = $foo->withBar('b');

echo $foo->getBar(); // 'a'
echo $newFoo->getBar(); // 'b'
var_dump($foo === $newFoo); // (bool) false

With this approach, you are guaranteed that one place in the code cannot change the $foo object at a distance from any other place in the code. Anything that ever gets that instance of $foo knows that its properties will always be the same no matter what.

The immutability approach can be powerful in Domain Driven Design and elsewhere. It works very easily in PHP with scalar values and nulls. That’s because PHP returns those by copy, not by reference.

However, enforcing immutability in PHP is difficult when the immutable object properties are non-scalar (i.e., when they are streams, objects, or arrays). With non-scalars, your object might seem immutable at first, but mutablity reveals itself later. These objects will be “quasi-“, not truly, immutable.

Streams as Immutable Properties

If a stream or similar resource has been opened in a writable (or appendable) mode, and is used as an immutable property, it should be obvious that object immutability is not preserved. For example:

file_put_contents('/tmp/bar.txt', 'baz');

$foo = new ImmutableFoo(fopen('/tmp/bar.txt', 'w+'));
$bar = $foo->getBar();
fpassthru($bar); // 'baz'

fwrite($bar, 'dib');

fpassthru($foo->getBar()); // 'dib'

As you can see, the effective property value has changed, meaning immutability has been compromised.

One way around this might be to make sure that immutable objects themselves check that stream resources are always-and-only in read-only mode. However, even that is not a certain solution, because the resource pointer might be moved by reading operations in different parts of the application code. In turn, that means reading from the stream may yield different results at different times, making the value appear mutable.

As such, it appears that only “read-only” streams can be used as immutable properties, and then only if the immutable object restores the stream, its pointers, and all of its meta-data to their initial state every time the stream is accessed.

Objects as Immutable Properties

Because PHP returns objects as references, rather than as copies, using an object as a property value compromises the immutability of the parent object. For example:

$foo = new ImmutableFoo((object) ['baz' => 'dib']);
$bar = $foo->getBar();
echo $bar->baz; // 'dib'

$bar->baz = 'zim';
echo $foo->getBar()->baz; // 'zim'

As you can see, the value of $bar has changed in the $foo instance. Any other code using $foo will see those changes as well. This means immutability has not been preserved.

One way around this is to make sure that all objects used as immutable properties are themselves immutable.

Another way around this is to make sure that getter methods clone any object properties they return. However, it will have to be a recursively deep clone, covering all of the cloned object’s properties (and all of their properties, etc.). That’s to make sure that all object properties down the line are also cloned; otherwise, immutability is again compromised at some point.

Arrays as Immutable Properties

Unlike objects, PHP returns arrays as copies by default. However, if an immutable object property is an array, mutable objects in that array compromise the parent object’s immutability. For example:

$foo = new ImmutableFoo([
    0 => (object) ['baz' => 'dib'],

$bar = $foo->getBar();
echo $bar[0]->baz;

$bar[0]->baz = 'zim';
echo $foo->getBar()[0]->baz; // 'zim'

Because the array holds an object, and because PHP returns objects by reference, the contents of the array have now changed. That means $foo has effectively changed as well. Again, immutability has not been preserved.

Likewise, if the array holds a reference to a stream resource, we see the problems described about streams above.

The only way around this is for the immutable object to recursively scan through array properties to make sure that they contain only immutable values. This is probably not practical in most situations, which means that arrays are probably not suitable as immutable values.

Settable Undefined Public Properties

Finally, PHP allows you to set values on undefined properties, as if they were public. This means it is possible to add mutable properties to an immutable object:

$foo = new ImmutableFoo('bar');

// there is no $zim property, so PHP
// creates it as if it were public

$foo->zim = 'gir';
echo $foo->zim; // 'gir'

$foo->zim = 'irk';
echo $foo->zim; // 'irk'

Immutability of the object is once again compromised. The only way around this is to impelement __set() to prevent setting of undefined properties.

Further, it might be wise to implement __unset() to warn that properties cannot be unset.


If you want to build a truly immutable object in PHP, it appears the best approach is the following:

  • Default to using only scalars and nulls as properties.
  • Avoid streams as properties; if a property must be a stream, make sure that it is read-only, and that its state is restored each time it is used.
  • Avoid objects as properties; if a property must be an object, make sure that object is itself immutable.
  • Especially avoid arrays as properties; use only with extreme caution and care.
  • Implement __set() to disallow setting of undefined properties.
  • Possibly implement __unset() to warn that the object is immutable.

Overall, it seems like immutability is easiest with only scalars and nulls. Anything else, and you have a lot more opportunity for error.

Remember, though, there’s nothing wrong with fully- or partially-mutable objects, as long as they are advertised as such. What you want to avoid are quasi-immutable objects: ones that advertise, but do not deliver, true immutability.

(For some further reading, check out At What Point Do Immutable Classes Become A Burden?)


FIG Follies, Part 3

This is the third of three posts I intend to make regarding the condition and actions of the FIG, and what they reveal.

The Future

[By way of presenting some context: I was the driving force behind PSRs 1 and 2; I conceived and then led PSR-4; I was a primary author on some of the early bylaws, including the voting protocol and the sponsorship model. I am a founding member of the FIG, and one of the two longest continually-serving members (along with Nate Abele). My perspective on the FIG spans its lifetime of 7+ years. It is that perspective which informs these posts.]

Regarding the rivalrous visions for the FIG, I see only two ways forward.

The first is that somehow the tension between the two visions is permanently resolved. It is this ongoing implicit tension that is the cause of recurring conflict. There is no common vision between all FIG members, and this causes resentment and distrust; sharing a common vision will provide a level of shared values and views.

I think the only way to relax that tension in the group is for one of the rival visions to supersede the other in an unmistakable and permanent way. That means one set of vision-holders would have to explicitly renounce its own vision in favor of the other. This could be accomplished by voice (i.e., by stating so on the mailing list) or by exit (i.e., by leaving the FIG).

Even though that would leave the FIG (per se) intact, I opine that sort of capitulation is unlikely from either set of vision-holders. After such protracted contention, the holders of each vision seem unlikely to withdraw, and even more unlikely to adopt the competing vision for FIG. (As a defender against the introduction of the newer “grand” vision, I certainly don’t to plan abandon the “founding” vision voluntarily.)

The second is that the holders of each vision all surrender simultaneously, and disband the FIG.

Disband The FIG?

There is already some level of interest for this idea, both from the wider community and within FIG itself, especially in relation to the FIG 3.0 proposal. From the thread Alternative to FIG 3.0 – Is it time to call FIG complete? (you should read the whole thing) we have these points from Joe Ferguson in two different messages:

As someone who feels like FIG 3.0 is a step in the right direction, and can empathize with those against it, I’d like to offer an observation:

Maybe it’s time to call FIG complete. FIG accomplished it’s primary goals (Bringing frameworks together to build interoperable packages / standards).

My comment is that maybe its time PHP get a standards body, led by the people who want to see FIG 3.0 happen. Let your work in FIG stand on it’s own. PSRs aren’t going anywhere. Start a Standards Body Group that adopts the work you’ve done here and picks up all the currently in progress PSRs and continues working on them. Close FIG down since it’s work as a Framework Interoperability Group has been completed.

This would be a perfect time to start fresh, get your bearings, and sort your stuff out with all the lessons learned from FIG. I would rather see this than people oppose FIG 3.0 and it being shoehorned in.

If you take away absolutely nothing else from my comments: FIG 3.0 is such a shift that it warrants the consideration of a new organization with leadership based on the people doing the work to make things happen in FIG.

I feel a sort of resignation toward this idea. I don’t really enjoy it, but something like it has to happen, and it’s probably for the best.

It certainly would eliminate the tension between the competing visions for the FIG, as there would be no FIG to contest over.


Let’s say, for a moment, that FIG dissolves itself, and the FIG 3.0 plan architected by Larry Garfield and Michael Cullum is realized as a new organization with a new name. What would be the benefits?

  • As a brand-new organization, it can define its vision and mission without in-group rivalry.

  • It can curate its membership, bringing in only the people and projects that adhere to its vision (and keeping out those who do not).

  • It can establish any organizational structure (hierarchical or otherwise) from the outset, without having to worry about precedent or prior expectations.

  • It can have any code of conduct it wants as part of its foundational structure.

  • Whatever negative baggage is perceived as being part of the FIG is dropped.

I’m sure there are other benefits as well.


There is one major drawback that I’ve heard voiced regarding a “disband the FIG and start a new group” approach. It is that new standards groups have a hard time getting off the ground. As one example, the PHP-CDS project does not seem to have gained much traction.

My guess is that an organization that forms after the FIG disbands would not have that trouble, especially given that FIG would no longer exist.

Note that some member projects such as Composer, Drupal, PEAR, phpBB, and Zend Framework have shown explicit support for the FIG 3.0 re-organization plan. I imagine that those projects alone would grant legitimacy to any new non-FIG group in which they were members.

Furthermore, as the architects of the FIG 3.0 plan, Larry Garfield is the Drupal representative to FIG, and Michael Cullum (while not a voting member) is directly involved with phpBB. The new group is guaranteed to have at least those two members from the start.

I have heard other drawbacks as well, but they seem primarily administrative in nature.

Administrative Issues

What happens to the accepted PSRs?

Accepted PSRs remain in perpetuity as the true product of the FIG, for any and all to adopt or ignore as they see fit. They were built to be immutable, and they will live on for as long as anyone cares to refer to them. Any new group that forms after the FIG would be free to adopt, or ignore, the finished PSRs (though it would not be free to claim them as their own).

What happens to the in-process PSRs?

There are at least two options here.

  1. In-process PSRs might convert to *-interop projects, a la container-interop and async-interop. Indeed, Woody “Shadowhand” Gilk has had the foresight and initiative to create an http-interop group already.
  2. If the migration out of FIG produces a new group, e.g. a FIG 3.0 style organization, that other group might adopt them in some fashion, perhaps by making those PSR owners initial members in the new group.

What about new PSRs?

After disbanding, no new PSRs would be admitted in any state.

What about the FIG website, Twitter account, Github account, etc. ?

I think this is the toughest problem with disbanding. It will be necessary to prevent the misappropriation of the FIG or PSR names after the group disperses, and at the same time make sure the various artifacts of the FIG (i.e., the PSRs) continue to be publicly available.

To that end, I suggest appointing an archivist (perhaps more than one) to receive ownership of the Github, Twitter, Google Mail, etc. accounts, as well as the FIG domain names. The job of archivist is is to hold the FIG name and accounts in trust and guard them from ever being used again. The archivist(s) might also merge errata and insubstantial changes on existing accepted PSRs, but I expect the activity on those should be minimal.

I assert that the archivist should be some nominally neutral party, one who has no designs on the FIG name or brand, and who has not participated in the production of PSRs or bylaws.

Finally, I would suggest that no follow-on group be allowed to claim to be the “successor” to the FIG, or somehow “approved” by FIG, but that’s a difficult thing to prevent. Members exiting the FIG would have to be on their honor for that one.


There is a tension in the FIG between two rival visions: a “founding” vision (mostly implicit through the history of the group) and a “grand” vision (explicitly described in the FIG 3.0 proposal). This tension reveals itself through things like the vote to remove me involuntarily, as well as ongoing conflict over internal processes, the direction and audience of PSRs, and other bureaucratic maneuvers.

The only ways to relax that tension are for one vision to supersede the other permanently and explicitly, or for the FIG to disband so there is no organization to contend over. Whereas I feel the former is unlikely to occur, the latter becomes the better course.

Disbanding leaves the products of the FIG intact (i.e., the PSRs). It also frees the holders of the “grand” vision to form a group of their own in their own way, to achieve their own ends without a competing group in place, and without compelling the holders of the “founding” vision to accede to a vision they do not share. The administrative issues of disbanding are minor in comparison.