Sevalla is the all-in-one PaaS for your web projects. Host and deploy your applications, databases, object storage, and static sites. Enjoy advanced deployment pipelines, a complete database studio, instant preview apps, and one-click templates. The pricing is simple: no hidden fees, no seat-based pricing, and you pay only for what you use. Get real human support from developers.

Get started now with a $50 credit at Sevalla.com.

Dissecting a spammer’s spam script

Link –

Let’s take a look at a PHP script used to send spam. These types of scripts run on servers all over the world and might give you some insight into a spammer’s dedication to annoy the hell out of you. ... One of the WordPress sites on a shared hosting web server I manage was infected by a spam script. Fortunately, the script was unable to do any real damage and was detected within half an hour of infection. I thought it would be fun to show you the script and dissect it, to find out exactly how these things work and make thousands of email administrators’ lives a living hell.
https://jelleraaijmakers.nl/2016/04/dissecting-spammers-spam-script

Read more

Enable http2 on a Forge provisioned server

Link –

Added on 2016-04-28: newly provisioned Forge servers will now use http2 by default whenever you install an ssl certifcate.

Like mentioned in the post on how to upgrade PHP, I'm a big fan of Forge. By default sites provisioned by Forge use regular http. Let's learn how to enable http2.

The http2 protocol provides a lot of benefits over http. In short it'll make your website load much faster. If want to know how this protocol works under the hood watch this excellent video by Mattias Geniar or read this blogpost at Cloudflare. Here an interesting test by (again) Mattias that shows the potential speed improvements.

A prerequisite for using http2 is that you serve your website via an encrypted connection (note: this is not 100% true but virtually all major browsers won't support http2 via unencrypted connections). Thanks to LetsEncrypt you can get free ssl certificates. Watch this free video on Laracasts to learn how to install a LetsEncrypt certificate.

Support for http2 was introduced in Nginx 1.9.5. You can check the version number of your Nginx installation by running nginx -v. If you're on 1.9.5 or higher you're good. You just have to add http2 to a server block in the Nginx configuration:

server {
  listen 443 ssl http2;
  ...
}

The Chrome developer tools can be used to check if you're site is indeed using http2. The column "protocol" should display "h2".

http2

Don't be overwhelmed with sadness if you're running something below Nginx 1.9.5. Upgrading is easy! Only three instructions are needed to upgrade to, at the time of this writing, Nginx 1.9.14:

sudo add-apt-repository ppa:nginx/development
sudo apt-get update
sudo apt-get install nginx

Read more

Stay up to date with all things Laravel, PHP, and JavaScript.

You can follow me on these platforms:

On all these platforms, regularly share programming tips, and what I myself have learned in ongoing projects.

Every month I send out a newsletter containing lots of interesting stuff for the modern PHP developer.

Expect quick tips & tricks, interesting tutorials, opinions and packages. Because I work with Laravel every day there is an emphasis on that framework.

Rest assured that I will only use your email address to send you the newsletter and will not use it for any other purposes.

Upgrading PHP 5.6 to 7.0 on a Forge provisioned server

Link –

If you've read some posts before on this blog, then you'll probably know that I'm a big fan of Forge. The service makes it very easy to set up and administer servers. At my company we've been using it since it launched.

We currently have 80 provisioned servers. Most of them are small droplets. We have a policy of running every site on it's own droplet. This approach has many benefits, but that's maybe something for a future post.

The bulk of our servers are on PHP 5.6. That's not too bad, but once you have some sites on PHP 7, the sites running on those servers feel a bit slow. It's amazing how fast you get used to the speed that PHP 7 offers. That's why I experimented a bit with upgrading the PHP version on a Forge provisioned server. My gut feeling was that upgrading the PHP version is less work that setting up a new server and moving a site to it.

To not mess up a live site I created a snapshot and used that to set up a server to toy around with. With a little bit of research I came up with these instructions to upgrade the PHP version.

sudo add-apt-repository ppa:ondrej/php

sudo apt-get update

sudo apt-get install php7.0

sudo apt-get install php7.0-fpm

Depending on your project you will need less or more php extensions, but these were the ones relevant for my site:

sudo apt-get install php7.0-gd

sudo apt-get install php7.0-mysql

sudo apt-get install php-memcached

sudo apt-get install php7.0-mcrypt

sudo apt-get install php-curl

sudo apt-get install php-imagick

Next, in the nginx configuration of the site I replaced unix:/var/run/php5-fpm.sock with unix:/var/run/php/php7.0-fpm.sock

The final adjustment I made was to make sure nginx would spawn the php processes under the forge. This will make sure that a php process can write to sites previously created by Forge:

// in the file /etc/php/7.0/fpm/pool.d/www.conf
...
user = forge
group = forge
...

After that I rebooted the server (maybe just restarting nginx is enough) and enjoyed browsing a site that was four times as fast. ?

If you decide to try this out for your server, be aware that what works for me doesn't necessarily work for you. Every site is a bit different. But I'm sure the instructions from this post will get you pretty far. Happy upgrading!

EDIT: Meanwhile DigitalOcean also published a guide on how to upgrade to PHP 7.

Read more

A great evening at PHPGent

Link –

Yesterday, after a winter sleep, PHPGent awoke and held a meetup at the offices of In The Pocket. It was nice to see some familiar and some new faces.

I had the honor of being the first speaker. My talk was titled "Backing up with Laravel". I started off with some best practices regarding backups and demonstrated the laravel-backup package which was released a few weeks ago.

Here are my slides:

https://speakerdeck.com/freekmurze/backing-up-with-laravel

phpgent_2016-Apr-14

Next up was Wouter Sioen of SumoCoders. He talked about building maintainable software. He showed how using the solid principles help to clean up the code of his home brew json to html converter. Then he continued with explaining object calisthenics: a few simple rules to greatly improve the readability of your code. Wouter's slides can found on github.io.

wouter

These two very beautiful graphic summaries of the talks were made by Peter Decuyper:

https://twitter.com/sgrame/status/720674134041235456

https://twitter.com/sgrame/status/720690758265778176

If you attended the meetup be sure to leave Wouter and me some feedback on joind.in so we can improve our speaking skills.

Visiting your local PHP user group is one of the best ways to learn new stuff and to getting to know the community. If you've never visited a user group, use this site to lookup the closest one to your home. If there isn't one close by, start one yourself.

Screen Shot 2016-04-14 at 23.43.52

Read more

Laravel medialibrary hits v4

Original – by Freek Van der Herten – 2 minute read

Today we tagged a new major version of laravel-medialibrary. In case you're not familiar with this package here's a quick rundown of what it can do. The package can associate all sorts of files with Eloquent models. It provides a simple, fluent API to work with. Here's a quick example: $newsItem =…

Read more

Recovering from a rm -rf

Link –

????

I run a small hosting provider with more or less 1535 customers and I use Ansible to automate some operations to be run on all servers. Last night I accidentally ran, on all servers, a Bash script with a `rm -rf {foo}/{bar}` with those variables undefined due to a bug in the code above this line.

All servers got deleted and the offsite backups too because the remote storage was mounted just before by the same script (that is a backup maintenance script).

http://serverfault.com/questions/769357/recovering-from-a-rm-rf

Read more

Making Eloquent models translatable

Original – by Freek Van der Herten – 2 minute read

Spatie, the company where I work, is located in Belgium. Although our country is quite small, there are three official languages: Dutch, French and German. That's why nearly all of our projects are multilingual. In most projects we used to rely on Dimitris Savvopoulos popular translatable package to…

Read more

Getting started with dotfiles

Link –

Dries Vints does not blog often, but when he does it's very much worth your time to read.

We all have specific ways of setting up our computer. It's all different somehow. The apps we use, our IDE settings, what shell we prefer, what programming languages we work with, the tools we prefer. How on earth are we going to get that specific setup back the way we had it before our computer broke down?

Enter dotfiles.

https://driesvints.com/blog/getting-started-with-dotfiles

You can find Dries' dotfiles on GitHub. Mine can be found here.

Read more

Easily store some loose values

Link –

For a site I was working on the admin should be able to switch on or off a form that's displayed on the homepage. Question: where's the best place to store the value of that switch? Creating a table and column for it in the database seems overkill. Putting it in a never expiring cache does not feel right. I think the best place to store such value is just write it to a simple file.

In the example above only one value needed to be stored, but for other projects there sometimes were two or three of them. Over the years I found myself writing the same code over and over again to store and work with such values.

Our intern Jolita and I whipped up a valuestore package. It only provides one class: Valuestore. The values will get written as JSON in a given file. The API mostly reflects Laravel's caching API. Here's how you can work with it:

$valuestore = Valuestore::make($pathToFile);

$valuestore->put('key', 'value');

$valuestore->get('key'); // Returns 'value'

$valuestore->has('key'); // Returns true

// Specify a default value for when the specified key does not exist
$valuestore->get('non existing key', 'default') // Returns 'default'

$valuestore->put('anotherKey', 'anotherValue');

// Put multiple items in one go
$valuestore->put(['ringo' => 'drums', 'paul' => 'bass']);

$valuestore->all(); // Returns an array with all items

$valuestore->forget('key'); // Removes the item

$valuestore->flush(); // Empty the entire valuestore

$valuestore->flushStartingWith('somekey'); // remove all items who's keys start with "somekey"

$valuestore->increment('number'); // $valuestore->get('key') will return 1 
$valuestore->increment('number'); // $valuestore->get('key') will return 2
$valuestore->increment('number', 3); // $valuestore->get('key') will return 5

// Valuestore implements ArrayAccess
$valuestore['key'] = 'value';
$valuestore['key']; // Returns 'value'
isset($valuestore['key']); // Return true
unset($valuestore['key']); // Equivalent to removing the value

// Valuestore impements Countable
count($valuestore); // Returns 0
$valuestore->put('key', 'value');
count($valuestore); // Returns 1

As you see it's quite a simple class, but I'm sure it'll come in handy in the future. The package can be found on GitHub.

Read more

Publishing package assets the right way

Original – by Freek Van der Herten – 2 minute read

At Spatie we do not only create a lot of Laravel packages, but we use also use a bunch of existing ones. In this post I'd like to give a quick hint to our fellow package developers. In the readme's of packages you'll often find an instruction like this to publish it's assets: php artisan…

Read more

The 5 laws of software estimates

Link –

Estimates are typically a necessary evil in software development. Unfortunately, people tend to assume that writing new software is like building a house or fixing a car, and that as such the contractor or mechanic involved should be perfectly capable of providing a reliable estimate for the work to be done in advance of the customer approving the work. This is pretty attainable by building contractors and auto mechanics, who generally are working with known materials building known things in known ways. ... With custom software, however, a great deal of the system is being built from scratch, and usually how it’s put together, how it ultimately works, and what exactly it’s supposed to do when it’s done are all moving targets.

https://medium.com/@ardalis/the-5-laws-of-software-estimates-fd13af46000b#.94s2f42fz

Read more

Things I used to do (that aren’t cool now)

Link –

In a post on his blog Michael Stivala looks back on his own code written a year ago. Because he learned a lot of stuff in a year time, he seems a lot of room for improvement.

As I’m picking up the codebase ahead of this Summer’s updates, I can’t help but review and refactor the existing code. It’s interesting to dissect previous design decisions. Also, I’ve learnt so much in the last year that it’s only natural for me to want to bring the standard of an older project up a bit.
https://michaelstivala.com/things-i-used-to-do-that-arent-cool-now/ If you look at your own code from a year (or longer ago) and think "this is allright, I can't improve on this", chances are you're not learning enough.

Read more

A package to protect your work in progress from prying eyes

Link –

Imagine you are working on new app. Your client wants to see the progress that you've made. However your site isn't ready for prime time yet. Sure, you could create some login functionality and display the site only to logged in users. But why bother creating users when there is a more pragmatic approach?

At Spatie we often instruct a client to visit /demo. Visiting that url will unlock access to the entire front site. Because creating packages has many benefits we decided to open source our solution.

Our newly released laravel-demo-mode package blocks your work in progress from prying eyes. After it is installed you can use a route macro to register a route that grants access to the protected routes:

Route::demoAccess('/demo');

Routes can be protected by using the demoMode-middleware on them:

Route::group(['middleware' => 'demoMode'], function () {
    Route::get('/secret-route', 'SecretController@index');
});

Unless a user has first visited /demo first, he or she will be redirected to /under-construction. This url can be changed in the config file.

A word to the wise: do not use this package to restrict access to sensitive data or to protect an admin section. For those cases you should use proper authentication.

You can take a look at the package on GitHub. If you like it, you might like some of our other Laravel packages as well.

Read more

Converting PHP 7 code to equivalent PHP 5 code

Link –

In the JavaScript world converting modern code to an older syntax is quite common. In the PHP world you don't see that happen often. Symfony provides a few polyfills, but a full fledged conversion isn't available. At the meetup of our local PHP user group Jens Segers, Hannes Van de Vreken and I were toying around with the idea of converting PHP 7 code to equivalent PHP 5 code automatically.

Today our little hobby project called 7to5 was tagged 1.0.0. You can view the repo on GitHub.

What does it do?

The tool will convert PHP 7 to PHP 5 by:
  • removing scalar type hints
  • removing return type hints
  • removing the strict type declaration
  • replacing the spaceship operator by an equivalent PHP 5 code
  • replacing null coalesce statements by equivalent PHP 5 code
  • replacing group use declarations by equivalent PHP 5 code
  • replacing defined arrays by equivalent PHP 5 code
  • converting anonymous classes to regular classes

Because there are a lot of small things that cannot be detected and/or converted properly it is not guaranteed that the converted code will work. It's highly recommended to run your automated tests against the converted code to determine if it works.

Using the tool

7to5 can be installed globally by running:
composer install global spatie/7to5

Once that's done you can use php7to5 to convert a whole directory in one go:

php7to5 convert {$directoryWithPHP7Code} {$destinationWithPHP5Code}

Behind the curtains

Removing some of the features of PHP 7 like scalar type hints and return type hints seems quite easy. Replacing anonymous classes, spaceship operators and null coaleasance operators is al little harder.

Image how you would convert this:

class Test
{
    public function test()
    {
        $class = new class() {
            public function method(string $parameter = '') : string {
                return $parameter ?? 'no parameter set';
            }
        };
        
        $class->method();

        $anotherClass = new class() {
            public function anotherMethod(int $integer) : int {
                return $integer > 3;
            }
        };
    }
            
}

to this:

class AnonymousClass0
{
    public function method($parameter = '')
    {
        return isset($parameter) ? $parameter : 'no parameter set';
    }
}

class AnonymousClass1
{
    public function anotherMethod($integer)
    {
        return $integer < 3 ? -1 : ($integer == 3 ? 0 : 1);
    }
}

class Test
{
    public function test()
    {
        $class = new AnonymousClass0();
        $class->method();
        $anotherClass = new AnonymousClass1();
    }
}

After the meetup of our usergroup the idea lay dormant for a while, but at this year's PHPUKConference Hannes decided to just do it™. I was immediately pulled in. We ran over a few options. It quickly became apparent that using regex was out of the question. Using a state machine would become very unwieldy fast too. We settled on using the PHP parser tool created by Nikita Popov. This tool can convert PHP code to an abstract syntax tree. It's very similar to a domtree for html code. Here's an example (taken from the php parser docs). This code:

echo 'Hi', 'World';
hello\world('foo', 'bar' . 'baz');

will get converted to this tree:

[
    0: Stmt_Echo(
        exprs: [
            0: Scalar_String(
                value: Hi
            )
            1: Scalar_String(
                value: World
            )
        ]
    )
    1: Expr_FuncCall(
        name: Name(
            parts: [
                0: hello
                1: world
            ]
        )
        args: [
            0: Arg(
                value: Scalar_String(
                    value: foo
                )
                byRef: false
            )
            1: Arg(
                value: Expr_Concat(
                    left: Scalar_String(
                        value: bar
                    )
                    right: Scalar_String(
                        value: baz
                    )
                )
                byRef: false
            )
        ]
    )
]

Here's the code to create the abstract syntax tree.

//create a parser
$parser = (new PhpParser\ParserFactory())->create(PhpParser\ParserFactory::PREFER_PHP7);

//feed it PHP 7 code
$php7code = file_get_contents($pathToPhp7File);

//this variable now contains the entire syntax tree
$syntaxTree = $parser->parse($php7code);

Now that we have created the abstract syntax tree, let's manipulate it. The tree can be traversed by a Traverser. The manipulation can be done by one or more Visitors objects. Let's view some code that traverses the tree and converts it back to regular PHP code.

$traverser = new PhpParser\NodeTraverser();

$traverser->addVisitor(new NullCoalesceReplacer());

$manipulatedTree = $traverser->traverse($syntaxTree);

//convert the tree back to regular code
$code = (new \PhpParser\PrettyPrinter\Standard())->prettyPrintFile($manipulatedTree);

file_put_contents($pathToFileWithManipulatedPhpCode, $code);

The real magic happens in the NullCoalesceReplacer class. It will convert all usages of the null coalesce operator, which is exclusive to PHP 7, to equivalent PHP 5 code. This class is not a part of Nikita's package. Hannes and I created it together with all other visitors.

Before taking a look at the code of that class, we'll first examine how we would manually replace a null coalesce operator.

//PHP 7 code
$result = $input ?? 'fixed-value';

//equivalent PHP 5 code
$result = isset($input) ? $input : 'fixed-value';

Let's describe the needed conversion in plain English. We'll need to create a ternary statement. The left hand side of the '??' needs to put in an isset statement. The true branch of the ternary statement needs to use the left hand side of the '??'-operator, the false branch needs the right hand side.

Here's the code of the NullCoalesceReplacer-visitor.

namespace Spatie\Php7to5\NodeVisitors;

use PhpParser\Node;
use PhpParser\Node\Expr\BinaryOp\Coalesce;
use PhpParser\NodeVisitorAbstract;

class NullCoalesceReplacer extends NodeVisitorAbstract
{
    public function leaveNode(Node $node)
    {
        //don't do at thing if the given node is not a Coalesce operator we
        if (!$node instanceof Coalesce) {
            return;
        }

        //create an isset functional call with the left side of '??' as the first parameter
        $issetCall = new Node\Expr\FuncCall(new Node\Name('isset'), [$node->left]);

        //replace the entire node by a ternary statement
        return new Node\Expr\Ternary($issetCall, $node->left, $node->right);
    }
}

Let's review another visitor. This one will remove all scalar type hints:

namespace Spatie\Php7to5\NodeVisitors;

use PhpParser\Node;
use PhpParser\Node\Param;
use PhpParser\NodeVisitorAbstract;

class ScalarTypeHintsRemover extends NodeVisitorAbstract
{
    public function leaveNode(Node $node)
    {
        if (!$node instanceof Param) {
            return;
        }

        if ($this->isScalar($node->type)) {
            $node->type = null;
        }
    }

    /**
     * @param string|null $type
     *
     * @return bool
     */
    protected function isScalar($type)
    {
        return in_array($type, ['int', 'integer', 'float', 'string', 'bool', 'boolean']);
    }
}

Using an abstract syntax tree sure makes manipulating code fairly readable. There are quite a number of other visitors. You can take a look at them on GitHub.

In closing

Honestly, I don't think I will ever use this tool myself. I'd rather upgrade a server to PHP 7 that converting code to PHP 5. That being said, it was a fun project to work on. It has a certain coolness factor. I learned that manipulating code using PHP parser is not that hard. Maybe I can use that knowledge on another project someday.

Meanwhile a more featured rich project that converts PHP 7 code has popped up (so if you do want to convert some PHP 7 code take a look at that one too).

Read more

Dropping the public keyword

Link –

Evert Pot makes some sound arguments in favor of dropping the public keyword.

I think people should be using "var" instead of "public". I realize that this is as controversial as tabs vs. spaces (as in: it doesn’t really matter but conjures heated discusssions), but hear me out!

Over the last year I’ve been going through all my open source projects, and I’ve been removing all the public declarations where this was possible.

...

"public" is completely optional. "public" is the default, so adding it does nothing to your code.

https://evertpot.com/drop-public-not-var/

Read more