Posts tagged with php

Converting big PHP codebases to PSR-2

It is known by now that every codebase large enough (in terms of lines of code or people collaborating to it) should follow any code standard. Here at Coolblue we weren’t different and were using our own coding standard.

But codebases evolve. And our codebase – that has been supporting one of the most visited ecommerces in The Netherlands – needed to be upgraded to a coding standard that’s a little bit more up to date.

This is the process we follow to move into PSR-2.

http://devblog.coolblue.nl/tech/converting-big-php-codebases-to-psr2/

In the past months we converted several of our old projects to PSR-2 with Fabien Potencier's coding standards fixer and had zero issues doing so. Hurray for standardized code.

 

Read more

Using collection macros in Laravel

Laravel 5.2 provides some nice additions to the framework. One handy feature that I don't see listed in the release notes is that Collection now is macroable. Using it's macro function you can easily extend Illuminate\Support\Collection with your own custom functions.

Take a look at this piece of code to uppercase every string in a collection.

$uppercaseWords = collect(['code', 'ferengi'])->map(function($word)  {
   return strtoupper($word);
});

That's good code, but image you need to uppercase a lot of collections. Typing the same closure will get very tiresome. Let's improve this with a macro.

use Illuminate\Support\Collection;

Collection::macro('uppercase', function() {

    return collect($this->items)->map(function($word) {
        return strtoupper($word);
    });

});

You could create a service provider to load up these macro's. Now that the macro is defined let's uppercase collections like there's no tomorrow:

$uppercaseWords = collect(['code', 'ferengi'])->uppercase();
$moreUppercaseWords = collect(['love', 'the', 'facade'])->uppercase();
$evenMoreUppercaseWords = collect(['activerecord', 'forever'])->uppercase();

You could be thinking "Why should I use a macro? I can easily to this with a regular function.". Consider this piece of code.

function uppercase($collection) {
...
}

$uppercaseWords = uppercase(collect(['halo','five']));

It works, but you have to encapsulate the collection with your function. The last executed function is put first, which is confusing. With macro's you can still chain functions and greatly improve readability.

//lots of functions
function4(function3(function2(function1(collect(['jack','cheats'])))));

//lots of macros
collect(['i', 'want', 'to', 'live', 'in', 'a', 'desert'])
  ->function1()
  ->function2()
  ->function3()
  ->function4();

Sure, the examples use in this post were a bit contrived, but I hope you see that collection macro's can be very handy.

EDIT: it seems that collection macro's were introduced in Laravel 5.1.25 a month ago.

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.

Fake the PHP version when running Composer

Mr. Composer, Jordi Boggiano, has posted an overview of composer features that have become available in the past year. A very nice one is config.platform.

The `config.platform` option lets you emulate which platform packages you have available on your prod environment. That way even if you have a more recent PHP version or are missing an extension locally for example, composer will always resolve packages assuming that you have the packages you declared installed.
That'll come in handy when you have a local php 7 environment and an older version installed on the server.

Read more

Processing big DB tables with Laravel's chunk() method

Povilas Korop shared a neat trick at Laraveldaily.com today.

Let’s imagine the situation: you have a big database table (like 10 000 rows or bigger) and you need to run an update to one column. But you cannot run just SQL query – there is some PHP logic behind it. So foreach loop could potentially take forever or bump into a default 30-second script limit. Luckily, Laravel has a neat solution for it.
http://laraveldaily.com/process-big-db-table-with-chunk-method/

Read more

Making call_user_func_array more readable

There's a lot PHP 7 love going around these days, but PHP 5.6 has it's fair share of nice features too. One of those features is the splat operator. It looks like this: ....

The splat operator can capture a variable number of arguments.

function logThis(...$messages)
{
    foreach ($messages as $message) {
        echo $message.PHP_EOL;
    }
}

logThis('one', 'two', 'three');

You can still use regular arguments as well:

function logThis($firstMessage, ...$otherMessages)
{
    echo "superimportant: {$firstMessage}".PHP_EOL;

    foreach ($otherMessages as $message) {
        echo $message.PHP_EOL;
    }
}

logThis('one', 'two', 'three');

Another usage for the splat operator is argument unpacking:

$messages[] = "one";
$messages[] = "two";
$messages[] = "three";

logThis(...$messages);

The operator can also help replacing usages of call_user_func_array to something more readable. Consider this contrived example where all calls to a class are forwarded to a dependency.

class ClassA
{
    protected $classB;

    public function __construct(ClassB $classB)
    {
        $this->classB = $classB;
    }

    public function __call($method, $args)
    {
        call_user_func_array([$this->classB, $method], $args);
    }
}

Using this splat operator this can be rewritten to:

class ClassA
{
    protected $classB;

    public function __construct(ClassB $classB)
    {
        $this->classB = $classB;
    }

    public function __call($method, $args)
    {
        $this->classB->$method(...$args);
    }
}

Do you know some other cool usage of the operator? Let me know in the comments below.

Read more

Installing Imagick on a Forge provisioned PHP 7 server

Update added on 14th november 2017: Adding imagick on a forge provisioned server is now as simple as running sudo apt-get install php-imagick


Today I set up some PHP 7 servers on Forge. Those servers are going to be used to host some Blender based projects. Blender uses laravel-medialibrary to convert images. The package uses Imagick to do that. It turns out the Imagick PHP 7 extension isn't released yet. But there's an RC2 release candidate. Pascal Baljet provided this script to compile and install the extension.

#!/bin/bash
if [ "$EUID" -ne 0 ]
  then echo "Please run as root"
  exit
fi

apt-get install pkg-config libmagickwand-dev -y
cd /tmp
wget http://pecl.php.net/get/imagick-3.4.0RC2.tgz
tar xvzf imagick-3.4.0RC2.tgz
cd imagick-3.4.0RC2
phpize
./configure
make install
rm -rf /tmp/imagick-3.4.0RC2*
echo extension=imagick.so >> /etc/php/7.0/cli/php.ini
service php7.0-fpm restart
service nginx restart

I was a bit worried that the extension would be unstable, but all image manipulations that I need on my projects (cropping and resizing some stuff), just worked. Mandatory disclaimer: your mileage may vary.

Read more

A better way to style the output of console commands

When creating output from a Symfony based console command you might have created a title using code like this:

$output->writeln('');
$output->writeln('<info>Lorem Ipsum Dolor Sit Amet</>');
$output->writeln('<info>==========================</>');
$output->writeln('');

Starting from Symfony 2.7 there's a nice way to style the output of console commands. This code produces the same output as the example above

$io = new SymfonyStyle($input, $output)
$io->title('Lorem Ipsum Dolor Sit Amet');

There are styles for titles, sections, questions, tables, and so on. Take a look at the documention to learn what's possible.

Read more

Pipelines, immutability and privates

In a new article on his blog Frank De Jonge demonstrates a lesser known feature/bug of PHP.

When two objects are of the same type, they can access the private properties of the other. This might seem like a bug, but it's actually a very valuable feature. For instance, it allows you to perform very efficient equality checks without the need to publicly expose your internals.
http://blog.frankdejonge.nl/pipelines-immutability-and-privates/

Read more

Exporting json for a mobile app using Laravel

Every year the city of Antwerp (my hometown :-)) organises lots of activities, such as an Ice rink, a Christmas market, a Santa Run and of course fireworks in the month of december. To inform people of which activities are happening where and when my team and I created a mobile app commissioned by the city council. The app is called "Winter in A" and is available on both Android's Play Store and iOS' App Store.

The administrators of the app can enter content in a custom installation of Blender, our Laravel based application. Blender will write of a bunch of json-files that are read by the mobile apps. Here's the file for all the events (english localization): https://api.winterapp.be/en/events.json. We use our homegrown laravel-fractal package to easily transform database records to json. Here's the export handler that's in charge of the exporting of events:

namespace App\Services\Export\ExportHandlers;

use App\Repositories\EventRepository;
use App\Services\Export\ExportHandler;
use App\Services\Export\Transformers\EventTransformer;

class Events implements ExportHandler
{
    /**
     * @var \App\Repositories\EventRepository
     */
    protected $eventRepository;

    public function __construct(EventRepository $eventRepository)
    {
        $this->eventRepository = $eventRepository;
    }

    /**
     * Get the json for the given locale.
     *
     * @param string $locale
     *
     * @return mixed
     */
    public function getJsonForLocale($locale)
    {
        return fractal()
            ->collection($this->eventRepository->getAllOnline())
            ->transformWith(new EventTransformer($locale))
            ->toJson();
    }
}

The EventTransformer itself:

namespace App\Services\Export\Transformers;

use App\Models\Event;
use App\Services\Export\Format;
use App\Services\ValueObjects\Period;
use League\Fractal\TransformerAbstract;
use Spatie\MediaLibrary\Media;

class EventTransformer extends TransformerAbstract
{
    /**
     * @var
     */
    protected $locale;

    public function __construct($locale)
    {
        $this->locale = $locale;
    }

    public function transform(Event $event)
    {
        return [
            'id' => $event->id,
            'name' => $event->translate($this->locale)->name,
            'text' => htmlToMarkdown($event->translate($this->locale)->text),
            ...
            'images' => $event->getMedia('images')->map(function (Media $media) {
                return [
                   'thumb' => $media->getUrl('thumb'),
                   'full' => $media->getUrl('full')
                ];
            }),
        ];
    }
}

To handle peaks in usage of the app we use CloudFlare. In this article they explain what they do. Cloudflare has this awesome feature called "Always online", to make sure the API is online even if our server is not.

The first events of Winter in Antwerp are starting tomorrow. The last ones are scheduled in the first days of 2016. I'll share some more tidbits of the code then.

Read more

Enabling autocompletion for dynamic return types in PhpStorm

If you're using PhpStorm you probably make heavy use of it's autocomplete features. The IDE can, for most classes, suggests all accessible functions. Unfortunately, when a function has a dynamic return type PHPStorm will leave you out in the cold. So when resolving something out of Laravel's IoC-container PhpStorm cannot help you. Here's an example with one of the repositories of Blender:

Screen Shot 2015-12-04 at 20.42.42

PhpStorm can't suggest functions because it doesn't know which class the make-function will return. Let's fix that.

The DynamicReturnType plugin provides a way to dynamically specify the return type of a function. You can install it like every other PHPStorm plugin. Next you'll have to create a file called dynamicReturnTypeMeta.json in the root of your project with this contents:

{
    "methodCalls": [
        {
            "class": "\\Illuminate\\Contracts\\Foundation\\Application",
            "method": "make",
            "position": 0
        }
    ]
}
```

This configuration will tell PHPStorm that the return type of the make-function of Illuminate\Contracts\Foundation\Application will return an instance of class specified in the first argument.

With this file in place PHPStorm can perform autocompleting:

Screen Shot 2015-12-04 at 20.34.59

To learn all other possibilities the plugin offers, read it's documentation on GitHub.

Update: As Nicolas Widart mentions in the comments below there's another (and maybe easier way) to get autocompletion when resolving stuff from Laravel's IoC-container. The ide-helper package can generate a meta file that, when indexed, will make PhpStorm understand which object gets returned.

Read more

Optimizing league/commonmark with Blackfire.io

For the League's CommonMark parser, we chose to prioritize extensibility over performance. This led to a decoupled object-oriented design which users can easily and customize. This has enabled others to build their own integrations, extensions, and other custom projects.

The library's performance is still decent - the end user probably can't differentiate between 42ms and 2ms (you should be caching your rendered Markdown anyway). Nevertheless, we still wanted to optimize our parser as much as possible without compromising our primary goals. This blog post explains how we used Blackfire to do just that.

http://www.colinodell.com/blog/2015-11/optimizing-league-commonmark-blackfire-io

Read more

A package to check all links in a Laravel app original

by Freek Van der Herten – 1 minute read

A few weeks ago I made a cli tool to check the status code of all links on a site. It made use of a home grown crawler. Today the Laravel integration gets released. The new package called laravel-link-checker can log all broken links. By default, a link is considered broken if the status code of…

Read more

This blog is one year old original

by Freek Van der Herten – 2 minute read

Exactly one year ago the very first post on murze.be was published. This blog was mainly started as a way to bookmark interesting links. Along the way I shared programming tips, talked a bit about learning and gave some background on the Spatie packages. It's been a fun ride and looking at the…

Read more

The future of PHP

Anthony Ferrara gave a excellent "state of php"-talk at php[world].

PHP is experiencing a renaissance; old methodologies are everywhere under assault from advances in tooling and design. From Composer to HackLang, "the PHP way" of solving problems is dramatically evolving. Walls between projects are falling; interoperability and collaboration are happening on levels never thought possible. What do these accelerating changes mean for the future of the language? What might PHP8 look like? How will our communities continue to collaborate and evolve? And most pressing: what steps can we take to ensure PHP's continuing vibrancy in the face of future technical challenges?
https://www.youtube.com/watch?v=MWTe-iswnqc

Read more

Zero downtime deployments with Envoy original

by Freek Van der Herten – 4 minute read

Envoy is Laravel's official task runner. Using a Blade style syntax tasks can be defined that can be run both locally and remotely. At Spatie, we've been using Envoy for quite some time to deploy code on production servers. Summarized our trusty Envoy script did the following things: bringing the…

Read more

PHP vs Ruby, let's all just get along

Phil Sturgeon, who has contributed to numerous valuable PHP related projects, is doing Ruby nowadays. In an article he wrote for Sitepoint compares Ruby with PHP.

... I thought it would be interesting to have a slightly more fair comparison, from the perspective of someone who really enjoys writing both PHP and Ruby, and has done so for years. The aim here is not to find out which is “better”, but to point out a few key things I like about Ruby and its ecosystem.
http://www.sitepoint.com/php-vs-ruby-lets-all-just-get-along/

Read more

Validate (almost) anything in Laravel original

by Freek Van der Herten – 1 minute read

Laravel ships with some good validation capabilities. Form request validation is a nice way to make sure http requests pass valid data. To validate stuff that enters the application in some other way validators can be created manually. Unfortunately this is kinda verbose: $validator =…

Read more