Use sane defaults over exceptions

Freek Lijten, a developer at Schiphol, makes the case for just setting a sane default value instead of throwing an exception when invalid input entered the application.

I didn’t think much of this, but I’ve seen a major drawback lately while working on a site that is a bit bigger than I was used to. With over half a million visitors a week and lots of scrapers, bots and other stuff visiting, these exceptions and fatal errors clog up logging quite a bit. Not to the point that we can’t handle the volume, but it generates false positives in monitoring channels and it is something we do not want to act upon anyway.

http://www.freeklijten.nl/2017/01/04/Sane-defaults-over-Exceptions

Conditionally adding rules to a validator in Laravel

Mohamed Said explains the not so well known sometimes validation rule in Laravel.

Laravel’s validation library is very powerful and easy to use, using a few keystrokes you can build a strong defence around your application, preventing invalid user input from corrupting the application flow and potentially introducing bugs.

In this post I’d like to highlight a trick related to conditionally adding validation rules.

http://themsaid.com/laravel-advanced-validation-conditionally-adding-rules-20170110/

To learn more read the relevant section in the Laravel docs.

Why I close PRs

Jeff Geerling, currently working as a technical architect at Aquina, wrote a good post on when and why he closes PRs to the packages he’s maintaining. This paragraph resonated with me.

I don’t cater to everyone. I usually cater to myself. And for 98% of my OSS projects, I’m actually using them, live, in production (often for dozens or hundreds of projects). So I’m generally happy with them as they are. I will not add something that increases my maintenance burden unless it’s very compelling functionality or an obvious bugfix. I can’t maintain a system I don’t fully understand, so I like keeping things lighter and cutting off edge cases rather than adding technical debt I don’t have time to pay off.

http://www.jeffgeerling.com/blog/2016/why-i-close-prs-oss-project-maintainer-notes

Easily work with the Twitter Streaming API in PHP

Twitter provides a streaming API with which you can do interesting things such as listen for tweets that contain specific strings or actions a user might take (e.g. liking a tweet, following someone,…). In this post you’ll learn an easy way to work with that API.

Phirehose

When researching on how to work with the streaming API in PHP it stumbled upon Phirehose. This package can authenticate and set up a connection with the streaming API. Unfortunately the API of Phirehose itself is a bit unwieldy. That’s why I created a wrapper around Phirehose that makes setting up a connection to Twitter’s streaming API a breeze. I made a framework agnostic version of the package and a Laravel specific one.

Getting started

Let’s review how to integrate the package in a Laravel app. First you need to retrieve some credentials from Twitter. Fortunately this is very easy. Head over to the Application management on Twitter to create an application.

Once you’ve created your application, click on the Keys and access tokens tab to retrieve your consumer_key, consumer_secret, access_token and access_token_secret.

Now you’ve got the credentials let’s install the package in a Laravel app.

Like a gazillion other packages laravel-twitter-streaming-api can be installed via composer.

composer require spatie/laravel-twitter-streaming-api

Next, install the service provider.

// config/app.php
'providers' => [
    ...
    Spatie\LaravelTwitterStreamingApi\TwitterStreamingApiServiceProvider::class,
];

If you love working with facades, you’ll be happy to know that there’s one provider by the package.

// config/app.php
'aliases' => [
    ...
    'TwitterStreamingApi' => Spatie\LaravelTwitterStreamingApi\TwitterStreamingApiFacade::class,
];

The config file must be published with this command:

php artisan vendor:publish --provider="Spatie\LaravelTwitterStreamingApi\TwitterStreamingApiServiceProvider" --tag="config"

It’ll copy a file with this content in config/laravel-twitter-streaming-api.php

return [

    /**
     * To work with Twitter's Streaming API you'll need some credentials.
     *
     * If you don't have credentials yet, head over to https://apps.twitter.com/
     */

    'access_token' => env('TWITTER_ACCESS_TOKEN'),

    'access_token_secret' => env('TWITTER_ACCESS_TOKEN_SECRET'),

    'consumer_key' => env('TWITTER_CONSUMER_KEY'),

    'consumer_secret' => env('TWITTER_CONSUMER_SECRET'),
];

Create the TWITTER_ACCESS_TOKEN, TWITTER_ACCESS_TOKEN_SECRET, TWITTER_CONSUMER_KEY and TWITTER_CONSUMER_SECRET keys in your .env and set them to the values you retrieved on Twitter.

Now you’re ready to use the package.

Your first stream

Let’s listen for all tweets that contain the string #laravel. I’ve created an example Laravel app with the package preinstalled. This artisan command included to listen for incoming tweets:

<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;
use TwitterStreamingApi;

class ListenForHashTags extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'twitter:listen-for-hash-tags';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Listen for hashtags being used on Twitter';

    /**
     * Execute the console command.
     *
     * @return mixed
     */
    public function handle()
    {
        TwitterStreamingApi::publicStream()
            ->whenHears('#laravel', function (array $tweet) {
                dump("{$tweet['user']['screen_name']} tweeted {$tweet['text']}");
            })
            ->startListening();
    }
}

In case you haven’t used it before, that dump function does the same as dd but without the dying part. The call to startListening() starts the listening process. The function will run forever so any code after that won’t be executed.

Let’s go ahead an execute the command. In the output you’ll see some logging done by the underlying Phirehose package.

Now tweet something with #laravel in the tweet.

In the console you’ll see your own tweet appearing immediately.

Pretty cool! Be aware that this API works in realtime, so they could report a lot of activity. If you need to do some heavy work processing that activity it’s best to put that work in a queue to keep your listening process fast.

Another example

In the example above we’ve used the public stream. You can use that one to listen for tweets with specific strings posted on Twitter. But there also other kinds of streams. With the user stream you can listen for certain events that happen for the authenticated user.

Here’s an example that demonstrates how you can listen people favouriting on of your tweets:

TwitterStreamingApi::userStream()
->onEvent(function(array $event) {
    if ($event['event'] === 'favorite') {
        echo "Our tweet {$event['target_object']['text']} got favourited by {$event['source']['screen_name']}";
    }
})
->startListening();

In closing

The Twitter Streaming API’s are pretty powerful. If you want to know more about them take a look at the official docs. The easiest way to get started with them is by using our laravel specific or framework agnostic package. If you don’t like wrappers and want to use Phirehose directly, then read this tutorial on Scotch.io.

In any case check out the other PHP and Laravel packages our team has made before.

Have fun building a cool app using Twitter’s streaming APIs!

How to contribute to an open-source GitHub project using your own fork

Serial blogger Matt Stauffer wrote a good tutorial on how use forked repos.

I just recently joined a new open source project, and there were a few folks on the team who weren’t familiar with how to contribute to an open source project by forking your own copy, so I wrote this up for the docs of that project. I figured I’d also share it here.

If you join a new open source project, it’s very likely that you won’t get direct access to push commits or branches up to the repository itself. So, instead, you’ll fork the repo, make the changes on your version of the repo, and then “pull request” your changes back to the original.

Here are the steps to take.

https://mattstauffer.co/blog/how-to-contribute-to-an-open-source-github-project-using-your-own-fork

A Laravel package to rebuild the database

Out of the box Laravel comes with a few commands to migrate the database. One of them is migrate:refresh. That one will first run the down-steps for all your migrations and then run all the up steps. After that process your database should have the same structure as specified in your migrations.

But what if your migrations don’t have a down-step? Because I seldom have to revert a migration in my recent projects I haven’t bothered with coding up the down steps. And without those down steps running migrate:refresh will result in errors, or worse, tears.

I’ve created a little package that contains a command to quickly nuke all the tables in the database, run all migrations and all seeders. It will not use the down steps of the migrations but will simple use the output of the SHOW TABLES query to knock down all tables.

Once the package is installed this is how you can build up your database again:

php artisan migrate:fresh

Need to run the seeds as well? No problem!

php artisan migrate:fresh --seed

The package works on MySQL, PostgreSQL and SQLite databases. If you need to perform some extra steps right before or right after the tables are dropped, you can hook into these events.

This this all sound good to you? Then check out the package on GitHub. On our company site you’ll find a list of Laravel packages we’ve previously made.

Framework code complexity comparison

On his new blog on Medium, Taylor Otwell, creator of Laravel, published some statistics on the code complexity of various popular PHP frameworks. Draw your own conclusion.

Last week as I was refactoring and cleaning Laravel for the 5.4 release, Graham Campbell showed me some code complexity statistics for the framework. I decided to compare this against some other PHP frameworks to see how Laravel stacks up.

https:[email protected]/measuring-code-complexity-64356da605f9

Recently Taylor sat down with the folks at Larachat. Watch the recording to learn some other nice interesting tidbits about Laravel and it’s ecosystem.

Making overloaded functions readable

Sometimes you might allow a function to accept multiple data types. I don’t know for certain if it’s the correct term but for the remainder of this post I’m going to call such a function overloaded. In this post I’d like to show you a little trick to make overloaded functions more readable.

Let’s first take a look at a function in Laravel that accepts multiple data types. To store something in a session you can pass a key and value to the session helper:

session($key, $value);

But you can also give it an array:

session(['key' => 'value']);

Now behind the scenes Laravel is calling a put function. It could have been implemented like this:

public function put($key, $value = null)
{
    if (is_array($key)) {
       foreach ($key as $arrayKey => $arrayValue) {
           $this->set($arrayKey, $arrayValue);
       }
    }
    else {
       $this->set($key, $value);
    }
}

In the function above there’s a path for doing the work if an array was passed and another path for when (hopefully) a string was passed.

The actual implementation is a bit different (and much better):

public function put($key, $value = null)
{
    if (! is_array($key)) {
        $key = [$key => $value];
    }

    foreach ($key as $arrayKey => $arrayValue) {
        $this->set($arrayKey, $arrayValue);
    }
}

The cool thing to note is that what the function first converts the passed arguments to a certain format (in this case an array) and then perform the work on the format. The actual work, the call to $this->set is only coded up once. When reading the source code of Laravel you’ll often come across this pattern.

Let’s take a look at another real life example to make the benefit of this pattern more clear. This next snippet is taken from a recent PR to the laravel-permission package. It aims to a add a query scope to a User model to perform the query only on users that have the given role(s). Roles can be passed through as an array, a string or an instance of Role.

/**
 * Scope the user query to certain roles only.
 *
 * @param string|array|Role|\Illuminate\Support\Collection $roles
 *
 * @return bool
 */
public function scopeRole($query, $roles)
{
    if (is_string($roles)) {
        return $query->whereHas('roles', function ($query) use ($roles) {
            $query->where('name', $roles);
        });
    }

    if ($roles instanceof Role) {
        return $query->whereHas('roles', function ($query) use ($roles) {
            $query->where('id', $roles->id);
        });
    }

    if (is_array($roles)) {
        return $query->whereHas('roles', function ($query) use ($roles) {
            $query->where(function ($query) use ($roles) {
                foreach ($roles as $role) {
                    if (is_string($role)) {
                        $query->orWhere('name', $role);
                    }

                    if ($role instanceof Role) {
                        $query->orWhere('id', $role->id);
                    }
                }
            });
        });
    }

    return $query;
}

The query is being build up in a few different ways depending on the type of the argument being passed through. The readability of this code can vastly be improved by:

  • first converting all arguments to a single format to work with
  • performing the work on that format
public function scopeRole($query, $roles)
{
    if ($roles instanceof Collection) {
        $roles = $roles->toArray();
    }

    if (! is_array($roles)) {
        $roles = [$roles];
    }

    $roles = array_map(function ($role) {
        if ($role instanceof Role) {
            return $role;
        }

        return app(Role::class)->findByName($role);
    }, $roles);

    return $query->whereHas('roles', function ($query) use ($roles) {
        $query->where(function ($query) use ($roles) {
            foreach ($roles as $role) {
                $query->orWhere('id', $role->id);
            }
        });
    });
}

In the snippet above all input, no matter what type is being passed through, is first converted to an array with Role objects. U sing that array the query is only being build up once. I should mention that the author of the PR did provide a good set of tests so it was very easy to refactor the code.

Let’s do one more example. This one’s taken from our laravel-fractal package which aims to make working with Fractal more developer friendly.

To return a response with json data you can to this in a Laravel app.

$books = fractal($books, new BookTransformer())->toArray();

return response()->json($books);

In the last version of our package a respond() method was added. Here’s the equivalent code using the respond method.

return fractal($books, new BookTransformer())->respond();

You can pass a response code as the first parameter and optionally some headers as the second

return fractal($books, new BookTransformer())->respond(403, [
    'a-header' => 'a value',
    'another-header' => 'another value',
]);

You can also set the status code and the headers using a callback:

use Illuminate\Http\JsonResponse;

return fractal($books, new BookTransformer())->respond(function(JsonResponse $response) {
    $response
        ->setStatusCode(403)
        ->header('a-header', 'a value')
        ->withHeaders([
            'another-header' => 'another value',
            'yet-another-header' => 'yet another value',
        ]);
});

This is original code for the function that was submitted through a PR (slightly redacted):

public function respond($callbackOrStatusCode = 200, $callbackOrHeaders = [])
{
    $response = new JsonResponse();

    $response->setData($this->createData()->toArray());

    if (is_callable($callbackOrStatusCode)) {
        $callbackOrStatusCode($response);
    } else {
        $response->code($callbackOrStatusCode);

        if (is_callable($callbackOrHeaders)) {
            $callbackOrHeaders($response);
        } else {
            $response->withHeaders($callbackOrHeaders);
        }
    }

    return $response;
}

Sure, that code does the job. Unfortunately the real work (in this case: modifying $response) is done all over the place. Let’s refactor! In the code below we’re going to convert all input to callables first and then use them to modify $response.

public function respond($statusCode = 200, $headers = [])
{
    $response = new JsonResponse();

    $response->setData($this->createData()->toArray());

    if (is_int($statusCode)) {
        $statusCode = function (JsonResponse $response) use ($statusCode) {
            return $response->setStatusCode($statusCode);
        };
    }

    if (is_array($headers)) {
        $headers = function (JsonResponse $response) use ($headers) {
            return $response->withHeaders($headers);
        };
    }

    if (is_callable($statusCode)) {
        $statusCode($response);
    }

    if (is_callable($headers)) {
        $headers($response);
    }

    return $response;
}

Hopefully you can use this neat little trick to improve the readability of your code as well.

Pragmatic coding

Stefan Koopmanschap argues that, besides writing beautiful code and using kickass frameworks and libraries, we should be able to do some quick and dirty coding as well.

Can you write me a simple script that fetches some information from an RSS feed and displays the titles? Like, just write me that script in a couple of minutes. I don’t care about tests, quality, etc. Just get me the information, quickly.

http://leftontheweb.com/blog/2017/01/04/pragmatic_coding/

How PHP Executes – from Source Code to Render

On the excellent PHP section of Sitepoint Thomas Punt has written a good high ievel overview of how PHP code is executed.

There’s a lot going on under the hood when we execute a piece of PHP code. Broadly speaking, the PHP interpreter goes through four stages when executing code:

– Lexing
– Parsing
– Compilation
– Interpretation

This article will skim through these stages and show how we can view the output from each stage to really see what is going on. Note that while some of the extensions used should already be a part of your PHP installation (such as tokenizer and OPcache), others will need to be manually installed and enabled (such as php-ast and VLD).

https://www.sitepoint.com/how-php-executes-from-source-code-to-render/

Quickly open a GitHub page from your terminal

At Spatie we use GitHub for both our client projects as our open source code. So in our day to day work we often have to open the browser to view issues of a repo or review pull requests.

Paul Irish, a well known developer and part of the Google Chrome team at Google, made a nice bash script to quickly open up a GitHub page from your terminal. If you’re on a path inside a git repo and type “git open” that’ll open up the corresponding page on GitHub.

The command also supports, amongst others, repos hosted on GitLab.com and Bitbucket.

https://github.com/paulirish/git-open

Using Varnish on a Laravel Forge provisioned server

For a project we’re working on at Spatie we’re expecting high traffic. That’s why we spent some time researching how to improve the request speed of a Laravel application and the amount of requests a single server can handle. There are many strategies and services you can use to speed up a site. In our specific project one of the things we settled on is Varnish. In this post I’d like to share how to set up Varnish on a Forge provisioned server.

High level overview

First, let’s discuss what Varnish does. Varnish calls itself a caching HTTP reverse proxy. Basically that means that instead of a webserver listening for requests, Varnish will listen for them. When a request comes in the first time it will pass it on to the webserver. The webserver will do its work as usual and send a response back to Varnish. Varnish will cache that response and send it back to the visitor of the site. The next time the same request comes in Varnish will just serve up it’s cached response. The webserver (and PHP/Laravel) won’t even be started up. This results in a dramatic increase in performance.

You might wonder how Varnish decides what should be cached and for how long. The answer: http headers. By default Varnish will look at the Cache-Control header in the response of the webserver. Let’s take a look example of such a header. This header will let Varnish know that this response should be cached for 60 seconds.

Cache-Control: public, max-age=60

Varnish can be configured in detail using a vcl. This stands or “Varnish Configuration Language”. It can be used to manipulate the request. You can do things such as ignoring certain headers, removing cookies before they get passed to the webserver. The response coming back from the webserver can be manipulated as well. Think of things like manipulating or add headers to the response. There are more advanced features like Grace Mode and Health Checks can be configured as well.

The remainder of this blogpost aims to set up a basic varnish installation on a Forge provisioned server. Before you continue reading I highly recommended watching this presentation Mattias Geniar gave at this year’s Laracon first. He explains some core concepts in more detail.

Prefer reading a blog post over watching a video? Then header over to this blogpost on Matthias’ blog.

Installing Varnish

Now that you know what Varnish is and what it can do, let’s get our handy dirty and install Varnish. If want to follow along provision a fresh server using Forge and install your project (or a clean Laravel installation) on it. I’m going to use the varnishtest.spatie.be domain for the remainder of this post. Replace this by your own url. Instead of using a clean Laravel installation I’m going to use a copy of our homegrown Laravel application template called Blender. By using Blender I’ll hopefully run into many gotcha’s when integrating Varnish with a real world app.

To install Varnish just run this command on your server:

sudo apt-get install varnish

This will pull in Varnish 4.x or Varnish 5.x. Both versions are fine.

Updating the default VCL

The VCL file – Varnish’ configuration file – is located at /etc/varnish/default.vcl. Out of the box it contains some empty placeholders functions. To make Varnish behave in a sane way we should write out how we want Varnish to behave. But, once more, Mattias Geniar has got our backs. He open sourced his VCL configuration. He went the extra mile and put very helpful comments throughout the template. Go ahead and replace the contents of /etc/varnish/default.vcl with the content of Mattias’ VCL.

Restart Varnish to make sure the updated VCL is being used:

sudo service varnish restart

Opening a port for Varnish

By default Varnish will listen for requests on port 6081. So the page that is seen when surfing to http://varnishtest.spatie.be (replace that url by the url of your project) is still being server up by nginx / PHP. Pointing the browser to http://varnishtest.spatie.be:6081 will result in a connection error. That error is caused by the firewall that by default blocks all requests to that port. In the Forge admin, underneath the “Network” tab you can add firewall rules. Go ahead and open up port 6081 by adding a line to that section.

Now surfing to http://varnishtest.spatie.be:6081 should display the same content as http://varnishtest.spatie.be:80. If, in your project that page doesn’t return a 200 response code, but a 302 you’ll see an Error 503 Backend fetch failed error. In my multilingual projects “/” often gets redirected to “/nl”, so I’ve encountered that error too. Let’s fix that. Turns out the Mattias’ VCL template uses a probe to determine if the back-end (aka the webserver) is healthy. Just comment out these lines by adding a # in front of it. A visit to http://varnishtest.spatie.be:6081 should now render the same content as on port 80.

Checking the headers

Even though the content of the pages of port 80 and 6081 are the same the response headers are not. Here are the headers of my test application:

Notice those X-Cache and X-Cache-Hits headers? They are being set because we told Varnish to do so in our VCL. X-Cache is set to MISS. And it stays at that value when performing some more requests. So unfortunately Varnish isn’t caching anything. Why could that be?

If you take another look at the headers you’ll notice that cookie called laravel_session is being set. By default Laravel opens up a new session for every unique visitor. It uses that cookie to match up the visitor with the session on the server. In most cases this perfectly fine behaviour. Varnish however will, by default, not cache any pages where cookies are being set. A cookie being set tells Varnish that the response it received is for a specific visitor. That response should not be shown to another visitor.

Sure, we could try to configure Laravel in such a way that it doesn’t set cookies, but that becomes cumbersome very quickly. To make working with Varnish in Laravel as easy as possible I’ve created a package called laravel-varnish. Simply put the package provides a middleware that sets a X-Cachable header on the response of every route the middleware is applied upon. In the Varnish configuration were going to listen for that specific header. If a response with X-Cacheable is returned from the webserver Varnish will ignore and remove any cookies that are being set.

Keep in mind that pages where you actually plan on using the session – to for example display a flash message or use authentication – cannot easily be cached with Varnish. There is a feature called Edge Side Includes with which you can cache parts of the page but that’s out of scope for this blog post.

Making Varnish play nice with Laravel

As mentioned in the previous paragraph I’ve made a Laravel package that makes working with Varnish very easy. To install it you can simply pull the package in via Composer:

composer require laravel-varnish

After composer is finished you should install the service provider:

// config/app.php

'providers' => [
    ...
    'Spatie\Varnish\VarnishServiceProvider',
];

Next you must publish the config-file with:

php artisan vendor:publish --provider="Spatie\Varnish\VarnishServiceProvider" --tag="config"

In the published laravel-varnish.php config file you should set the host key to the right value.

Next the Spatie\Varnish\Middleware\CacheWithVarnish middleware should be added to the $routeMiddleware array:

// app/Http/Kernel.php

protected $routeMiddleware = [
...
   'cacheable' => Spatie\Varnish\Middleware\CacheWithVarnish::class,
]

Finally, in you should add these lines to the vcl_backend_reponse function in your VCL located at /etc/varnish/default.vcl:

if (beresp.http.X-Cacheable ~ "1") {
    unset beresp.http.set-cookie;
}

Restart Varnish again to make sure the added lines will be used:

sudo service varnish restart

Now that the package is installed we can apply that cacheable middleware to some routes.

Route::group(['middleware' => 'cacheable'], function () {
   //all the routes that should be cached
});

I’ve gone ahead and cached some routes in my application. Let’s test it out by making a request to the homepage of the site and inspect the headers and response time.

You can see that the X-Cacheable header that was added on by our package. The presence of this header tells Varnish that it’s ok to remove all headers regarding the setting of cookies to make this response cacheable. Varnish tells us through the X-Cache header that the response came not from it’s cache. So the response was built up by PHP/Laravel. In the output you can also see that the total response time was a little under 200 ms.

Let’s fire off the same request again.

Now the value of X-Cache header is HIT. Varnish got this response from its cache. Nginx / Laravel and PHP were not involved in answering this request. The total response time is now 75 ms, an impressive improvement.

To flush cache content normally you need to run a so-called ban command via the varnishadm tool. But with the package installed you can just use this artisan command on your server:

php artisan varnish:flush

You could use this command in your deployment script to flush the Varnish cache on each deploy. Running curl -I -w "Total time: %{time_total} ms\n" http://varnishtest.spatie.be:6081/nl again will result in a cache miss.

Measuring the performance difference

The one small single test from the previous paragraph isn’t really enough proof that Varnish is speeding up requests. Maybe we were just a bit lucky. Let’s run a more thorough test. Blitz.io is an online service that can be used to perform load tests. Let’s run it against our application.

We’ll run this test:

It will run a bunch of get request originating from Ireland. In a time span of 30 seconds it will ramp up the load from 1 to 1000 concurrent users. This will result in about 26 000 request in 30 seconds.

The server my application is installed upon is the smallest Digital Ocean droplet. It has one CPU and 512 MB of RAM.

Let’s first try running the test on port 80 where nginx is still listening for requests.


O my… The test runs fine for 5 seconds. After that the response time quickly rises. After 10 seconds, when 200 concurrent request / second are hitting the server response times grow to over 2 seconds. After 15 seconds the first errors start to appear due to the fact the webserver is swamped in work. It starts to send out 502 Bad Gateway errors. From there on the situation only gets worse. Nearly all requests result in errors or timeouts.

Let’s now try the same test but on port 6081 where Varnish is running.


What. A. Rush. Beside the little hiccup at the end, the response time of all requests was around 80 ms. And even the slowest response was at a very acceptable 120 ms. There were no errors: all 26 000 requests got a response. Quite amazing.

Let’s try to find Varnish’ breaking point and up the concurrent requests from 1 000 to 10 000.


15 seconds in, with 2 500 requests hitting on our poor little server in one second, the response time rises to over a second. But only after nearly 30 seconds, with a whopping 6 000 requests a second going on, Varnish starts returning errors.

Installing Varnish: final steps

As it stands, Varnish is still running on port 6081 and nginx on port 80. So all the visitors of our site still get served uncached page. To start using Varnish for real the easiest thing your can to is to just swap the ports. Let’s make Varnish run on port 80 and nginx on port 6081.

Here are the steps involved:

1) edit /etc/nginx/sites-enabled/<your domain>. Change

listen 80;
listen [::]:80;

to

listen 6081;
listen [::]:6081;

2) edit /etc/nginx/forge-conf/<your domain>/before/redirect.conf. Change

listen 80;
listen [::]:80;

to

listen 6081;
listen [::]:6081;

3) edit /etc/nginx/sites-available/catch-all. Change

listen 80;

to

listen 6081;

4) edit /etc/default/varnish. Change

DAEMON_OPTS="-a :80 \

to

DAEMON_OPTS="-a :6081 \

5) edit /etc/varnish/default.vcl. Change

  .port = "80";

to

  .port = "6081";

6) edit /lib/systemd/system/varnish.service. Change

ExecStart=/usr/sbin/varnishd -j unix,user=vcache -F -a :6081 -T localhost:6082 -f /etc/varnish/default.vcl -S /etc/varnish/secret -s malloc,256m

to

ExecStart=/usr/sbin/varnishd -j unix,user=vcache -F -a :80 -T localhost:6082 -f /etc/varnish/default.vcl -S /etc/varnish/secret -s malloc,256m

I’m pretty sure there must be a more elegant way, but let’s just fire off the bazooka and restart the server. When it comes back up you’ll notice that headers of response on port 80 will contain X-Cache headers (set by Varnish) and those on port on 6081 (where Nginx is running) do not. If you wish to do so may remove the line that opens up port 6081 in Firewall rules screen on Forge.

And with that your Varnish installation should be up and running. Congratulations!

In closing

Varnish is a incredible powerful tool that can speed up your application immensely. In this post I’ve barely scratched the surface of what you can do with it. If you want to learn more about it, check out the official documentation or the aformentioned blogpost by Mattias Geniar.

Out of the box Varnish can’t handle https connections, so you’ll need to do some extra configurating to make it work.

For our particular project we settled on Varnish, but there are plenty alternatives to scale your app:

Also keep in mind that you should only use Varnish if you expect high traffic. For smallish sites you probably shouldn’t bother installing and configuring Varnish.

If you do decide to use Varnish, be sure to take a look at our laravel-varnish package. If you like it, check out our other Laravel and PHP packages.

10 things I learned making the fastest site in the world

David Gilbertson made a lighting fast site and wrote a fantastic article about it.

Writing a fast website is like raising a puppy, it requires constancy and consistency (both over time and from everyone involved). You can do a great job keeping everything lean and mean, but if you get sloppy and use an 11 KB library to format a date and let the puppy shit in the bed just one time, you’ve undone a lot of hard work and have some cleaning up to do.

https://hackernoon.com/10-things-i-learned-making-the-fastest-site-in-the-world-18a0e1cdf4a7

A collection of PHPStorm tips

Nikush Patel created an awesome little site where he shares PHPStorm tips. Every tip is demonstrated by an animated gif.

I’m a big fan of PhpStorm and an equally big fan of keyboard shortcuts and optimised workflows, so I wanted to share all the best tips and tricks I know to help everyone else make the most of PhpStorm as well!

I produce useful tips in bite-sized gif recordings so they are easier to consume than reading the docs.

http://phpstorm.tips/

Setting up Xdebug with Laravel Valet

On most of my day to day work I use Laravel Valet to develop locally. When hitting a bug often I just put a dd() statement in the code to quickly inspect what’s going on. But when encountering a complex bug this becomes tedious. Wouldn’t it be nice if we could add a breakpoint to our code and be able to inspect the values of all variables in one go (and even execute the script line by line)? Enter Xdebug. In this post I’ll show you easy it is to install and use it.

Installing Xdebug

I’m going to assume that you have are running macOS, have latest version of PHP installed together with homebrew.

To install xdebug, just run this command:

brew install php71-xdebug

In the last lines of the output of the installation indicated that there’s a new ini file created at /usr/local/etc/php/7.1/conf.d/ext-xdebug.ini. By running php --ini you can verify that php is reading that setting file.

Go ahead and add these lines to that file:

xdebug.remote_enable=true
xdebug.remote_host=localhost
xdebug.remote_port=9000
xdebug.remote_handler=dbgp

The above settings are needed to allow PHPStorm to connect to Xdebug. You can look up the meaning of the individual settings in the xdebug documentation. Port 9000 seems to be the default, but you may choose another port if you like.

Debugging a cli command

If you want to follow along with the rest of this post, create a fresh copy of laravel in a directory you parked with Valet. In my mac I’ve parked the /Users/freek/dev/sites directory. In that directory I ran laravel new laravel to create fresh copy of Laravel in the laravel directory.

Let’s first test out if we can add a breakpoint to a script that is running on the command line. Open up the newly created project in PHPStorm. In the Debug preferences in PHPStorm make sure the debug port is set to the same value you specified in the ini file. Also uncheck “Force break at the first line when a script is outside the project”.

Next up, select “Start listening for PHP Debug Connections” from the “Run” menu.

Let’s add our first breakpoint. Open up routes/console.php and add a breakpoint by adding click in the sidebar left on the $this->comment(... line.

Now let’s run the command in which we just place a breakpoint. Got to the command line and execute php artisan inspire. And boom, xdebug should activate.

In the variables pane you can now inspect every single variable in the script. In the console pane you can run arbitrary code. Handy! Explaining the Xdebug UI in PHPStorm is out of scope for this article. Read the PHPStorm docs to know more or just play around with it.

Debugging a web request

In order to trigger Xdebug a special cookie needs to be set on the webrequest. You can use the bookmarklets provided by Jetbrains to set those cookies. Personally I prefer using the Chrome Xdebug Helper extension.

With the extension installed just point your browser to your site, click on the little bug icon next to the address bar, and choose “Debug”.

That bug icon should turn green now indicating that the right cookies have been set. Now go to the a piece of code in your project that should run when the web request is performed. In my case I’m going to set a breakpoint in web/routes.php. When refreshing the webpage you should first see this dialog indicating that PHPStorm got an incoming connection from Xdebug.

After clicking “Accept” you should hit your breakpoint.

Congratulations on your working Xdebug installation!

A word on performance

With Xdebug enabled your PHP code will run a lot slower. Luckily Djamil Legato coded up an xdebug toggler make it easy to switch xdebug on and off with a single command.

You might see this warning when running composer:

You are running composer with xdebug enabled. This has a major impact on
runtime performance.

To solve that just update to the latest version of composer which can automatically detect and temporarily turn off Xdebug while it’s running.


If you had trouble following this guide, you might take a look at this video by Gary Hockin. He dives a little bit deeper in the Xdebug integration in PHPStorm.

Happy debugging!

PHP 5: Active Support Ends. Now what?

Starting from tomorrow PHP 5.6. will not be actively supported anymore. Sebastian Bergmann, author of PHPUnit explains how PHP’s release process works, and what the ending of active support means for you. Spoiler: you should upgrade asap.

It is high time to think about upgrading your PHP stack to PHP 7, ideally to PHP 7.1. This should be a short-term goal for you.

Upgrading the version of PHP you use must not be a rare event you are afraid of. You must not think of upgrading your PHP stack as a “special project”. You need to make upgrading the PHP version you use part of your normal operational procedure and align the upgrade cycle of your PHP stack with the release cycle of the PHP project. This should be a long-term goal for you.

https://thephp.cc/news/2016/12/php-5-active-support-ends-now-what

Looking back on the year

Laravel News published a nice overview of what happened in the Laravel ecosystem in 2016.

As 2016 is coming to a close it’s a great time to look back on the year and see just how much progress has been made. Laravel had a busy year with 5.3 being released, Laracon, updates to all the components, and now gearing up for the Laravel 5.4 release.

To look back on the year I’ve put together a list of some of the hits of 2016 and arranged them by month so you can get a quick overview of all the highlights.

https://laravel-news.com/80-laravel-tutorials-packages-and-resources

The Laravel ecosystem sure is moving fast. For me the best new software that emerged from it was Laravel Valet. I use it for most projects now and can’t imagine working on a Vagrant box anymore for my normal day to day work. Hopefully Valet will gain more recognition in the greater PHP community in 2017.

I’m also happy to report that the Laravel / PHP packages my company releases have grown in popularity in 2016.

A thousand best replies on the Laracasts forum

On the Laravel Daily blog Povilas Korop published an interview with Bobby Bouwmann. In the past two years Bobby earned almost a thousand best reply awards, an amazing accomplishment.

In recent years, Laracasts has become a no.1 resource for learning Laravel. Also, there’s a really active discussion forum on the website, so we decided to chat with one of the most active members there. Bobby Bouwmann has almost 1000 “Best Reply” awards on the forum, which is a huge number. So what is it like to be so active on Laracasts? Let’s find out.

http://laraveldaily.com/bobby-bouwmann-lessons-1000-best-replies-laracasts/

Inside PHP 7’s performance improvements

On the Blackfire.io blog Julien Pauli peeks behind the curtains of PHP. In the five part series he explains how you should write your code to make the best use of the internal optimizations present in PHP 7.

This blog series will show you what changed inside the Zend engine between PHP 5 and PHP 7 and will detail how you, as a developer, may effectively use the new internal optimizations. We are taking PHP 5.6 as a comparison basis. Often, it is just a matter of how things are written and presented to the engine. Performance must be taken care of when critical code is written. By changing some little things, you can make the engine perform much faster, often without losing other aspects such as readability or debugging control.

https://blog.blackfire.io/php-7-performance-improvements-packed-arrays.html

Dealing With Templates in Vue.js 2.0

Sebastian De Deyne, my colleague at Spatie, wrote a very nice overview of all different methods in Vue to define a template.

This article isn’t about Vue’s template syntax, but about where and how to define your templates. I wrote this because at the time of writing there aren’t really resources that consolidate all the different manners to manage your templates.

I’ve divided the different ways to define templates in three different categories, each with their own drawbacks:

  • Writing templates that compile at runtime (lesser performance)
  • Using single file .vue components (requires a build step)
  • Manually writing render functions (pure JavaScript, no html-like template syntax)

    https://sebastiandedeyne.com/posts/2016/dealing-with-templates-in-vue-20