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

Bootstrapping

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)

Link
Voices of the ElePHPantInterview with Ann Gaffigan (13.10.2017, 14:39 UTC) Link
PHP: Hypertext PreprocessorPHP 7.2.0 Release Candidate 4 Released (12.10.2017, 00:00 UTC)
The PHP development team announces the immediate availability of PHP 7.2.0 RC4. This release is the fourth Release Candidate for 7.2.0. All users of PHP are encouraged to test this version carefully, and report any bugs and incompatibilities in the bug tracking system. THIS IS A DEVELOPMENT PREVIEW - DO NOT USE IT IN PRODUCTION! For more information on the new features and other changes, you can read the NEWS file, or the UPGRADING file for a complete list of upgrading notes. These files can also be found in the release archive. For source downloads of PHP 7.2.0 Release Candidate 4 please visit the download page, Windows sources and binaries can be found at windows.php.net/qa/. The next Relase Candidate will be announced on the 26th of October. You can also read the full list of planned releases on our wiki. Thank you for helping us make PHP better.
Link
Stefan KoopmanschapYour unit test methods need docblocks too (11.10.2017, 19:37 UTC)

If you've met me at any time in the previous 20 years and you discussed unit testing with me, chances are pretty big that I'd have told you that your test methods in your unit tests don't really need docblocks, because the test methods would be named in such a way that they were descriptive. In a unit test class you could have methods such as testCheckWithQueueThatHasMessagesButIsNotProcessingThemReturns500() or testCheckWithQueueThatHasCorrectValuesReturns200(). Those names give you a good idea of what it is testing, which makes it a lot easier to find the test that fails when you run your unit tests and get some red Fs in your field of dots.

Tests can be hard to real though, especially (but not exclusively) when testing legacy code. You may have lots of mocks to configure, for instance, or you may have several similar tests that are testing specific situations, edge cases or bugs you found along the way that you wanted to test before you them. Even when you wrote the tests yourself, in 6 months you may not realize what the context was when you wrote the test. Or you might have another developer join the team that is not aware of the context.

Documentation is important. It lowers the bus factor, makes it easier to on-board new developers (or temporary external developers, waves) and makes you think about your own code in a different way. We're (getting?) used to documenting our software, but why not document our tests by giving it a bit more context?

It fixed a bug

Earlier this week I was writing tests for the code I had just written. I usually write empty test methods first for every situation I want to test, and then fill them up one by one. As I came to the last empty test method I looked at the situation I wanted to test. I implemented the test as I thought I had meant it based on the name of the method. Then I started adding docblocks to give the tests a bit more context. As I was writing the docblock for the last method I paused: Something was wrong. The thing I was describing was not actually the thing I was testing. Looking closer at the test, it made no sense. Everything I tested in this method had been tested in other methods.

I ended up rewriting the test to actually cover the situation I had wanted to test, and tweeted:

I started adding docblocks above test methods to describe what I'm testing. I just caught myself writing a nonsensical test that way. WIN. (@skoop)

What to document?

The way I write the docblocks is that I describe, in actual human understandable language, which situation the test covers. For instance, for one of the above examples:

/**
 * This test checks that the happy flow is correctly handled.
 * If the queue returns the right data according to our
 * specifications, it should return a 200 response.
 */

This will give you a lot of information about the test. But this one is for the standard happy flow, so it's still short. Let's have a look at another one.

/**
 * This test checks the failure flow: Matching transactions
 * fails. We also test whether database transactions are
 * used successfully: We should still commit the transaction
 * in this scenario
 */

Here I don't just explain the flow I'm testing, but I also explain some additional things we test in this specific test: Many developers would assume that in a failure scenario the database transaction should be rolled back, but in this specific case, it fails to match information, but that is an expected outcome, so we should still commit the database transaction.

Assumptions are... well, you know the drill. I realize that as a developer I make assumptions all the time, but if I can minimize the assumptions I (or other developers) make with only a small bit of effort by documenting those details, that's a WIN in my book.

DDT: Docblock Driven Testing

So these days as I start writing my tests, I still create the empty test methods first, but they are now immediately accompanied by the docblocks, describing in a bit more detail which situation the method is going to be testing. That helps me make sure I don't accidentally miss any possible scenario, or accidentally write a test I had completely meant to be different.

Link
Rob AllenPretty print curl -i (11.10.2017, 10:03 UTC)

My favourite tool for working with APIs is curl and in particular, I like using the -I switch to view the status line and headers too:

This generates an output that looks like this:

$ curl -i https://api.joind.in
HTTP/1.1 200 OK
Date: Wed, 04 Oct 2017 09:51:46 GMT
Server: Apache
X-Powered-By: PHP/5.6.4
Access-Control-Allow-Origin: *
Content-Length: 363
Content-Type: application/json; charset=utf8

{"events":"https:\/\/api.joind.in\/v2.1\/events","hot-events":"https:\/\/api.joind.in\/v2.1\/events?filter=hot","upcoming-events":"https:\/\/api.joind.in\/v2.1\/events?filter=upcoming","past-events":"https:\/\/api.joind.in\/v2.1\/events?filter=past","open-cfps":"https:\/\/api.joind.in\/v2.1\/events?filter=cfp","docs":"http:\/\/joindin.github.io\/joindin-api\/"}

What I would like to do is pretty print the body if it's JSON or XML so that it's easier to read. There are some tools out there, like jq which will format JSON, but they can't seem to cope if the first part of the string is not JSON:

$ curl -i https://api.joind.in | jq
parse error: Invalid numeric literal at line 1, column 9

Solution 1: Use -D flag

The easiest solution is to use the -D flag to send the headers to stderr:

$ curl -s -D "/dev/stderr" https://api.joind.in | jq
HTTP/1.1 200 OK
Date: Wed, 04 Oct 2017 14:56:29 GMT
Server: Apache
X-Powered-By: PHP/5.6.4
Access-Control-Allow-Origin: *
Content-Length: 363
Content-Type: application/json; charset=utf8

{
  "events": "https://api.joind.in/v2.1/events",
  "hot-events": "https://api.joind.in/v2.1/events?filter=hot",
  "upcoming-events": "https://api.joind.in/v2.1/events?filter=upcoming",
  "past-events": "https://api.joind.in/v2.1/events?filter=past",
  "open-cfps": "https://api.joind.in/v2.1/events?filter=cfp",
  "docs": "http://joindin.github.io/joindin-api/"
}

To make this easier, you can add to your ~/.curlrc. Mine looks like this:

$ cat .curlrc
 -w "\n"
 silent
 -D /dev/stderr

Now you never need to think about it.

Solution 2: A simple script to pipe the output through

Another way to do it is via a script that knows where the body starts. We can write this in PHP and it can automatically pretty print XML for us too:

#!/usr/bin/env php
<?php
/**
 * Pretty print XML or JSON, when the output includes HTTP headers from curl -i
 */
$input = file_get_contents('php://stdin');

$input = trim($input);
if (substr($input, 0, 5) == 'HTTP/') {
    // input is probably the output of curl -i
    define('DELIMITER', "\r\n\r\n");
    list($headers, $body) = explode(DELIMITER, $input, 2);
    if ($body) {
        echo $headers . DELIMITER;
        $input = trim($body);
    }
}

// is it JSON?
if ($data = json_decode($input)) {
    echo json_encode($data, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT);
    exit;
}

// is it XML?
libxml_use_internal_errors(true);
if ($simpleXML = simplexml_load_string($input)) {
    $dom = dom_import_simplexml($simpleXML)->ownerDocument;
    $dom->formatOutput = true;
    echo $dom->saveXML();
    exit;
}

// it's something else!
echo $input;

Save this as as /usr/local/prettyprint, make it executable with chmod a+w /usr/bin/prettyprint and you're good to go:

$ curl -i https://api.joind.in | prettyprint
HTTP/1.1 200 OK
Date: Wed, 04 Oct 2017 09:57:07 GMT
Server: Apache
X-Powered-By: PHP/5.6.4
Access-Control-Allow-Origin: *
Content-Length: 363
Content-Type: application/json; charset=utf8

{
    "events": "https://api.joind.in/v2.1/events",
    "hot-events": "https://api.joind.in/v2.1/events?filter=hot",
    "upcoming-events": "https://api.joind.in/v2.1/events?filter=upcoming",
    "past-events": "https://api.joind.in/v2.1/events?filter=past",
    "open-cfps": "https://api.joind.in/v2.1/events?filter=cfp",
    "docs": "http://joindin.github.io/joindin-api/"
}

Pick the solution that works best for you!

Link
Sammy Kaye PowersFinding & patching a bug in php-src (10.10.2017, 15:41 UTC)

Fair warning: take all this with a grain of salt; I'm still a PHP-internals newbie, but I wanted to show you a behind-the-scenes look behind bug #75237.

Find the bug

It all started whilst looking for lines of code to cover for a Chicago PHP UG meetup which was participating in PHP TestFest 2017.

I found an uncovered line using the gcov website for ext/json/json_encoder.c. I was trying to write some PHP that would hit this line.

json_encoder.c

I was trying various things to try and hit that line and nothing was working and then suddenly I inadvertently triggered a segfault with the following code.

<?php
class Foo implements JsonSerializable {
  public function jsonSerialize() {
    return new self;
  }
}

# Segfault!
var_dump(json_encode(new Foo));

Segfaults should never happen in PHP; the PHP core code should throw an exception and deliver a nice error message to userland before a segfault is able to occur.

Just to see which versions of PHP were affected by this bug, I created an 3v4l snippet and saw that all actively supported versions of PHP were segfaulting.

This segfault only happens when jsonSerialize() returns a new instance of itself. If I return the same instance with $this, the code works as expected.

<?php
class Foo implements JsonSerializable {
  public function jsonSerialize() {
    return $this;
  }
}

# Works fine
var_dump(json_encode(new Foo));

Submit a bug report

All bugs in PHP core should be reported via bugs.php.net. Even though I was going to attempt to patch the bug myself, I still needed to create a bug report to reference in my patch later on.

So I filled out the report a bug form and bug #75237 was born.

Make a patch

Now that hard part. How do we begin even patching this thing?

Update php-src and recompile

First, I pulled in any upstream changes from the main git repo to make sure I was working with the most up-to-date version of php-src. I have a remote called upstream that points to the main php-src repo on GitHub.

$ git fetch upstream
$ git checkout master
$ git rebase upstream/master master

Then I created a new branch off of master for the patch and named it after the bug ID.

$ git checkout -b bug75237

Then I needed to recompile from source. I won't go into too much detail on this, but I do have another post that describes in more detail

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

Link
Paul M. JonesA Few Right Ways, But Infinitely More Wrong Ways (10.10.2017, 15:25 UTC)

A response to the saying: “There’s no one ‘right’ way to do things. There are different ways of doing something that are ‘right’. So stop criticizing my chosen way of doing things — you cannot prove that it is wrong.”

For any question, there is a certain number of right answers, but an infinite number of wrong ones.

Likewise, there may be more than one right way, but that number is small in comparison to the infinite number of wrong ways.

Each right way is ephemeral and contingent, and has its own tradeoffs.

Each right way is dependent on your current understanding as applied to your current circumstances.

As your understanding changes with experience, and as your circumstances change over time, the way that is thought to right will also change.

Sometimes that means realizing that your earlier understanding was wrong.

The novice says: “My new idea cannot be wrong, because there is no one right way.”

The master asks: “Is it more likely that I have a new way that is better, or a new way that is worse?”

The novice demands “proof” that their way is wrong.

The master asks which ways are “better” and which are “worse”, and picks the best one for the situation.

Sometimes the best way is still “bad”, but better than all the others; the master knows this, and does not defend it as “right.”

Link
Adam CulpStop the pain, get to PHP 7 (6.10.2017, 15:13 UTC)

When I was young I played football at my local middle school…very terribly. I didn’t enjoy running with the heavy pads in the heat, and I definitely didn’t enjoy running into and hitting the other kids, most of which were larger than me. But in high school that all changed. Why? Because in middle school football was painful. Meanwhile in high school, well, it was still painful but there was something more pleasurable to offset the pain. It was the praises from the coach and the sounds of people cheering my name that truly made the difference.

See, in middle school, the coach seemed to focus more on the larger kids who could bully others, or the popular kids whose parents were the cornerstone of our small community. However, in 9th grade, it changed a bit because the coach was great at distributing his attention to the entire team. He would tell me “good job”, or “you can do better”, and he even let me play a game while my skills were catching up. These are things I didn’t have before, and it made a huge difference. I came to love playing and worked harder than I ever had to stay first string all season long rather than being satisfied with sitting on the sidelines watching others play.

So, now you may be asking, “What does this have to do with upgrading to PHP version 7?” The answer, because many are letting the pain of moving to PHP 7 prevent them from experiencing the pleasure and rewards.

PHP version 7.0 was released almost 2 years ago. (1 year 10 months to be exact.) And many are still running PHP version 5.something. As a matter of fact, PHP version 7.0 is already going to run out of active community support in only 1 month and will only receive security fixes for another year after that.

You can see the supported versions of PHP at http://php.net/supported-versions.php

The Pains

I get it. Upgrading to a new major version is painful. There are backward compatibility issues that caused it to be a new major version, to begin with, and now we need to jump through some hoops without any good reason. I mean, the app already works, right?

Add to this that there may be compatibility issues that have nothing to do specifically with PHP, but rather the individual libraries and packages we used in the past have not updated yet. Dependency hell is only a step away.

Also, how can we possibly endure the pain of explaining why we should upgrade to PHP version 7+ to management!?!

So we should just give up. Perhaps remaining on PHP 5.4, 5.5, or 5.6 is not so bad after all.

NO WAY! Read on!

Acclimation

Those pains aside, there are more that we’ve become acclimated to over time. We avoid upgrading because we’ve become used to the pain faced on a daily basis with what we currently have. It has become our comfort level. Meaning, we avoid the pleasures of advancing because we settle for what we already know.

Pleasure

In case you haven’t heard, PHP 7 brings a whole new level of FAST. Some companies have even recorded speeds of some apps to double. You read that right, “Double the speed in some apps.” That means customers get served web pages in half the time. Internal employees are able to navigate intranets, accounting software, and other internal apps in half the time. Imagine the productivity gains and reductions in salary required to have employees sitting at a screen waiting for the next page to come up. Imagine the customers who don’t click away from our products because it now loads faster!

In addition, many companies also noticed their resources (servers) running PHP apps with PHP 7 have dropped drastically. (about half) Meaning they can serve the same PHP applications on half the number of servers they used previously. If a company was using 100 servers to do business, they are now able to do the same thing with only 50 servers! That is a saving of 50 fewer servers needing to be hosted. Imagine

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

Link
Voices of the ElePHPantInterview with Samantha Quiñones (6.10.2017, 11:30 UTC)

Samantha Quiñones

Show Notes

The post Interview with Samantha Quiñones appeared first on Voices of the ElePHPant.

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