Merry Christmas and a Happy New Year for 2018

This is the last you will be hearing from me – newsletter wise, at least – for 2017.

With that in mind I’d like to take this opportunity to say firstly a very big and sincere thank you to you for your support this year.

Whether your are a subscriber currently, have subscribed to the site in the past, or will be subscribing in the future, your support means a lot to me.

I’m really pleased with how things have progressed with CodeReviewVideos.com this year.

I launched the new site version, which whilst still a work-in-progress (and likely always will be) now is in line with almost everything new I’ve learned in the last four years.

I share everything I know on CodeReviewVideos.com, and from the feedback I’ve had this year (thank you!) I know it’s really helpful to many of you, too.

This site is all about saving you weeks, months, or even years off the amount of time it takes to learn a framework as big and (potentially) complex as Symfony.

There’s other great stuff on here too, like learning how to use Docker in the real world, and another of my personal favourites, React with Redux and Redux Saga all connected to a Symfony JSON API.

Video Update

This week saw three new videos added to the site.

#1 – Fixing Third Party Bundle Deprecations (Indirectly)

We’ve fixed the issues with Symfony’s code.

We’ve fixed the issues with our own code.

Now we must fix the issues with any third party bundles we are using.

In our case we have just one bundle – eightpoints/guzzle-bundle.

The issue we have is fairly common. If a bundle you use adds ‘stuff’ to the sidebar in the profiler, then you are almost certainly going to need to fix this issue. Well, I say you. What I really mean is you will need to hope your bundle maintainer has updated their code appropriately, or you have a few options:

  1. Don’t upgrade
  2. Fix it yourself (which may take a while to get merged)
  3. Fork it, and fix it yourself (hoorah, now you’re in open source)
  4. Be lucky and have the bundle maintainer already have updated it for you

We all hope for number 4, right?

Fortunately on eightpoints/guzzle-bundle we get lucky. This is fixed for us… but:

Always a but. This will mean we need to be on at least PHP 7. Actually thought, Symfony 4 needs PHP 7.1, so yeah… either way it’s time to come kicking and screaming in to the modern world of PHP. Good.

#2 – [Part 1/2] Migrating to Symfony 4.0 with Flex

The recommended approach for upgrading to Symfony 4 with Flex is to start a brand new Flex project, and then migrate code between the old project, and the new.

This brings a potential problem:

When you create the new Flex project you will, by default, get a git repo created on your local computer.

For the love of Mike, don’t do what I did and accidentally copy that git directory over your existing git directory. Whoops. I share for the comedy, and fortunately it didn’t cost me any, because that was during the write up, and I re-do the whole thing again for the video. I bet you don’t want to do things twice though 🙂

There’s a bunch of steps to work through, some easier than others. You won’t believe step 5! Ho, ho, a buzz feed style bit of link bait title nonsense.

No, but seriously, step 5 needs some extra attention so be sure to watch the video to learn what that is.

#3 – [Part 2/2] Migrating to Symfony 4.0 with Flex

Finally we finish up the Symfony 4 migration by moving over the src  directory contents from the old Symfony 3.4 project to the new Symfony 4 Flex approach.

We then move over the Twig templates. There’s more work to be done here, and some of the problems we will face are not very intuitive. I guess it depends on how much you’ve been following the changes made in Symfony 4.

It really does feel good to have migrated a complete project, regardless of the project’s size, from Symfony 3 to Symfony 4. There’s some serious sense of satisfaction in seeing everything continue to work, even with such a massive amount of change behind the scenes.

Here’s to 2018

Whatever you are up to in 2018 I sincerely wish you every success.

Thank you and happy Christmas!

Chris

Refactoring Legacy Code

Last week I started the journey of updating all the existing tutorial content from Symfony 2 and Symfony 3 up to Symfony 4.

I mentioned that I don’t plan on recording a video for every single migration.

I also mentioned that I would be covering the most requested content first. That’s why I started with the GitHut series, with which most site users who are brand new to Symfony take their first steps.

So far I’ve written 9000 words on updating from Symfony 3 to Symfony 4.

Nine thousand words.

I was staggered by this.

It’s left me wondering exactly who this content is aimed at? I can’t imagine a beginner taking a 6 video (7 including the bonus) course, and then thinking a further 6 videos on updating this small project to Symfony 4 is something that makes sense.

Also, the project is for beginners so I can’t imagine too many experienced developers using this as reference, either.

Anyway, I’ve started so I’ll finish.

As a heads up, whilst I’m updating these projects there are very likely to be a few weeks without some new videos. I have a limited amount of time per week to create new content, and the general consensus from support tickets is that updating existing content is preferable to new content.

Video Update

This week saw three new videos added to the site.

#1 – What happened to my Web Server?

This change happened earlier than in Symfony 3.4, but as we are using the GitHut project as the base of this series, we are impacted by this change.

If you aren’t aware, as of Symfony 3.3 the web server (available via bin/console server:start ) was extracted out into a separate bundle.

In hindsight this foretold the way that most things in Symfony would become – opt-in, rather than opt-out.

Anyway, removing the web server bundle is potentially unexpected, and adding it back in is the first in a list of tasks that we need to do to migrate from Symfony 3 to Symfony 4.

#2 – Fixing Generic Symfony Deprecations

Whatever your Symfony 3 application does currently, as soon as you upgrade to Symfony 3.4 you’re going to get a whole slew of deprecation warnings.

This is code that must be addressed by us as developers, if we are going to upgrade to Symfony 4.

Simply put, if we don’t fix these problems and then blindly update to Symfony 4 then our site will (most likely) just stop working.

A lot of these deprecation warnings sound complicated but are really just about adding in a speech mark here, or a new line there. Often if unsure, a quick Google is enough to see you right.

Even so, there are a bunch of these to cover and if you’re brand new to Symfony then this might not be a super easy task to complete. But don’t worry, this tutorial walks you through each fix, step by step.

#3 – Fixing Deprecations In Our Own Code

Whilst the previous video tackled problems that you’ll find in most every Symfony code base, in this video we look at specific problems to our own code.

It’s telling that even though the GitHut app is very simple compared to most real world projects, we still have a bunch of issues to solve. When I’ve approached this task on my own real world projects, the list of deprecations can be large and off-putting.

In this video we cover one of the most frequent problems you will encounter:

Legacy service definitions.

You may have already started using the new approach to Dependency Injection, and if so, you’re going to have a head start in this battle.

If you haven’t then now is the time to jump in and start learning some new stuff.

Ok, that’s it from me this week. Short and sweet.

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

Chris

Deploying Symfony

I want to start this week with a thank you to everyone who has given me feedback on the new site. I’m really happy that so many of you have found the time to send me an email or a tweet, it really does mean a great deal to me.

There are more changes forthcoming. I wanted the initial launch to be largely visually identical to the old site. From here on out I can more easily change and update both large and small parts of the site.

I’m being emailed quite a lot regarding the new Deployment series, launched this week. Mostly the questions are: “will you be covering X”

The answer is largely yes, I can cover deployment scenario X, but only if you tell me about it 🙂 I have my own ways of deploying, and those will be the ways I cover. If there’s a specific way you’d like to see – and crucially, I am capable of deploying that way – then I am happy to include it.

With that said, my best advice with deployments is: keep it simple.

There’s a bunch of tools out there already that by-and-large solve the deployment headache. We will be covering some of them in this series.

 

Video Update

This week saw four new videos added to the site.

#1 – Symfony LAMP (Linux, Apache, PHP, MySQL) Setup

We’re looking into deploying Symfony applications. We could go with Apache (think: the LAMP stack), or nginx (LEMP).

In this first video we cover how to quickly set up a LAMP stack for Symfony deployments.

Please note this is the bare minimum for a LAMP stack, not a production optimised environment. We are only using this for practicing deployments. We will get onto a more robust LAMP stack setup later in this series.

#2 – Symfony LEMP (Linux, nginx, PHP, MySQL) Setup

Three parts of this LEMP stack tutorial are identical to the LAMP stack tutorial above. I’ll leave it up to you to figure out which three 🙂

LEMP is a bit of a weird name – the E stands for way we pronounce nginx – Engine X.

Again this is a bare minimum for a LEMP stack, not a production optimised environment. We are only using this for practicing deployments. We will get onto a more robust LEMP stack setup later in this series.

#3 – Apache or nginx – You Gotta Get Your Permissions Sorted

Whether you have decided to go with Apache or nginx, you will need to get your permissions sorted out, or you’re going to have a bad time.

This will come back to visit us at various points in this series, and is one of those things its best to ingrain into your memory. I’m not saying you need to memorise the commands, just be aware of this and return to it as and when you encounter permissions problems.

#4 – Symfony 3.x Demo Deploy Project

With Symfony 4 rapidly approaching I was a little cautious about running a series on deploying Symfony apps – as everything is about to change.

That said, it’s unlikely that the change from Symfony 2 and Symfony 3 apps to Symfony 4 will happen over night. Plenty of 2 and 3 projects will persist for a good long while, in my opinion.

With that in mind, for the moment we are only covering deploying a Symfony 2.x and 3.x project, which both have the same directory structure. We will look at Symfony 4 deployments later in this series.

As a heads up, Symfony 4 drops on 30th November.

The project we are using as our demonstration is based on the official Symfony demo project. The reason for this is that it comes with a working app that involves the database, and has login already setup and good to go. This makes it a perfect example of a working Symfony website that might need deployment.

Ok, that’s all from me this week.

Have a great weekend, and happy coding.

Chris

 

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