larry@garfieldtech.comThe 3 paragraph pitch (20.10.2017, 22:21 UTC)
The 3 paragraph pitch

Earlier this week a fellow PHP public figure tweeted saying that I write great session proposals for conferences. After I finished blushing I reached out to him and we talked a bit about what it was he likes about them. (Whatever I'm doing right, I want to know to keep doing it!)

Based on that, I figured it would be educational to dissect how I go about writing session proposals for conferences and hope that conference organizers don't catch on to my tricks. :-)

Larry 20 October 2017 - 6:21pm
Voices of the ElePHPantInterview with Alan Seiden (20.10.2017, 11:30 UTC) Link
Nomad PHPBuilding a CI System with Free Tools and Duct Tape (20.10.2017, 04:05 UTC)

January 2018 - EU
Presented By

Julian Egelstaff
January 18, 2018
20:00 CET

The post Building a CI System with Free Tools and Duct Tape appeared first on Nomad PHP.

SitePoint PHPGit and WordPress: How to Auto-Update Posts with Pull Requests (18.10.2017, 21:54 UTC)

At, we also use WordPress for now, and use the same peer review approach for content as we do at SitePoint.

We decided to build a tool which automatically pulls content from merged pull requests into articles, giving us the ability to fix typos and update posts from Github, and see the changes reflected on the live site. This tutorial will walk you through the creation of this tool, so you can start using it for your own WordPress site, or build your own version.

The Plan

The first part is identifying the problem and the situation surrounding it.

  • we use WPGlobus for multi-language support, which means content gets saved like this: {:en}English content{:}{:hr}Croatian content{:}.
  • authors submit PRs via Github, the PRs are peer reviewed and merged, and then (currently) manually imported into WP's Posts UI through the browser.
  • every post has the same folder layout: author_folder/post_folder/language/
  • this is slow and error prone, and sometimes mistakes slip by. It also makes updating posts tedious.

The solution is the following:

  • add a hook processor which will detect pushes to the master branch (i.e. merges from PRs)
  • the processor should look for a meta file in the commit which would contain information on where to save the updated content
  • the processor automatically converts the MD content to HTML, merges the languages in the WPGlobus format, and saves them into the database


If you'd like to follow along (highly recommended), please boot up a good virtual machine environment, install the newest version of WordPress on it, and add the WPGlobus plugin. Alternatively, you can use a prepared WordPress box like VVV. Additionally, make sure your environment has ngrok installed - we'll use that to pipe Github hook triggers to our local machine, so we can test locally instead of having to deploy.


For this experiment, let's create a new repository. I'll call mine autopush.

In the settings of this repository, we need to add a new hook. Since we're talking about a temporary Ngrok URL, let's first spin that up. In my case, entering the following on the host machine does the trick:

ngrok http

I was given the link, so that's what goes into the webhook, with an arbitrary suffix like githook. We only need push events. The json data type is cleaner, so that's selected as a preference, and the final webhook setup looks something like this:

Webhook setup

Let's test this now.

git clone
cd autopush
echo "This is a README file" >>
git add -A
git commit -am "We're pushing for the first time"
git push origin master

The ngrok log screen should display something like this:

POST /githook/                  404 Not Found

This is fine. We haven't made the /githook endpoint yet.

Processing Webhooks

We'll read this new data into WordPress with custom logic. Due to the spaghetti-code nature of WP itself, it's easier to circumvent it entirely with a small custom application. First, we'll create the githook folder in the WordPress project's root, and an index.php file inside it. This makes the /githook/ path accessible, and the hook will no longer return 404, but 200 OK.

According to the docs, the payload will have a commits field with a modified field in each commit. Since we're only looking to update posts, not schedule them or delete them - those steps are still manual, for safety - we'll only be paying attention to that one. Let's see if we can catch it on a test push.

First, we'll save our request data to a text file, for debugging purposes. We can do this by modifying our githook/index.php file:

file_put_contents('test.txt', fil

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

Voices of the ElePHPantInterview with Colin O’Dell (18.10.2017, 11:30 UTC) Link
Rob AllenDisplaying errors in Expressive with Twig (18.10.2017, 10:03 UTC)

If you're not using the Whoops error handler with Expressive and are using the Twig renderer, then you are given no information about the problem that occurred, even in debug mode.

To fix this, I changed error.html.twig to this:

{% extends '@layout/default.html.twig' %}

{% block title %}{{ status }} {{ reason }}{% endblock %}

{% block content %}
    <h2>This is awkward.</h2>
    <p>We encountered a {{ status }} {{ reason }} error.</p>
    {% if status == 404 %}
            You are looking for something that doesn't exist or may have moved. Check out one of the links on this page
            or head back to <a href="{{ path('home') }}">Home</a>.
    {% endif %}

    {% if error %}
        <h2>Error details</h2>
        <p>Message: <strong>{{ error.getMessage() }}</strong></p>
        <p>in <tt>{{ error.getFile() }}:{{ error.getLine() }}</tt></p>
        <pre>{{ error.getTraceAsString() }}</pre>

        {% set prev = error.getPrevious() %}
        {% for i in 1..10000 if prev %}
            <h3>Previous error</h3>
            <p>Message: <strong>{{ prev.getMessage() }}</strong></p>
            <p>in <tt>{{ prev.getFile() }}:{{ prev.getLine() }}</tt></p>
            <pre>{{ prev.getTraceAsString() }}</pre>
            {% set prev = prev.getPrevious() %}
        {% endfor %}
    {% endif %}
{% endblock %}

The new part is the within the {% if error %} block. In debug mode, error is set to the exception that was thown and is blank otherwise, so you won't leak sensitive information (as long as you don't enable debug in production).

Inside the {% if error %} block, I render the error message and where it happened and then iterate down through any previous errors and displays their information too. Interestingly, there isn't a while loop in Twig which would be ideal to recursively iterate through the previous errors. To solve this, I used the construct which works nicely as long as I don't have more than 10,000 previous errors!

If you use the Zend-View or Plates rendering engines, I imagine similar code would work there too.

Paul M. JonesChoose Dependency Injection — If You Can (17.10.2017, 14:00 UTC)

Some people say, “You don’t need to use dependency injection for everything. Sometimes dependency injection is not the best choice.”

It occurs to me that the people who say this are the ones who can’t use it for everything. They say “choose what’s best for your situation”, but their situation precludes the use of dependency injection in the first place.

Anyone who says “X is not always the best choice”, but does not have X as an available option, is being disingenuous. They are not choosing against X based on an examination of the tradeoffs involved. Instead, they are making a virtue out of necessity, then posing as virtuous for not having better choices available.

Dependency injection is, by default and until proven otherwise, the best choice — when you have that choice available to you.

If that choice is not available to you, if you cannot construct an object using any form of dependency injection (constructor injection, setter injection, etc.), then you need to consider if the code in question has been designed poorly.

Paul M. JonesAtlas.Orm 2.0 Is Now Stable (17.10.2017, 13:43 UTC)

I am very happy to announce that Atlas, a data-mapper for your persistence layer in PHP, is now stable for production use! There are no changes, other than documentation updates, since the beta release two weeks ago.

You can get Atlas from Packagist via Composer by adding …

    "require": {
        "atlas/orm": "~2.0"

… to your composer.json file.

The updated documentation site is at (with both 1.x and 2.x documentation).

Submit issues and pull requests as you see fit!

Voices of the ElePHPantInterview with Adam Culp (16.10.2017, 11:30 UTC) Link
SitePoint PHPSymfony Flex: Paving the Path to a Faster, Better Symfony (15.10.2017, 15:26 UTC)

Symfony Flex is a modern replacement for the Symfony Installer, and not the name of the next Symfony version. As the intro text says:

Internally, Symfony Flex is a Composer plugin that modifies the behavior of the require and update commands. When installing or updating dependencies in a Flex-enabled application, Symfony can perform tasks before and after the execution of Composer tasks.

The new Symfony will be called just Symfony 4, and while this tutorial will deal only with the Flex tool, it will mention some Symfony 4 upgrades as well.

Still Under Development

Symfony Flex can be considered a Composer wrapper, in that it provides your Symfony project with additional options during installation and configuration. It was developed with simplicity in mind, and obviously heavily influenced by the user-friendliness of Laravel. Remember, Laravel got to its current level of popularity due to its ease of use and the low entry barrier it provides newcomers with, and Symfony wanted to emulate this.

It should be noted that both Flex and Symfony 4 are still under development, slated for release somewhere at the end of November this year (2017). As such, some of the features mentioned in this post may have changed by the time you read it, but we'll do our best to keep it up to date.

Most notably, the use of a makefile and the make tool to build a project if Symfony/Console is unavailable is still up in the air, as it seems to not be working properly on some operating systems. Fabien recently held a survey around this, asking for the community's suggestions to a replacement, and overwhelmingly, the community voted in favor of just making Symfony/Console required.

Survey result

What's Different?

Most notably, Flex respects the coming Symfony 4 updates which boil down to the following major changes:

  • PHP 7+ is required
  • all folders are optional. If your project isn't using one, it doesn't have to be there. This makes the directory tree much simpler and more readable. Additionally, often useless files like .htaccess, LICENSE, and README have been removed as well - a project which needs those can easily add them.
  • there is no more web folder. Instead, there is the public folder, like in all other major frameworks. This consolidates user experience across ecosystems.
  • temporary files go under /var in the root of the project folder, with the /var/cache subfolder reserved for long term cache, like merged class files for deploying apps as read-only artifacts
  • source code goes under /src. No /app.
  • configuration goes into /config.
  • templates go into /templates.
  • Flex will have its own Symfony-verified list of packages that are referenced by one and one alias alone. So executing composer require cli will actually trigger Flex, which will look in its list of packages, find the one tagged as cli (in this case, Symfony Console), and install it. These "official" packages are called recipes, and can be found here. To accept user-submitted recipes, a flag exists in Flex's configuration which needs to be set to true: composer config extra.symfony.allow-contrib true. Those recipes can be found here. By officially endorsing some packages, Symfony is in many ways becoming as opinionated as Laravel. While this is bad in some ways, it's very good in many more ways: a consolidated, opinionated way to build Symfony apps used by most people so that everyone is on the same page.
  • bundle fragments no longer need to be custom-activated and added into a ton of files. Flex automates this, as well as their removal.
  • instead of parameters in config files, Symfony 4 will be using environment variables like Laravel


As usual, we'll assume you're already running a healthy VM environment like Homestead Improved so you can follow along.

Okay, let's get our hands dirty with an example app. All Symfony apps can now be started from the bare bones super-minimal Symfony Skeleton app:

 composer create-project symfony/skel

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

LinksRSS 0.92   RDF 1.
Atom Feed   100% Popoon
PHP5 powered   PEAR
ButtonsPlanet PHP   Planet PHP
Planet PHP