decorative image for blog on laminas project
December 22, 2020

Laminas Project: A Year in Review

Zend Framework

Last year, on New Years Eve 2019, we successfully migrated the codebase of Zend Framework to the Laminas Project. Since then, the project has grown incrementally, achieving some substantial milestones along the way.

In this blog, I look back at some of these milestones, including the ratification of the Linux foundation charter, the formation of the technical steering committee, an important inflection point for the Laminas project, and more.

Zend Framework Becomes Laminas

No migration the size of this one will be 100% successful. The first several weeks were spent ironing out issues users had when migrating; surprisingly, we had very few of these! The majority were a handful of components where early releases had a largely different source tree than later releases, which in turn led to edge cases that we had not handled. In each of these, we decided to create "patch releases" of the historical release that fixed the edge cases, and then marked the package as a replacement for the earlier tag. As an example, laminas-diactoros 2.2.1 had issues, and we released 2.2.1p1 and 2.2.1p2 to correct them. Users pinned to 2.2.1, on an update, would receive 2.2.1p2, correcting any issues that the original rewrite had missed.

We also had lost some tooling along the way. Under Zend Framework, we'd had a bot that would build documentation for us, create GitHub releases from tags, and perform some Slack integrations. Since many of our processes had changed, and, more importantly, the repository locations, we needed to update the bot. One problem: it was written in Node.js, and was fairly difficult to maintain, in large part due to running on outdated dependencies. Geert Eltink, one of our contributors, had done some similar work using Expressive and Swoole, and gave me access to his work so I could write the bot in PHP. I did this work in January 2020, and got the bot launched under our domain. Surprisingly, we've had very little reason to update it since, other than occasional tweaks to message formatting and frequency.

Watch the Webinar Version

I recently recorded a webinar that covered the material in this blog and more. You can watch the full version for free, below.

Ratifying the Linux Foundation Charter

There was also one lingering, but important, item left in our migration to complete: ratification of our charter with the Linux Foundation. In February, I asked the members of our legacy community review board to either step back or commit to being members of the Technical Steering Committee under the Linux Foundation; we also extended invitations to several new people who had provided help during our migration. From there, we made some revisions to the original draft charter the LF had provided us, voted to ratify it, and returned it for acceptance to the LF. We were formally accepted as a Linux Foundation project on March 24, 2020!

With our acceptance to the Linux Foundation, we were also finally able to start receiving donations. We set these up via their Community Bridge project (now the LXF Crowdfunding platform), and have had a steady trickle coming in ever since.

Technical Steering Committee

Under the Linux Foundation, we needed a Technical Steering Committee to manage the project. The LF does not stipulate anything about the size of the TSC, nor what its scope should be; it only requires:

  1. Monthly, open-to-the-public meetings.
  2. A record of any votes held.
    1. If a meeting has a majority of TSC members, votes can be held during the meeting, and require a simple majority to pass.
    2. If a vote happens outside a meeting, it needs a majority of all members to pass

The above seems simple enough, but the voting protocol was something we had to revisit and clarify as early as August to ensure that we would not have any binding votes that did not have a majority approval from the TSC, and so that we could ensure that asynchronous votes (those not held during a meeting) would not be invalidated due to somebody's absence.

We decided our meetings would be the first Monday of each month at 19:00 UTC, and held our first meeting on March 2, 2020.

The membership of the TSC has fluctuated slightly, with a few folks withdrawing early on due to time commitments, and a few more being nominated and voted into the group. It currently stands at 15 members; you can find a listing of members in our organization TSC repository.

What have we discussed?

These are some of the highlights:

Versioning and LTS Support

One of the first topics we considered was when we would bump to new PHP versions, and what this would mean in terms of long-term support versions.

LTS is something many organizations look for when selecting a framework or library. They want to be able to pin to a version and know that it will receive security updates for the lifetime of their project.

LTS is also a huge barrier for attracting new maintainers. It generally means backporting and manually applying patches to previous release versions, which can be error prone and time consuming. And keeping release branches open long-term means that a job they volunteered for originally to scratch an itch has now become unpaid work.

On top of this, there's PHP's own aggressive release schedule, which dictates a new minor (or major) version each year, with any given version getting security fixes for 3 years after its initial release. This means that at any given time, there's at least three supported PHP versions in play, and changes made to what versions are supported each and every year.

We decided as a group that we would continue doing security releases for a given version as long as its minimum supported PHP version is currently supported by, or it is the current default release branch. Further, we will apply patches to the earliest supported release branch first, allowing us to "merge up" to the next release branch, and so on until the most recent release branch is reached. This approach tends to introduce the fewest merge conflicts, reduces the number of branches we support at any given time, and simplifies maintenance.

This then leads to our policy for adopting new PHP versions.

We decided that we would do this as soon as possible. One thing we noted was that adopting it means simply that we are testing against it. Taking advantage of its features can wait until it is the minimum supported version for the given release branch. On top of that, we also decided that bumping the minimum supported PHP version is not automatically a backwards compatibility break; it just indicates the range of versions we will support going forwards. As such, we determined we could bump PHP versions in a minor release.

Finally, we had some conversations around when new major releases can be made. The driving factor should always be that a backwards compatibility (BC) break cannot be avoided, and that there are good tradeoffs in terms of code maintainability and API simplification for creating the BC break. However, we also decided any new major release would require TSC approval, a review from the TSC before merging any BC breaking change, and, if possible, either migration tooling or a transitional release to help users upgrade.

Automatic Releases

To codify our security window and versioning practices, and to simplify the process of reviewing, merging, and releasing code, Marco Pivetta suggested we use a GitHub Action to help manage and automate our process. He'd developed one for the Doctrine Project, and volunteered to port it to Laminas and customize it for our workflow.

Over the months of June and July, several of us worked on this heavily, and got it fully customized and automated for the needs of the Laminas Project. In July, we rolled it out to all of our repositories.

The process works like this:

  • All code development is done on release branches, named after the minor release, and with a literal ".x" as the suffix; e.g., 2.1.x.
  • Issues and PRs are assigned to milestones named after unreleased versions.
  • Once we've closed all PRs and issues related to a milestone, we close the milestone.
  • From there, the automatic-releases workflow, which operates on GitHub Actions:
    • checks out the code
    • pulls a list of all issuse and PRs closed, and creates a summary
    • appends that list to the target version in the chagnelog, sets the release date in the changelog, commits it, and pushes it back to the repo.
    • tags, pushes, and creates the release, using the changelog entry for the release as the summary.
    • bumps the release version in the changelog, and then commits and pushes it back to the branch.
    • creates the next minor release branch, if no newer release branch exists.
    • bumps the release version in the changelog for the new release branch, committing and pushing it.
    • creates milestones for the next bugfix, minor, and major release, if they do not exist.
    • creates an "up-merge" pull request to the next newer release branch, if it existed before the release.

The long and short of it is that maintainers can spend the bulk of their time reviewing code, and then push the green merge button when done, and close a milestone when a release is ready.

Reduce What We Support

In the vein of reducing maintentance overhead, we did a survey of activity on components, and came up with a list of 2-3 dozen that we might want to consider dropping. The TSC is finite, and we need to attract more maintainers if we want to move our well-over-100 repos forward. On top of that, a number of components had reached the end of their usefulness, required highly specific expertise, or had solid replacements elsewhere in the PHP ecosystem.

In the end, we voted to discontinue maintenance on around 2 dozen components, and mark them as security only (though we have yet to update them to indicate this).

CLI Tooling

One thing we've noted over time is that part of the success around other frameworks has been around having copious CLI tooling for performing repetitive tasks. Zend Framework originally tackled this via MVC-based console tooling, but for years prior to the transition, had been recommending symfony/console instead. The main problem with using symfony/console was that you had to setup your application, including configuration aggregation and seeding your DI container, in order to make the tooling useful. Michał Bundyra proposed we provide a way to automate this, and proposed a new component, laminas/laminas-cli, which would build on top of symfony/console in order to integrate with both laminas-mvc and Mezzio applications.

By May, we had all the basics in place, which includes a default "laminas" vendor binary that scans configuration to determine what other commands are exposed. On top of that, we added some custom features around prompting users for required options, making for a simpler, more interactive tool. We have integrated it with Mezzio and the mezzio-swoole bindings at this time, and have some pending patches for laminas-mvc for creating controllers. We're hoping to get more people interested in writing commands for us in the near future.

Commercial Vendor/Support Provider Program

While the economy is stagnated due to the global pandemic, we decided to pass on another attempt at a full funding round for the project. Regardless, we've also had a few companies interested in partnering with the project, with an interest in being listed on the website.

In talking with our contacts at the Linux Foundation, we found we could create a program for this. To qualify, it needed to either be informal (anybody who asks can get listed), or formal (we would specify criteria the company or individual must meet in order to be listed). The criteria for a formal program could be anything; we could require code contributions or mentoring from them, a financial contribution, or a link to the project on their website.

We decided that we wanted to do a formal program, and use a financial contribution as the gateway, to weed out those looking for cheap advertising. Our program will require a three year commitment, with a $1000 contribution yearly. We are currently finalizing paperwork and processes with the Linux Foundation, and hope to open this up soon!


Max Bösing suggested we actively participate in Hacktoberfest this year, and came up with a plan: we'd already decided we wanted to provide PHP 8 support for all components, and also to add Psalm as a static analysis tool in our CI toolchain. He created projects for each of these, adding issues to each repo detailing the steps needed, and labeled them all so that Hacktoberfest participants could find them and assist.

This resulted in a very busy October for us!

We had 54 pull requests come in across 38 repositories to help us achieve this goal.

What a way to end the year!

An Inflection Point for Laminas

Sometime this autumn, I was asked how adoption of Laminas was going.

I didn't know, so I turned to Packagist to find out. Packagist provides statistics covering downloads over the last day, week, month, year, and all history, letting you get as much detail as you like. I decided to look at laminas-stdlib versus zend-stdlib, as it's a dependency of a majority of our packages, and thus will give a decent idea of how downloads are trending.

What I saw surprised me!

I'd expected that we'd still be seeing a lot of Zend Framework downloads. What I actually saw was that sometime mid-year, we hit an inflection point where Laminas downloads were exceeding those of Zend Framework. On top of that, the combined downloads outstripped what we'd seen the previous year in Zend Framework alone.

Laminas has largely taken over for Zend Framework already, and is maintaining and growing its popularity in the ecosystem!

Community Reactions to Laminas

I saw countless times over the year people indicating that migrating to Laminas was as simple as our migration documentation made it out to be. For most of these people, they followed the directions, and several minutes later, were fully operational on Laminas, Mezzio, or Laminas API Tools.

This, for me, is a huge win. Without success like this being the norm, we would never be able to get people to migrate, and without people doing so en masse, the risk was that the project would flounder.

We've also seen people start releasing projects written in Laminas and its subprojects.

  • Several contributors updated the Doctrine bindings for Laminas, to continue providing ease of integration between the two projects.
  • The Drupal team has updated to use Laminas packages as well.
  • Sam Sheridan is on the verge of releasing a commercial, subscription support tracker written on top of Mezzio.
  • Adam Omelak created a "Laminas Starter Kit" that provides Bootstrap integrations into laminas-view and laminas-form, CRUD generation, CLI tooling, user management, and more, to get you up and developing applications quickly.
  • Matthew Setter has created a Pluralsight course for Mezzio.

We're seeing momentum grow each day.

Become a Laminas Evangelist!

One way YOU can help is to evangelize Laminas:

  • Write blog posts.
  • Create videos.
  • Start podcasts.
  • Write wrappers around other projects to integrate them in Laminas MVC or Mezzio, and make sure you tag them with "laminas", "laminas-mvc", or "mezzio" when you create them, so others can find them.

When you do these things, drop a note to the @getlaminas account on Twitter, or in the Slack, and we'll help spread the word even further. The more YOU, as users of Laminas, let others know about the project, the more contributors and maintainers we'll attract, which means you'll see more fixes and more features.

And if you can, donate to the project (there's a button on every repository and every documentation page!), or get your company to sponsor part of your time to help the project.