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

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

Join 9,500+ smart developers

Get my monthly newsletter with what I learn from running Spatie, building Oh Dear, and maintaining 300+ open source packages. Practical takes on Laravel, PHP, and AI that you can actually use.

No spam. Unsubscribe anytime. You can also follow me on X.

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

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

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

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

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

A quick look at the WordPress database model

The database model behind WordPress doesn’t follow several good database design rules and conventions. When we’re designing a database for a specific purpose, knowing all its desired functionalities in advance, we can follow all of those rules. But WordPress needs to cover anything that anyone could have in mind, so sacrificing foreign keys and using EAV is something that must be done.
http://www.vertabelo.com/blog/technical-articles/wordpress-behind-the-scenes-part-2

Read more

Building a GIF search engine with React

Over at the Tighten blog Samantha Geitz posted an amazing introduction to React. She starts off by clearly explaining how to setup the environment (webpack and a few dependencies). After making sure that it all works, she continues by building a GIF search engine. Along the way the core concepts of React are explained. If you're in any way interesting in learning React, I warmly recommend reading the entire piece.

React itself is reasonably well-documented and easy to pick up, once you can shift your thinking to align with its conventions. The problem is, if you want to build robust apps, the V in MVC probably isn't going to cut it, and you have to dive into the often-confusing ecosystem surrounding React.

In this series, we're going to walk through the stages of building a React application — an app that lets you search the Giphy API and displays results, similar to what Giphy has on its own website.

In this first article, we are going to build the application using only React (with Webpack for asset compilation).

http://blog.tighten.co/react-101-building-a-gif-search-engine

I'm looking forward to read the next articles of this series.

Read more

A modern package to generate html menus original

by Freek Van der Herten – 4 minute read

Virtually every website displays some sort of menu. Generating html menus might seem simple, but it can become complex very quickly. Not only do you have to render some basic html, but you also have to manage which item is active. If a menu has a submenu you'll also want the parents of an active…

Read more

Easy file sharing from the command line

Transfer.sh is a free service by Dutchcoders that allows you to easily share files from the command line. Here's an example of how you can use it:

transfer my-favorite-file.txt

The given file will be uploaded to the transfer.sh-servers and the command will respond with a short url linking to that file. Pretty neat!

The only thing you need to do is set up a bash function called "transfer" (you can name it anything you want really).

Don't trust the transfer.sh with your supersecret files? Then you can set up your own server to transfer the files to.

Read more

Let your clients use sftp on a Forge provisioned server original

by Freek Van der Herten – 3 minute read

A few years ago all the projects I worked on were served on a shared hosting environment. It was quite common that a client had ftp access to server to upload some files. A control like Cpanel or Plesk made it really easy to create some ftp accounts. Fast forward to today. Most projects are hosted…

Read more

A Laravel package to clean up models original

by Freek Van der Herten – 1 minute read

Most databases will contain some records that must be cleaned up. The reasons why a record can become unneeded are diverse: maybe it's a temporary record that was only needed for a little while if you're logging stuff to a table, a record may become too old to be of interest anymore ... To help a…

Read more

How to rescue legacy code through refactoring

Jeroen Moens posted a, very well written, article on paying technical debt in a legacy codebase.

How can you get a legacy codebase under control and bring it to a new level of maturity? This post summarises my advice and lessons learned from years of working on a large legacy web application.
http://marketing.intracto.com/paying-technical-debt-how-to-rescue-legacy-code-through-refactoring

On a sidenote: as an Artisan I always like to sneak in a little Laravel in legacy projects. There are a lot of Illuminate components take can be used independently outside Laravel. If you want to do this too take a look at Matt Stauffer's Torch repo on GitHub.

Read more

A step by step guide to building your first Laravel application

Eric L. Barnes, the curator of Laravel News, recently launched his new website called dotdev. It aims to be a resource for developers who want to read quality reviews and tutorials amongst other things.

Although the site in general doesn't focus on Laravel, Eric wrote a good introductory post for people who are new to the framework. Unlike most beginner level articles, it focuses on creating a real world application.

My goal with this is to create a guide for those just learning the framework. It is setup to take you from the very beginning of an idea into a real deployable application. ... I am attempting to go through the process of creating a new application just as I would in a real world environment. In fact, the code and idea is taken from a project that I built.

https://dotdev.co/tutorials/step-by-step-guide-to-building-your-first-laravel-application/

For the first batch of posts on the site I made a playlist for coding late at night. Do you have something to share that would interest the readers of dotdev? Read these guidelines on guest posting first, and thenemail Eric.

Read more

Approaches to Testing: A Survey

The last few months have been my first opportunity to do automated testing at my full-time job. As I’ve been trying to get the hang of it, my biggest question has been how many of each type to test to write: how many unit, integration, and acceptance tests. Turns out Folks Got Opinions™ on this! As I researched, I found at least four different approaches to testing, and they each provide different answers to a number of questions I had.
http://codingitwrong.com/2016/02/08/approaches-to-testing-a-survey.html

Read more