larry@garfieldtech.comShort and safe array iteration (22.10.2017, 09:50 UTC)

Short and safe array iteration

Submitted by Larry on 22 October 2017 - 5:50am

One reason to follow development mailing lists is you sometimes pick up on some very neat tricks. Here's one that I spotted on the PHP Internals list recently to simplify array iteration in PHP 7.

Link
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
Link
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.

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

At Bitfalls.com, 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/final.md
  • 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

Bootstrapping

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.

Hooks

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 homestead.app:80

I was given the link http://03672a64.ngrok.io, 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 https://github.com/swader/autopush
cd autopush
touch README.md
echo "This is a README file" >> README.md
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:

<?php
file_put_contents('test.txt', fil

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

Link
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 %}
    <h1>Oops!</h1>
    <h2>This is awkward.</h2>
    <p>We encountered a {{ status }} {{ reason }} error.</p>
    {% if status == 404 %}
        <p>
            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>.
        </p>
    {% endif %}

    {% if error %}
        <h2>Error details</h2>
        <p>Message: <strong>{{ error.getMessage() }}</strong></p>
        <p>in <tt>{{ error.getFile() }}:{{ error.getLine() }}</tt></p>
        <p>Trace:</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>
            <p>Trace:</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 for..in..if 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.

Link
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.

Link
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 atlasphp.io (with both 1.x and 2.x documentation).

Submit issues and pull requests as you see fit!

Link
Voices of the ElePHPantInterview with Adam Culp (16.10.2017, 11:30 UTC) Link
LinksRSS 0.92   RDF 1.
Atom Feed   100% Popoon
PHP5 powered   PEAR
ButtonsPlanet PHP   Planet PHP
Planet PHP