How I use WordPress and Docker Compose

It’s a cold Friday morning with the struggling sun doing its best to blind me with glare. That can only mean one thing:

The weekly CodeReviewVideos fun-filled newsletter.

(insert your own party popper sound effects)

This week saw three new videos added to the site.

#1 – [Part 1/2] – WordPress and nginx with Docker Compose

WordPress gets a lot of hate.

There are some valid reasons to nag on WordPress, but they are the same reasons you could nag on Laravel, Symfony, or Rails (or *insert any other framework / language here*).

Primarily the cause of problems with WordPress are *drum roll* People!

Specifically: developers.

Yes, PHP has a super low barrier to entry.

And yes, that means many take their first steps in coding by adding functionality to a tool they already use. In this case, seeing as WordPress apparently powers ~25% of the web, it’s unsurprising that many of these first steps happen within the WordPress ecosystem.

With that said, there are plenty of reasons why WordPress is a tool I often reach for. The big one is:

WordPress stops me from reinventing the wheel.

Also, paying clients love it.

Most any site I create will have some WordPress functionality.

Also, most any site I create these days has Docker in there somewhere.

In this, and the next video we cover one way you could use WordPress with Docker.

The kicker here is that this is not true to the spirit of containerisation.

Why not?

Well, WordPress and all its plugins and themes tend to update at a rapid pace. If each time a plugin or theme or WordPress itself needed updating, I would spend most of my working week keeping up to date, then packaging a new image, then uploading it, and so repeats the cycle for every point release.

No thank you.

Instead, I opt for a different approach. And that’s what we cover in this video.

#2 – [Part 2/2] – WordPress and nginx with Docker Compose

This video continues on from the previous.

We’re setting up WordPress with nginx as our web server, and a MySQL back end. All of this is managed by Docker Composer, because life’s too short to do all this by hand.

We make use of environment variables in this configuration. And these are great in development / test / staging environments.

However, in production I tend to not use environment variables. We’ve covered why that is as part of this series already.

In this video we cover a way to easily switch out our wp-config.php file depending on the environment we are in.

This not only means we can make use of environment variables in development and use the hardcoded, classic approach in production, but also that we can keep our WordPress ‘core’ files completely isolated from our config.

Hey, it works for me.

#3 – Better Strings (Template Strings)

I get asked about JavaScript more than pretty much anything right now.

There’s a lot to cover.

In this new series I’m trying something a little new:

We’re going to look at some PHP code. And then some ES5 code. And then some ES6 code.

In each case we are going to (try to) achieve the same thing. Often this won’t be possible, but seeing an example you already know how to do in PHP, or ES5, will – hopefully – make the transition to ES6 that much easier.

In this video we start with template strings. This is probably the most gentle way to introduce yourself to ES6, and we will continue to use template strings in many examples throughout the rest of this series.

As ever, I’d love to get your feedback on this course.

Next Conference

I love attending a good conference.

You can read all my past conference reviews by clicking here.

The next one I will be attending is PHP Yorkshire. At the time of writing there’s 12 remaining tickets at the super early bird price of £78. That’s fairly fantastic value for a conference ticket price, so if you’re in the area, consider grabbing one before the price hike.

When I got mine there were ~28 remaining, so these tickets are selling.

As ever, if you are attending then please get in touch as I’d love to meet up 🙂

Ok, that’s about it from me. Have a great week, and happy coding.

Chris

 

Symfony with Redis

In a bid to make getting up and running with CodeReviewVideos tutorials moving forwards, I have created a new repo called the Docker and Symfony3 starting point.

I will be using this as the basis for all projects going forwards as it dramatically simplifies the process of setting up each tutorial series, and should – in theory – make reliably reproducing my setups much easier for you.

I’ve had a lot of feedback lately to say it’s increasingly hard work to follow some of the older tutorials as the dependencies are out of date.

Taking this feedback on board, I will do my best to update these projects in the next few weeks-to-months. I am, however, going to wait for Symfony 4 to land before I spend any time updating stuff. No point duplicating a bunch of effort. Symfony 4 drops in November, in case you are wondering.

Video Update

This week saw two new videos added to the site. Unfortunately I was ill early in the week so didn’t get to record the usual third video.

#1 – [Part 1/2] – Symfony 3 with Redis Cache

Caching is a (seemingly) easy win.

Imagine we have some expensive operation: maybe a heavy computation, or some API request that needs to go across the slow, and unpredictable internet.

Wouldn’t it be great if we did this expensive operation only once, saved (or cached) the result, and then for every subsequent request, we sent back the locally saved result.

Yes, that sounds awesome.

Symfony has us covered here. The framework comes with a bunch of ways we can cache and store data.

Redis seems to be the one I find most larger organisations like to use, so that’s one of the reasons behind picking Redis out of the bunch.

At this point you may be thinking:

But Chris, I don’t have a Redis instance just laying around waiting for use, and I’m not rightly sure how I might go about setting one up!

Well, not to worry.

To make life as simple as possible, we are going to use Docker.

Docker… simple… the same sentence?!

Well, the jolly good news is that you don’t need to know anything about Docker to use this setup. At least, I hope you won’t. That’s the theory.

As mentioned above, I am making use of the new Docker / Symfony 3 starting point repo. I’ve tweaked this a touch for our Redis requirements.

By the end of this video you will have got a Symfony website up and running, and cached data into Redis. We will cover the setup required, both from a Docker perspective, and the config needed inside Symfony.

#2 – [Part 2/2] – Symfony 3 with Redis Cache

In the previous video we put all our caching logic into a controller action.

That’s really not going to cut it beyond your first steps. In reality you’re going to want to move this stuff out into a separate service.

To give you an example of how I might do it:

Controller calls CacheApiWrapper which calls Api if needed.

That might not be making much sense, so let’s break it down further.

Let’s imagine an app without caching.

We need to call a remote API to get the days prices of Widgets.

We hit a controller action which delegates the API call off to our Api service, which really manages the API call for us. When the API call completes (or fails), it returns some response to the calling controller action, which in turn returns the response to the end user.

If that API call always returns the same response every time it is called – maybe the prices of Widgets only change every 24 hours – then calling the remote API for every request is both pointless, and wasteful.

We could, if we wanted to, add the Caching functionality directly into the Api service.

I don’t like this approach.

Instead, I prefer to split the responsibility of Caching out into a separate ‘layer’. This layer / caching service has an identical API to the Api service. This caching service takes the Api service as a constructor argument, and wraps the calls, adding caching along the way.

If all this sounds complex, after seeing some code, hopefully it will make a bit more sense:

class WidgetController extends Controller
{
    /**
     * @Route("/widgets", name="widget_prices")
     */
    public function widgetPriceAction(
        WidgetPriceProvider $widgetPriceProvider
    )
    {
        return $this->render(
            ':widget:widget_price.html.twig',
            [
                'widget_prices' => $widgetPriceProvider->fetchWidgetPrices(),
            ]
        );
    }

This should hopefully look familiar.

The unusual part is the WidgetPriceProvider. Well, they do say the two hardest parts of computer science are cache invalidation, and naming things…

Really WidgetPriceProvider is the best name I could think of to explain what’s happening. This service provides Widget Prices.

How it provides them is where the interesting part happens:

<?php

namespace AppBundle\Provider;

use AppBundle\Connectivity\Api\WidgetPrice;
use AppBundle\Widget\WidgetPriceInterface;
use Psr\Cache\CacheItemPoolInterface;
use Symfony\Component\Cache\Adapter\AdapterInterface;

class WidgetPriceProvider implements WidgetPriceInterface
{
    /**
     * @var CacheItemPoolInterface
     */
    private $cache;

    /**
     * @var WidgetPrice
     */
    private $widgetPriceApi;

    public function __construct(
        AdapterInterface $cache, 
        WidgetPrice $widgetPriceApi
    )
    {
        $this->cache          = $cache;
        $this->widgetPriceApi = $widgetPriceApi;
    }

    public function fetchWidgetPrices()
    {
        $cacheKey = md5('fetch_widget_prices');

        $cachedWidgetPrices = $this->cache->getItem($cacheKey);

        if (false === $cachedWidgetPrices->isHit()) {

            $widgetPrices = $this->widgetPriceApi->fetchWidgetPrices();

            $cachedWidgetPrices->set($widgetPrices);
            $this->cache->save($cachedWidgetPrices);

        } else {

            $widgetPrices = $cachedWidgetPrices->get();

        }

        return $widgetPrices;
    }
}

As mentioned, WidgetPriceProvider is a wrapper / layer over the Api Service.

It also has the cache injected.

This way the API call is separated from the cache, and can be used directly if needed. Sometimes I don’t want to go via the cache. Maybe in the admin backend, for example.

Note that this service implements WidgetPriceInterface. This isn’t strictly necessary. This interface defines a public function of fetchWidgetPrices.

The reason for this is, as mentioned earlier, I want the caching layer (WidgetPriceProvider) to use the same method name(s) as the underlying API service.

Speaking of which:

<?php

namespace AppBundle\Connectivity\Api;

use AppBundle\Widget\WidgetPriceInterface;
use GuzzleHttp\Client;
use Psr\Log\LoggerInterface;

class WidgetPrice implements WidgetPriceInterface
{
    /**
     * @var LoggerInterface
     */
    private $logger;
    /**
     * @var Client
     */
    private $client;

    /**
     * WidgetPrice constructor.
     *
     * @param LoggerInterface $logger
     * @param Client          $client
     */
    public function __construct(
        LoggerInterface $logger,
        Client $client
    )
    {
        $this->client = $client;
        $this->logger = $logger;
    }

    public function fetchWidgetPrices()
    {
        // better to inject via constructor, but easier to show like this
        $url = "https://api.widgetprovider.com/prices.json";

        try {

            return json_decode(
                $this->client->get($url)->getBody()->getContents(),
                true
            );

        } catch (\Exception $e) {

            $this->logger->alert('It all went Pete Tong', [
                'url'       => $url,
                'exception' => [
                    'message' => $e->getMessage(),
                    'code'    => $e->getCode()
                ],
            ]);

            return [];
        }
    }
}

So really it’s about delegating responsibility down to a more appropriate layer.

Be Careful – don’t blindly copy this approach.

There is a gotcha in this approach which maybe not be immediately obvious.

If your API call fails, the bad result (and empty array in this case) will still be cached.

Adapt accordingly to your own needs. It may be better to move the try  / catch logic out from the WidgetPrice class and into the WidgetPriceProvider instead.

Or something else. It’s your call.

Anyway, that’s an excursion into a potentially more real world setup.

Hopefully you find this weeks videos useful.

As every, have a great weekend and happy coding.

Chris

You’ve Got To Go Forwards To Go Back

Another week goes by, and another newsletter where I can’t announce the launch of the revised version of CodeReviewVideos. It’s killing me.

I’ve pulled a PHP 6.

I’m now onto CodeReviewVideos version 3, and yet version 2 never got released! Oh my.

What’s most amusing to me is that v3 is so similar to v1 in terms of look-and-feel that I almost needn’t have bothered. Good times. Good times.

Anyway, I still have an absolute ton of stuff left to do, so today’s update is going to be short and sweet.

Video Update

This week saw three new videos added to the site:

#1 – Docker PHP Symfony Tutorial

In order to get a Symfony stack up and running with Docker there are a few pieces that already need to be in place.

These are your webserver (nginx, in our case), and likely a database (mysql, for us).

Our web stack

Also, being that Symfony uses PHP, we kinda need PHP available inside the Docker container 🙂

Now the good news is that we sorted out PHP last week. We created a ‘base’ image, based on PHP 7.1.

We can now use as the starting point for any PHP project we do. This could be Symfony, or WordPress, or Slim, or whatever.

In our case this will be a Symfony Docker image.

And what this means is that we will do a bunch of Symfony-specific tasks such as copying over the app , src , web , and bin  directories, and setting up the parameters.yml  file.

By the end of this video you will have all the pieces of the puzzle (the puzzle being: how to get a Symfony stack up and running in Docker) ready to go.

You could – if you were being particularly cruel on yourself – decide that you’re going to docker run all these images and get everything hooked up by hand.

Or, if you prefer life being that little bit easier then you could use Docker Compose to make this task massively simpler…

#2 – Docker Compose Tutorial

In a nutshell, Docker Compose allows you to define an environment in which your project / code will run.

As above, in our case we need nginx for our web server, we need MySQL as our database server, and we need our Symfony code to run our application.

Docker Compose allows us to define how all of this fits together.

It might not make much sense as words, so here’s some real config:

version: '3'

services:

    db:
        image: mysql:5.7.19
        hostname: db
        volumes:
          - "./volumes/mysql_dev:/var/lib/mysql"
        env_file:
          - ./.env

    nginx:
        image: docker.io/codereviewvideos/nginx.symfony.dev
        hostname: nginx
        volumes:
          - "./volumes/nginx/logs:/var/log/nginx/"
          - "./:/var/www/dev"
        ports:
          - 81:80
        depends_on:
          - php

    php:
        image: docker.io/codereviewvideos/symfony.dev
        hostname: php
        volumes:
          - "./volumes/php/var/cache:/var/www/dev/var/cache/:rw"
          - "./volumes/php/var/sessions:/var/www/dev/var/sessions/:rw"
          - "./volumes/php/var/logs:/var/www/dev/var/logs/:rw"
          - "./:/var/www/dev"
        env_file:
          - ./.env
        depends_on:
          - db

Even if you don’t understand how it all works, the likelihood is you can figure out what it will do if you were to run docker-compose up  against this config.

However, one of my goals with CodeReviewVideos is to ensure you do understand how. And so in this video we cover exactly that.

#3 – Docker Compose Tutorial For Elixir and Phoenix Framework

In this tutorial series we are covering how to get a working Phoenix Framework environment up and running with Docker.

In case you aren’t aware, Phoenix is a web framework written in Elixir, a rather interesting functional programming language.

The main reason for this tutorial series is to show you that the back end and front end code can be completely separate entities.

We could use Symfony as our back end. We could use Laravel. We could use Django, or Rails, or in this case, Phoenix.

Ultimately, in most of my projects lately, all my back end does is serve up a JSON API.

From the point of view of the front end (React, Angular, Vue, some mobile app, or whatever), it doesn’t matter – at all – how the back end works. It just needs to work.

One of the often repeated pieces of advice for programmers who want to improve their craft is to “learn a different language”.

We aren’t going to be learning Elixir here. If there is interest then I would be happy to share what I know.

However this series is intended to show you how to achieve a working JSON API, and quickly, in a different environment to that which you might be used to.

Hopefully you find it interesting regardless of whether you decide to investigate Elixir / Phoenix any further.

And that’s about it for me this week.

I’ve had a lot of requests lately for “how to deploy Symfony“, so this will be covered in next week’s videos.

Until next week, have a great weekend and happy coding.

Chris

PHP > React > Server Side Rendering > PHP

Back when I was a server room techy there was a line my old boss used to say whenever I got wind of something new and shiny:

There are no new ideas in IT, just the same ones on repeat.

Of course he was being tongue-in-cheek, but there was a truth in what he said.

For example, around the time I was in this role, the IT industry was moving from distributed to centralised. That is to say we had a bunch of servers dotted all over the county, and the plan was to bring them into just two central server rooms.

This, I was assured, was very much like “the olden days” when individual desktops were replaced with “dumb terminals”, which relied heavily on a centralised Mainframe.

At some point, someone (likely an army of well paid consultants) espoused the failings of such an architecture (oh my, single point of failure!) and likely sold them a bunch of high powered standalone desktops.

This worked well for a while, then companies like Citrix came along and sold a different spin on “dumb terminals” using your existing high powered desktop, and so on, and so on.

What the heck does any of this have to do with Web Development, I hear you ask.

Good question.

As you may recall, I have been getting quite excited about launching the new, shiny revision of CodeReviewVideos.com. I had my zip lock baggy of party poppers at the ready. Things were looking super.

Then, over the previous weekend, it dawned on me:

How’s the SEO on this new site then?

Seeing as about 70% of the incoming visitors to CodeReviewVideos arrive via Google, I figured I should probably – ya’ know – give this some consideration.

I checked, and it turned out that I had, ahem, neglected to set any of the head information.

Yes, I felt quite the chimp.

But not to worry, I have all the SEO data just sat ready and waiting in the DB. After all, it’s exactly the same as for the existing site.

What happens with the existing site is what happens with pretty much any PHP site I have ever worked with:

  • A request comes in
  • The relevant data is fetched from the DB (thanks, Doctrine)
  • This data populates a template (thanks, Twig)
  • The response is returned to the end user (thanks, Symfony!)

It doesn’t matter if the request is from Google Bot, or from a real person. The process is always the same.

What this means is that the response contains everything needed to make a full page representation.

Google Bot can look at the page and see all the expected “stuff”: the header tags, and body content, it’s all there.

Sure, we can then augment this with a snazzy bit of JS here and there, but largely, it’s good to go.

Web 2 Point… Oh?!

Then sometime a few years back, Single Page Applications (SPA, and not the relaxing kind) became popular.

SPA – not as relaxing as you may have been led to believe

Fast forward a few years and boom, I’ve done a few of these here SPA’s with React and Angular, and I’m thinking: yeah, this is awesome, let’s make CodeReviewVideos all snazzy using all this wicked tech.

So I did.

The new version of the site uses React, and Redux, and Redux Saga, and it talks to a Symfony JSON API, and it’s all lovingly tested and fills me with warm fuzzy feels whenever I work with either code base.

Unfortunately, all this awesomeness does make the architecture more complex. Let’s revisit how a request / response works now:

  • A request comes in
  • The user gets sent this:
<!DOCTYPE html><html lang="en"><head><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta charset="utf-8"/><meta name="viewport" content="width=device-width,initial-scale=1"><title>Code Review Videos</title><script type="text/javascript" src="https://js.stripe.com/v2/"></script><link rel="shortcut icon" href="/favicon.ico"><link href="/main.0c31c168e455a7de8ecee02d7d21798e.css" rel="stylesheet"></head><body><div id="app"></div><script type="text/javascript" src="/main.bf614c9bf38e83f9d4e0.js"></script></body></html>
  • We are done, let’s go to the pub.

If you’re a bot Yahoo, Bing, or Yandex, you’re now done.

Forgetaboutit

By all accounts these bots do not process JavaScript, so forgettaboutit.

This may very well be of no major consequence.

By way of some hard figures, the combined total visitors that CodeReviewVideos received over the last 7 days that came via a search engine that isn’t Google was:

11.

Fixing the world for the sake of these other search engines probably isn’t worth my time right now.

But Google… well, we must do better.

Now, it turns out that maybe Google has already solved this problem.

My guess is they have. I mean, this is Google. They are super smart, and it’s their job to get this right.

But can I risk killing the site on a maybe.

No, definitely not.

What Happens Next?

Back to the HTML from above. Thinking about the request / response sequence, what happens next?

Well, on the client side – which is to say in your visitor’s browser – assuming they have JavaScript enabled, the JS is read and run (or parsed and executed, if you’re a CS text book).

Cus i’m Shiny!

This is where all the cool stuff happens!

  • React builds the page from my components
  • The components instruct the browser to make requests to the back-end API for the real content
  • The real content is received
  • React renders the content into the right place(s)
  • The visitor is completely indifferent

By the way, if the visitor doesn’t have JavaScript enabled then they are going to have a bad time. But, ya know, 2017, etc, etc.

When I realised my mistake about SEO last weekend, my first thought was to simply grab my Helmet and populate the head tags using the API response.

Alas, as we have now seen, this simply will not do.

So I figured I would be a Smart Guy ™ and put a caching layer in front of my web server. Maybe I could trick the bots by returning a fully cached version of each page.

Yeah, that didn’t work.

At this point I had a short breakdown.

Fortunately, PHP North West happened which took my mind off of the problem.

Ultimately though, it meant I had to postpone the scheduled launch. And that sucks.

Server Side Rendering anybody? No? SSR? No?

Of course I’m not the first person to have experienced this problem.

There is already a solution:

Server Side Rendering.

The idea here is rather convoluted, but stick with me:

We already have our shiny new React site, right? Yes, yes we do.

Server-side-rendiamous!

So, let’s get a Node JS instance to sit in front of our React site, and uses some of the stuff we learned in the Dark Arts class at Hogwarts to run this code, then convert the response to a string, and write the string to a template, which is turned into another string which is sent back to the browser so that we now have the necessary HTML to please Google like in the olden days.

Oh my.

It seems like we’re repeating ourselves here.

But now with more layers. More bug filled, confusing, maybe unnecessary layers.

Anyway, that’s where I’m at with CodeReviewVideos right now. Trying to migrate my existing front end code from client-side only, to this SSR setup to essentially reproduce the outcome I already have with plain old PHP.

What this means is right now I have no ETA on the next version, and once it is again “ready”, I will need to go back through a phase of testing before go-live.

Video Update

This week saw three new videos added to the site:

#1 – [Part 1] – Twig Extensions – How to add a custom CSS class to an invalid form field

Between this, and the next video we look at a question I got asked late last week:

How can I add a custom CSS class to the `input` / other form field when validation fails for that field?

This video explores one possible solution to this problem.

What happens however, is that we end up with a bunch of repeated logic living in a Twig template.

Generally, if you find yourself repeating yourself… or you end up with complex logic living inside a Twig template, you can probably extract it into a better location – a custom Twig function.

#2 – [Part 2] – Twig Extensions – Create a Twig Extension Function to Keep DRY

As such we look at extracting this repeated logic from our Twig template into a Twig Extension.

It’s one of those topics that sounds like it might be hard, or too nerdy, or whatever.

It’s just a strange name for a very useful concept.

If you use Twig in any seriousness, and you don’t yet know about Twig Extensions then this video should help you understand how to use one, and why it’s not as hard as you might think to do so.

#3 – Docker Elixir Phoenix – Part 1 – The Web Server

In my personal experience there has been no better way to improve my overall knowledge of software development than by learning another language.

Elixir, in this case, is the language.

Phoenix is somewhat akin to Symfony, or Rails, or what have you. It’s a framework for web applications.

In this series we are building up a small but functional (ho, ho) JSON API using Elixir and Phoenix.

In this video we cover how to set up the Web server by way of docker-compose.yml. This series is a little more advanced than most of the content on CodeReviewVideos, but I hope you’re finding it enjoyable all the same.

That’s It, That’s All

That’s just about it from me this week.

My favourite snowboarding movie 🙂 Great soundtrack.

As mentioned last week I spent the previous weekend at the PHP North West conference.

You can read about my time there right here.

There are pictures 🙂 and also a lesser spotted Rasmus found in his natural habitat.

Have a great weekend, and happy coding.

Chris

[PHP North West 2017] – Conference Review

This was my fourth consecutive year attending PHPNW, which is now in its 10th year overall.

Why didn’t I attend the first six? I didn’t get involved in the PHP – or indeed any tech – community until then. Probably to my detriment. So, if you’re sat reading this and you’ve never been to a conference then I would urge you to find a local one and head along, even if you go solo (as I always do).

For once I was early, so managed to get a coffee before heading into the keynote.

Keynote – PHP in 2018 – Rasmus Lerdorf

This year the keynote was by creator of PHP, Rasmus Lerdorf.

I was very excited when the conference line up was announced and Rasmus was revealed as the keynote. I know, I know, major geekout, but still, this is the person whose hard work has allowed me to do what I do for the past 15 years or more. Without PHP I might still have found my way into software development, but the barrier to entry would have been significantly higher.

This talk covered a bunch of interesting topics:

Firstly, Rasmus suggested those interested in search technology like Lucene, Elasticsearch and similar should look at Vespa. I saw this on Hackernews the other day but haven’t looked into it as of yet. Rasmus suggested an entire industry might spring up around this, similar to Hadoop.

This slide caught my attention. Although way beyond my personal needs, it’s pretty cool to see that you can create an optimized PHP binary for your specific needs… at least, I think that’s what this is doing.

There were some interesting slides on the financial cost of power savings as a result of using PHP7+. This could be contrasted with Bitcoin:

Running Bitcoin uses a small city’s worth of electricity

I’m not sure of the orders of magnitude, but according to Rasmus’ slides, PHP drives 50% of the web which is ~1 billion websites.

Currently only ~5% of those are running PHP7.

That 5% equates to ~$200m savings annually. Plus a lot less CO2 in the air.

If PHP7 could reach 100% adoption this could save $4 billion annually, with 7.5 billion kg less CO2.

In other words – switch to PHP7 and save the planet.

Probably the coolest thing coming in PHP 7.2 (in my opinion) is Dead Code Elimination (DCE). What this does, from a very high level, is to analyse your code, and then silently discard any instructions that would have been redundant.

The funny part about this is that the worse your code is, the better your potential savings 🙂 And the joke of it all was that there’s likely a lot of bad code out there in PHP-land (especially if you listen to the haters), so things look rosy 🙂

The slides explain this much better than I could ever hope too, should you wish to understand how. Simply using PHP 7.2 (and especially 7.3+) will give you this benefit for free.

There are a few new features coming in PHP 7.2 that you may find use for. Honestly, there’s nothing here quite as big as those PHP7, nor 7.1.

There is parameter type widening:

You can use trailing commas everywhere:

You can now use object as a typehint:

Also Libsodium is now in the PHP Core. Crypto is not my strong point, but my understanding of this is that by having Libsodium as a part of the PHP Core that the resulting code that does need to use encryption, signatures, and password hashing will be more secure by default.

Rasmus gave this link for reference.

Phan was also covered.

Now I recently tried to use Phan against both a Symfony project running on PHP7, and also a legacy app that had a ‘custom’ framework. I struggled with it.

What I’d like to do is put Phan into my GitLab CI pipeline. I haven’t managed this yet as at the time it didn’t work for me ‘out-of-the-box’. I will revisit it though – maybe it would be a good topic for a video 🙂

One thing I did take note of was that Phan works a lot better if you use Docblocks in your code. Yet another reason to document 😀

Overall it was reassuring to see PHP as a language is still being very actively developed, and the future holds a good many treats for us as developers, without us really having to do very much (just upgrade to the latest release).

Slides

Meet Terraform – Michael Heap

From the keynote I headed to Michael Heap’s talk on Hashicorp’s Terraform.

Hashicorp make some great tech – Vagrant being the one you’re most likely to have heard of.

I had heard of Terraform before this talk, but was not too sure how it might fit into my personal dev / ops workflow.

My biggest question before this talk was:

How is Terraform different from Ansible?

Here’s what I concluded:

Terraform allows you to define your server / infrastructure setup as code.

For example, say I wanted three digital ocean droplets of a particular size, in a particular data centre, all named in a particular way.

Terraform makes this easy for me.

I would likely still need Ansible to actually install and configure the software that runs on these machines, however.

After Terraform has created the machines according to my spec, it could invoke my Ansible playbook commands to do this for me.

In short, the tools are complimentary, rather than competitive.

Michael shared a bunch of potential gotchas towards the end of this talk. You can find these from slide 87 onwards. I liked this as not only did it demonstrated Michael’s obvious real world experience in using the tool, but also that in reality, once you do start using Ansible, or Terraform, or whatever, they are never quite as simple as you might have been led to believe.

An example of this might be in what happens if you make a mistake. Michael explained that the taint command could be used to mark a box as to be destroyed and re-provisioned. This definitely sounded easier than when things go wrong with Ansible…

Morning Break

During the first break of the day I decided to quickly review the notes I’d taken from the first two morning sessions.

It was at this time I realised my handy note taking app – Gmail – had somehow deleted my draft. Sigh.

Needing a place to sit and hastily re-type my notes, I headed for the ‘Unconf’.

If you aren’t aware, the Unconf is the fourth talk-track. It only announces its speakers on the day, so you won’t find them on the official website. The talks here are shorter – 25 minutes – and often more advanced, or specific in subject.

As soon as I saw a talk about Symfony Flex I decided I would be in there for a while 🙂

Unconf – Creating Rich Universal React Apps Powered By RESTful PHP – Akihito Koriyama

There was a lot of detail in this talk – more than could be reasonably covered in 25 minutes.

A really useful takeaway for me here was in what the HTTP OPTIONS  verb is supposed to be used for. Now, here’s me thinking it’s just the annoying verb that often reports a failure when CORS problems occur 😉

OPTIONS , I learned, are (rather unsurprisingly, given the name) supposed to tell the API consumer exactly what can be done with any given endpoint.

Now this all assumes you are providing a truly RESTful implementation. In most of my projects lately I have instead opted for the simpler approach of providing a JSON API.

There was a lot of emphasis on HAL. All examples were given in the context of Bear.sunday though Akihito did also mention that API Platform offered similar functionality, for the Symfony-inclined.

I really enjoyed this talk. I wish I had taken further notes around Akihito’s implementation of Server Side Rendering, which has become a problem for me in the time since attending PHPNW17.

Unconf – Enfys: The Infant Year – Mark Baker

I had absolutely no idea what Enfys was before this talk.

You may not either, so allow me to enlighten you:

Enfys is the Elephant plushy representing diversity in the PHP Community.

This talk was all about the journey from idea to successful kick-starter.

This was an absolutely fantastic talk, well delivered and full of warm feels 🙂 It is obvious that Mark cares passionately about his project, and its wider implications.

I would strongly recommend reading the kickstarter page as it contains a great description of what this project is about, and why it’s needed. I confess my ignorance to issues like this well in advance. Being that I work almost entirely remotely, I have never experienced any of the problems that this project aims to address. Without attending PHPNW17 I likely would never have come to hear about this project.

I had to ask – what does Enfys mean? Mark told a wonderful story of how he came across the name. Again from the kickstarter page:

“Enfys” is a Welsh name meaning “Rainbow”, and is gender neutral (it can be used for both boys and girls), so it seemed an ideal name for a new Rainbow Elephpant, to promote Diversity within the PHP Community.

Brilliant.

Dinner Time

I wouldn’t normally spend too long on the dinner time round up, but at PHPNW17 I got lucky.

Rasmus, less so.

One of the strange parts about the PHP North West conference is that at dinner time the food is served in the main exhibition hall area, but you can eat in the unadvertised dining area.

Fortunately having been a few times now, I knew about the dining area, as eating a chicken steak stood up is not easy to do.

Anyway, in I went and being a loner, it’s usually fairly easy to find a seat.

I spied 3 empty chairs towards the back of the room, and plonked myself down.

Shortly after, Rasmus arrived back to his chair – the very next chair – and took his seat. Oops, had I stolen Rasmus’ seat? Alas no. Thankfully.

Anyway, not wanting to miss my opportunity, I asked if he’d mind my interruption for a question. He obliged.

After thanking him for giving me the opportunity to do what I do (in a roundabout way), I asked him: why Etsy?

Here is a person who can very likely walk into literally any tech job in the world – so I was entirely curious as to why he would take that job.

Rasmus explained how Etsy is a great choice if you want to make a real difference to the lives of artists.

There’s a ton of opportunities about (particularly in Silicon Valley) that are simply about making money for the various mega-corps, but Etsy enables real people to make a living from their art work.

I can identify with this not just because my wife is an artist, but because as coders a lot of what we do is more art than science. Well, at least that’s my interpretation of it. I can totally understand why Rasmus would take such a role.

Symfony Flex 101 – Renato Mendes Figueiredo

Symfony Flex is just around the corner. If you haven’t heard of Symfony Flex yet (come out from under that rock!) then you will do as of November 2017, when Symfony 4.0 becomes the new stable release.

My understanding of it is that Symfony Flex replaces the Symfony Installer. Symfony Flex aims to reduce / remove the boilerplate config needed to get most any Symfony bundle up and running.

The main point of concern I have currently is that this will possibly make it harder, not easier for those new to Symfony to get started. My own observations are that Symfony has lost a sizable chunk of new project market share over 2017 because of how difficult, by comparison, it is to get started with Symfony compared to e.g. Laravel.

Anyway, Renato’s talk was thankfully not about such things.

Instead it focused on how to use Symfony Flex to get a new project up and running. A live demo, over a potentially sketchy wifi connection is always fun, but Renato pulled it off.

Renato covered how to use some of the official recipes – for example to get the Web Debug Toolbar, and Web Server pulled into the project, and up and running without any configuration required.

Renato then covered pulling in, and starting a GraphQL server. All rather fantastic.

I thoroughly enjoyed this talk. I thought it was well presented, and the content was easy enough to digest in the allotted time. I found the demos interested, and the presentation style both relaxed and informative.

Great stuff.

Async requests and reactive responses with php-fpm – Holger Woltensdorf

This talk covered a problem that so many non-trivial PHP applications face:

How to do work in the background without it becoming a nightmare?

Typically when faced with background jobs I would reach for RabbitMQ. Holger showed that perhaps we could use PHP-FPM for the job, instead.

This is a really interesting project which I would advise you check out on GitHub.

The problem defined here has been puzzling me for a while. My personal experiences with RabbitMQ have been largely enjoyable in development, and largely horrible in production.

My own experiences tell me this is a really tricky and complex problem. The solutions to which are exactly the kind of black-box code that cause head-scratching and hair loss when they go wrong. If you have such a problem, potentially Holger’s library may offer you a solution.

As a side note I’ve lately been looking into the Elixir language as a potential alternative in this problem space. Some of the built-in features offer a potentially ‘simpler’ (or at least, less black-box-y) alternative. Time will tell.

Baking security into your workflow – Tim Nash

I have to admit by this point I was flagging. My brain was filled with good, useful stuff. What better then than a security talk!?

Fortunately Tim was full of enthusiasm and joviality, and was clearly enjoying presenting.

Tim drilled in the oft-repeated maxim of never trusting user data. Ever.

If you receive data from end-users then it must be validated. Good solid advice.

It made me think of how sometimes this kind of advice is really hard to bake into a real workflow, however.

For example, when working with Stripe and their Webhooks, one of their recommended practices is to verify the data signature. This is good advice, of course, but with some of Stripe’s Webhook data, it is impossible (to the best of my knowledge) to test – because the signatures don’t work in their faked / test responses. At least, that was my experience.

Of course this isn’t a slight on Tim’s talk in any way. It is simply that even with the best of intentions, security is flippin’ hard.

Tim shared a bevvy of useful tools, so here goes:

  • Kali Linux – full of hacker tools which you can pen-test your network / website(s) with.
  • Metasploit – I *think* this was the one Tim said was most Scriptkiddy-ish.
  • OWASP Zap – good, but possibly going to give false positives / noise
  • Vesuppi Garcon – detect a bunch of bad stuff via static analysis. Maybe useful in your CI pipeline?

A couple of other points made where:

  1. Disable registration on your WordPress blogs, if at all possible. And certainly don’t make the default user role to be Administrator. Lel.
  2. Watch your mail queue – often spikes are a great indicator of hacks.

The GDPR is coming, are you ready? – Michelangelo van Dam

The short answer: probably not.

The General Data Protection Regulation (GDPR) is a law that’s going to affect most everyone, as best I understand it. Essentially if you collect and process privacy related of EU subjects, you need to be paying attention.

(sorry that’s a terrible photo, and that’s saying something as typically my photos are terrible to begin with :))

Most big businesses have not got their acts together regarding GDPR as of yet.

You kinda ought to take this seriously, as if you suffer a data breach and are subsequently found responsible,and fined, you may very well be put out of business as the fines are incredibly steep.

One key takeaway from this talk is that you cannot be compliant with GDPR – you can only be ‘ready’. And defining ‘ready’ appears to be the biggest grey area of all.

It’s highly contentious, as was demonstrated during the QA section of this talk.

Hallway Track

For the first time ever at a conference I skipped a session (the closing session) to chat with a fellow dev.

I had a great chat with Rick West, who I encourage you to follow on Twitter.

Thanks Rick 🙂

After this it was back down the M61 for me, home in time for tea and medals.

Day 2

Yes, PHP North West is a two day conference over both a Saturday (all day), and a Sunday (till 13:00).

I missed the opening address – in fact, I didn’t even know there was an opening address on day 2 until reviewing the schedule for this blog post. Whoopsie daisy.

Chatbots and PHP – Katy Ereira

This was my favourite talk of the entire conference.

I remember relatively recently having a discussion with my wife about how, when I used to go to a bunch of business networking events, I was always getting asked “do you make apps?”, and “how much for an app?” etc. So many variants. So many people wanting the next Facebook for £1000.

Anyway, I don’t go to any of those business networking events anymore. Success.

But after hearing Katy mention how Bots are the new Apps, I do wonder now if the questions have changed to “how much for a bot?”. Thankfully, I’m happy to wonder.

I really enjoyed this talk because of how wonderfully practical and inspiring I found the content.

The examples were clear, and I could envisage real world use cases immediately.

The concept for the bot used in the talk was to accept restuarant reservations. To begin with this began as a command line app, but Katy explained how this could be turned into a Facebook or Slack bot without a huge amount of effort.

Times have moved on since I last looked into some of the concepts behind how these bots work. I remember working with spammy article spinners that would convert / spin articles using { he | him | man | person } sorts of thing, and the resulting articles came out at about the same quality as paying $5 for 10,000 words on odesk (ahem, upwork :/).

Nowadays, however, we don’t need to concern ourselves with such matters. Instead, Katy explained how we can simply hook into Google or Facebook’s AI, and get them to figure out what the user is talking about. Very fascinating, though I’m somewhat dubious about Google / Facebook’s longer terms plans from all this data collection.

Skynet was mentioned 🙂

Some interesting links:

Beep boop.

Teaching the next generation – Michael Woodward

I attended this talk as it seemed to be inline with what I’m trying to do.

Michael introduced us to his project – PHP School, which if you have ever used Node School should feel instantly familiar.

Taking ownership of your learning is a concept I feel more developers should pay attention too.

I strongly believe that being a software developer – if you enjoy writing software – is the best job in the world.

MySQL Worst Practises: Bring your system to its knees – Andrew Moore

After a somewhat unusual start, this talk was amongst my favourites of the conference. Fortunately I don’t do a huge amount with vast volumes of data in databases as of late, and haven’t had to do ops tasks on such complex setups as described for a good long while.

sorry this photo is bad 🙁

This talk, as the name suggests, focused on stuff that you ideally should not do if you want to get your 8 hours of sleep per night.

These included:

  • Don’t use NFS

Putting your database on disk accessible via the network introduces latency, which makes people sad.

  • SAN / NAS also not good because of the latency, and are effectively an expensive single point of failure.

NetApp were mentioned. Ho ho.

  • RAID 10 is preferable for your DB disk
However, we aren’t all made of money. Mirroring and striping are costly. But then, so is losing your data 🙂
  • Don’t put your temp dir on same disk as the data dir

Say no more.

  • Don’t use Windows as server

I wasn’t going to write anything further here, but Andrew did expand on that this is because lack of access to good MySQL tooling.

  • Don’t use MyISAM
Yesterday tech for today’s applications. My sides.
There are a bunch of other tips in Andrew’s slides which I am unfortunately not able to locate. If you do MySQL beyond the basics then I would urge you to watch the video of this talk when the vids are released.

Closing Keynote: For The Love Of Code – John Cleary

This talk had a couple of important points that left a lasting impression on me:

  1. If you want to do the Keynote, then you should ASK.

I don’t want to do a keynote. As a matter of fact, conference speaking in general holds very little appeal to me.

But asking is so, so important.

One of the hardest things do as a developer can be to ask for help. It feels like defeat.

However, often those around you would much rather you simply ask early, rather than spending hours / days / weeks going down rabbit holes or feeling lost / confused / distressed.

What’s the worst that can happen if you ask? You get rejected. Rejection sucks, but at least you asked. Now go ask someone else 😀

2. Test Your Core Values

In order to test your core values, you need to know what your core values are.

Now this exercise is beyond the scope of this blog post, but it’s well worth taking the time to do this, even if it feels like bull hockey.

The content of this talk is based on the book The 7 Habits of Highly Effective People by Stephen R. Covey. Also his website is built with PHP, so no excuses.

My only criticism of this talk was that it was too short. I’m not even sure why it was so short, perhaps it was explained but I missed it.

And On That Bombshell

All that remained was for the conference to be closed for another year.

At this point Jeremy dropped the bombshell that this was to be the last PHP North West conference for the foreseeable future.

I can understand this: plenty of conferences organisers have stated just how physically and emotionally taxing it is to run a conference, and after 10 consecutive years the entire crew of PHPNW are only to be applauded.

And indeed they were, with a standing ovation.

I’m not sure how to take the news that PHPNW18 won’t be a thing. I’m not sure what it says about PHP. This was the (possibly unanticipated) message that I pondered on my journey home.

The truth is PHP is not a sexy language right now. It hasn’t been for a good long while, and possibly never will be again. Depending on where you are in the world right now, there may be a language that is dominant in your location.

Typically that language is JavaScript.

I don’t see any immediate issue for PHP. For the next decade or so everything should be business as usual.

But as we approach 2030, will PHP still be relevant? It’s hard to say. And it ties in with the decline in new developers taking an interest in the language.

Anyway, rather than end of such a downbeat note:

I have thoroughly enjoyed my previous four years at PHP North West, and want to say a huge thank you to everyone involved in making it happen. I hope to see you all again in the future 🙂