Grauphel: Seeking new maintainer or funding – Christian Weiske

In 2014 I wrote grauphel, a owncloud/Nextcloud extension that allows you to synchronize notes between Tomboy (Linux, Windows), Tomdroid (Android) and Conboy (Nokia N900 – Maemo).

I personally do not use grauphel anymore and thus have no reason to maintain it any longer. For each Nextcloud release it must be tested, updated and re-released. Big changes are necessary to make it compatible with Nextcloud 21 as well.

The last real changes to grauphel were done in 2018 (version 0.7.0), and since then the changes were only to make it compatible with Nextcloud 15…20. The application itself is complete since 4 years, but unfortunately the foundations are constantly moving.

The original grauphel was a standalone application, but I converted it to a owncloud/nextcloud extension so that I can rely on its login and user management. From today’s perspective this was a mistake; a standalone version would still work today and not require unnecessary maintenance.

I’d like to hand grauphel over to a new maintainer that keeps it compatible with the latest Nextcloud versions.

Alternatively, I could make a standalone version of grauphel that works without Nextcloud if I get money to work on this task – 1000€.

Please write a comment in the issue on github if you’d like to take over the project, or how much you’re willing to contribute to the standalone version’s fund.

Ketting 7 released – Evert Pot

We just released version 7 of Ketting. Ketting is a generic HATEOAS
client for Javascript.

A whole bunch of features have been added since September. We’ve been
testing Ketting 7 in beta since January, so I’m excited to get this out
the door.

I’ve been working on this project since 2016. Normally, I would expect a
project like this to get a little stale. For me personally, the opposite
has been true and using Ketting (especially with React) is starting to feel
a bit like a paradigm shift.

Read on to see what’s new!

What is Ketting?

In short: Ketting is a generic REST client for Javascript. You can use it for
pushing JSON objects via HTTP, but the richer your API is in terms of best
practices and standard formats, the more it can automatically do for you.

It has support for Hypermedia formats such as HAL, Siren, Collection+JSON,
JSON:API and can even understand and follow links from html.

In the past it was not uncommon to hear that HATEOAS is lacking a good generic
client. If you are a Javascript/Typescript user this is no longer true.

More information can be found on the Github page.

What’s new?

Better HAL-Forms support

HAL-Forms is an extension of HAL, and adds support for ‘actions’ or
‘forms’, similar to what the <form> tag is to html.

Since the start of the year HAL-Forms has seen major updates, which was a
collaborative effort by several people from projects in the HAL community
(including Spring HATEOAS and yours truly) and lead by it’s author
Mike Amudsen.

Spring HATEOAS released its HAL-Forms updates in version 1.3 M2 (unclear
if this is a stable release or not), and Ketting follows today.

Major new features in HAL-Forms include:

  • Support for lookups
    • Example use-case is rendering dropdowns/comboboxes.
    • The list of possible options can either be provided in-line or via an
      external resource.
    • JSON and text/csv is support for external resources.
  • Support for most of the html5 input types, such as checkbox, color,
    tel, email, textarea, etc.
  • Support for many of the field attributes that also exist in html5 form
    fields, such as placeholder, min, max, step, cols, rows, and
  • Support for a form target. Previously this could also be supplied via
    the URI.
  • Support for multiple forms per document.

React bindings: <RequireLogin>

(note: all of the new react-ketting features were backported to Ketting 6)

react-ketting now has a RequireLogin component, that can be use to handle
the OAuth2 authorization_code flow in React applications.

Example usage:

function MyApp() { return <RequireLogin clientId="my-oauth2-client-id" authorizeEndpoint="https

Truncated by Planet PHP, read more at the original (another 13433 bytes)

Bedrock for modern WordPress development –

WordPress is the legacy content management system. It’s remained tremendously popular since its release in 2003 for the power it gives users to quickly put together a website with tools that offer them real, intuitive control over their content. That popularity has both inspired and depended upon constant modernization efforts by WordPress fans. The latest project to keep the classic CMS clicking two decades after its birth is Bedrock, an effort to turn WordPress into a Twelve-Factor app by the folks at Roots.

Xdebug Update: March 2021 – Derick Rethans

Xdebug Update: March 2021

Another monthly update where I explain what happened with Xdebug development in this past month. These will be published on the first Tuesday after the 5th of each month.

Patreon and GitHub supporters will get it earlier, around the first of each month.

You can become a patron or support me through GitHub Sponsors. I am currently 91% towards my $1,000 per month goal. If you are leading a team or company, then it is also possible to support Xdebug through a subscription.

In March, I worked on Xdebug for about 28 hours, with funding being around 32 hours.

Xdebug 3.1

I started working on the Xdebug 3.1 tasks, and so far I have mostly been working on making sure that Xdebug continues to compile with PHP 8, and on improvements to xdebug_info(). It now also includes whether a debug connection was successful, which IP address it connected to, and whether some protocol features are enabled.

I have also started triaging really old bug reports, and will close them if no extra information is provided. This should cut down on my “open issues” queue.

Xdebug Cloud

Xdebug Cloud is continuing to operate as Beta release, and provides an easy way to debug your PHP applications with Xdebug, without having to deal with complexities with regards to networking.

Packages start at £49/month, and revenue will also be used to further the development of Xdebug.

If you want to be kept up to date with Xdebug Cloud, please sign up to the mailinglist, which I will use to send out an update not more than once a month.

PHP Internals News: Episode 80: Static Variables in Inherited Methods – Derick Rethans

PHP Internals News: Episode 80: Static Variables in Inherited Methods

In this episode of “PHP Internals News” I chat with Nikita Popov (Twitter, GitHub, Website) about the “Static Variables in Inherited Methods” RFC.

The RSS feed for this podcast is, you can download this episode’s MP3 file, and it’s available on Spotify and iTunes. There is a dedicated website:


Derick Rethans 0:14

Hi I’m Derick, welcome to PHP internals news, the podcast dedicated to explain the latest developments in the PHP language. This is episode 80. In this episode I speak with Nikita Popov again about another RFC that he’s proposing. Nikita, how are you doing today?

Nikita Popov 0:30

I’m still doing fine.

Derick Rethans 0:33

Well, that is glad to hear. So the reason why you saying, I’m still doing fine, is of course because we basically recording two podcast episodes just behind each other.

Nikita Popov 0:41

That’s true.

Derick Rethans 0:42

If you’d be doing fine 30 minutes ago and bad now, something bad must have happened and that is of course no fun. In any case, shall we take the second RFC then, which is titled static variables in inherited methods. Can you explain what is RFC is meant to improve?

Nikita Popov 1:00

I’m not sure what this meant to improve, it’s more like trying to fix a bug, I will say. This is a really, like, technical RFC for an edge case of an edge case, so I should say first, when I’m saying static variables, I’m not talking about static properties, which is what most people use, but static variables inside functions. What static variables do unlike normal variables, is that they persist across function calls. For example, you can have a counter static $i equals zero, and then increment it, and then each time we call the function, it gets incremented each time and the value from the previous call is retained. So that’s just the context of what we’re talking about.

Derick Rethans 1:43

Why would people make use of static variables?

Nikita Popov 1:46

I think one of the most common use cases is memoization.

Derick Rethans 1:50

Can you explain what that is?

Nikita Popov 1:51

If you have a function that that computes some kind of expensive result, but which is always the same, then you can compute it only once and store it inside the static variable, and then return it. Maybe possibly keyed by by the function arguments, but that’s the general idea. And this also works if it’s a free standing function. So if it’s not in the method where you could store state inside the static property or similar, but also works inside a non method function.

Derick Rethans 2:22

The keyword here in his RFC’s title is inherited methods, I suppose. What happens currently there?

Nikita Popov 2:29

There are a couple of issues in that area. The key part is first: How do static variables interact with methods at all? And the second part is how it interacts with inheritance. So first if you have an instance method, with a static variable, then some people expect that actually each object instance gets a separate static variable. This is not the case. The static variables are really bound to functions or methods, they do not depend on the object instanc

Truncated by Planet PHP, read more at the original (another 13509 bytes)

Tinker-like REPL for Mezzio – Matthew Weier O’Phinney

Today in the Laminas Slack, somebody asked if there was an equivalent to Laravel’s Tinker REPL.
The short answer is “no”, but I had a suggestion for them.


The first part of my answer to the question was suggesting they use the PHP REPL.

PHP has had a REPL since version 5.1.0, which you can invoke using php -a.
Once you’ve started, you can do anything you’d normally do in PHP, including such things as including files, declaring namespaces, declaring classes, etc.

I’ve often wanted to test how classes work, or run one-off jobs without writing a script.
To accomplish these tasks, I’ll include the autoloader installed by Composer:

$ php -a
php > include './vendor/autoload.php';

Once I’ve done that, I can reference any classes, functions, and constants autoloaded by Composer, as well as anything PHP exposes.

Mezzio container

The Mezzio skeleton sets up a few files in its config/ subdirectory that give us a number of ready-to use artifacts.

The first is config/config.php, which aggregates and returns all application configuration, including from config providers as well as local autoloaded configuration files (those in config/autload/).
From the REPL, you can dump this information directly if you want:

$ php -a
php > include './vendor/autoload.php'; // we need autoloading for most config providers
php > $config = include './config/config.php';
php > var_export($config);

The second, and more important to this exercise, is config/container.php.
This file autoloads, configures, and returns the PSR-11 DI container defined in the application.
By using this approach, we can keep Mezzio agnostic of the specific container used, and leave it to that file to properly instantiate and configure it for us.
We provide out-of-the-box versions of that file for a number of containers, and have a specification for dependency configuration that we recommend to ensure that dependency configuration provided by third-party packages can be detected and utilized.

Because this is just a PHP file, and returns the PSR-11 container, we can include that and capture it to a variable in the REPL:

$ php -a
php > include './vendor/autoload.php';
php > $container = include './config/container.php';

From there, you can then pull any configured services, including the configuration, and start interacting with them:

php > include './vendor/autoload.php';
php > $container = include './config/container.php';
php > $config = $container->get('config');
php > echo $config['debug'] ? 'In debug mode' : 'In production mode';
php > $httpClient = $container->get(Http\Adapter\Guzzle7\Client::class);


While not quite as powerful as Tinker, the PHP REPL, coupled with Composer autoloading and a configured PSR-11 container, is a fantastic tool for interacting with your project.
I can definitely recommend this as a way to play with and experiment with your application code!

mwop Tinker-like REPL for Mezzio was originally published on by .

PHP releases on hold – PHP: Hypertext Preprocessor

As announced on the php.internals mailing list, a pair of malicious commits were made in the PHP source code repository over the weekend. These commits were immediately noticed and reverted, and thus never reached end users. The investigation into the root cause and exact scope of the compromise is still ongoing, therefore releases will be put on hold for two weeks assuming no further issues are discovered. Thank you for bearing with us while we endeavor to ensure that PHP is a stable and reliable platform for web development.

PHP Internals News: Episode 79: New in Initialisers – Derick Rethans

PHP Internals News: Episode 79: New in Initialisers

In this episode of “PHP Internals News” I chat with Nikita Popov (Twitter, GitHub, Website) about the “New in Initialisers” RFC.

The RSS feed for this podcast is, you can download this episode’s MP3 file, and it’s available on Spotify and iTunes. There is a dedicated website:


Derick Rethans 0:14

Hi, I’m Derick. Welcome to PHP internals news, a podcast dedicated to explain the latest developments in the PHP language. As you might have noticed, the podcasts are currently not coming out once every week, as there are not enough RFCs being submitted for weekly episodes. I suspect that this will change soon again. This is episode 79. In this episode, I speak with Nikita Popov, about a few more language additions that he’s proposing. Nikita, how are you doing today?

Nikita Popov 0:43

I’m doing well, Derick, how are you doing?

Derick Rethans 0:45

I’m pretty good as though, I always much happier when it’s sunny outside.

Nikita Popov 0:48

Yeah, for us to weather also turned today. Yesterday it was still cold.

Derick Rethans 0:53

We’re here to talk about a few RFCs. The first one, titled “New in Initializers”. What is this RFC about?

Nikita Popov 1:00

The context is that PHP has basically two types of expressions: ones, the ones used on normal code, and the other one in a couple of special places. These special places include parameter default values, property default values, constants, static variable defaults, and finally attribute arguments. These don’t accept arbitrary expressions but only a certain subset. So we call those usually constant expressions, even though they are not maybe constant in the most technical sense. The differences really that these are evaluated separately so they don’t run on the normal PHP virtual machine. There is a separate evaluator that basically evaluates an abstract syntax tree directly. They are just like, have different technical underpinnings.

Derick Rethans 1:49

Because it is possible to for example, define a default value to seven plus 12?

Nikita Popov 1:54

Exactly. It’s possible to define it to seven plus 12, but maybe not to seven plus variable A, or seven plus some function call or something like that.

Derick Rethans 2:03

I guess the RFC is about changing this so that you can do things like this. What are you proposing to add?

Nikita Popov 2:09

Yes, exactly. So my addition is a very small one, actually. I’m only allowing a single new thing and that’s using new, so you can use new, whatever, as a parameter default, property default, and so on.

Derick Rethans 2:23

In this new call, pretty much a constructor call for a class of course, can arguments to be dynamic, or do they need to be constant as well?

Nikita Popov 2:33

Rules are always recursive, so you can like pass arguments to your constructor, but they also have to follow the usual rules. So again, they also have to be constant expressions, or after this RFC, they can also include new, but they cannot include variable references and so on.

Derick Rethans 2:50

Is this something that is being defined at the grammar level or somewher

Truncated by Planet PHP, read more at the original (another 18149 bytes)

Laminas CI Automation – Matthew Weier O’Phinney

The Laminas Project has close to 200 repositories between the main project, Laminas API Tools, and Mezzio.
It’s a lot to maintain, and keeping on top of incoming patches can be a gargantuan task, much less creating releases.

That’s why this past year, we’ve spent a bunch of time on streamlining our processes; we want to be able to review, merge, and release changes quickly and confidently.
To that end, we have developed a number of GitHub Actions to make these processes as easy as possible for our maintainers.

Automated Releases

The first was a brainchild of Marco Pivetta (aka Ocramius).
He wanted a way to make releases as simple as possible.

Before this, we had a rather convoluted process:

  • If a pull request was against our “master” branch:
    • Merge to “master”
    • Merge to “develop” (which generally resulted in merge conflicts, due to differences in the file between branches)
    • Create a branch off of “master” to set the release version
    • Bump the release version in the
    • Merge the release branch into “master”
    • Merge the release branch into “develop” (again, merge conflicts)
    • Tag the release, copying the relevant entry into the tag description
    • Push the release
    • Create a release on GitHub from the tag, and, again, copy the entry into the description
  • If a pull request was against our “develop” branch:
    • Merge to “develop”
    • Merge “develop” to “master”
    • Create a branch off of “master” to set the release version
    • Bump the release version in the
    • Merge the release branch into “master”
    • Merge the release branch into “develop”
    • Bump the release version in the file in the “develop” branch to the next minor version
    • Tag the release from “master”, copying the relevant entry into the tag description
    • Push the release
    • Create a release on GitHub from the tag, and, again, copy the entry into the description

A lot of the work around tagging and creating the GitHub release are handled by my keep-a-changelog tooling, but it was still work, and there was a lot of boilerplate and busywork involved.

Marco’s big idea: what if we assigned issues and pull requests to GitHub milestones, and, when the milestone was closed, the release was created automatically?

This led to the creation of our automatic-releases GitHub action.

To work with it, you need to create release branches in your repository, named after semantic versions, and of the form {MAJOR}.{MINOR}.x (that’s a literal “.x” at the end).
(This has a nice side benefit of removing the “master” verbiage from our branches as well.)
You then create milestones named for the next releases you want to create: 1.2.3, 1.3.0, 2.0.0.
From there, you add a small workflow to your application, along with a few secrets (a GPG signing key, a Git author and email for tagging the release, and potentially a privileged GitHub token to allow creating a merge-up request; more on that later).

As you triage, assign your issues and pull requests to milestones.
When all issues and pull requests related to a milestone are complete, you close the milestone, and the workflow takes it from there.

What the workflow does:

  • It pulls the milestone description.
  • It pulls the list of issues and pull requests, along with the people who created them, to create a list of release notes detailing the issues/pull requests closed.
  • If you have a in the Keep A Changelog format, it will update the entry for the release to append the milestone description and release notes pulled in the previous steps, as well as set the release date, pushing the changes back to the branch.
  • It creates a tag using the signing key and git author/email, setting the description to the the changelog entry, or the information from the first two steps, pushing the tag on completion.
  • It creates a release on GitHub, using the same notes provided in the tag description.
  • If a newer release branch exists (e.g., if you were rele

Truncated by Planet PHP, read more at the original (another 9599 bytes)