Posts tagged with laravel

A Laravel package to rebuild the database original

by Freek Van der Herten – 2 minute read

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…

Read more

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://medium.com/@taylorotwell/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.

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.

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.

Read more

Using Varnish on a Laravel Forge provisioned server original

by Freek Van der Herten – 12 minute read

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…

Read more

Setting up Xdebug with Laravel Valet original

by Freek Van der Herten – 4 minute read

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…

Read more

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.

Read more

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/

Read more

Overriding Laravel's helper functions

Miklós Galicz posted a short article on how he managed to override Laravel's str_slug helper function.

Long story short, until this is resolved one way or another... A really obscure but powerful tool can be a temporary solution for this. It's called Helper Overloading. Laravel's helpers are created in a way that checks if the method already exists. ... This is really great, the only thing remaining is to actually add our own method before Laravel creates it own version.

https://blackfyre.ninja/blog/fixing-slug-generation-problems

Read more

Symfony and Laravel will require PHP 7 soon

According to Fabien Potencier, lead of the Symfony project, the next major version of Symfony, to be released at then end of 2017, will require PHP 7.

But Laravel will drop PHP 5 support even sooner. Taylor Otwell, the creator of Laravel, announced that Laravel 5.5, to be released in June 2017, will leave PHP 5 behind.

On multiple occasions Taylor et co. have stated that they don't like the strictness that things like scalar and return type hints bring to the table. So I don't expect to see them appear much in Laravel codebase. Smaller syntax improvements like for example the null coalescing operator will almost certainly be used.

A few weeks ago Jordi Boggiano reported that only a miserable 3% of all packages present on Packagist require PHP 7. The best thing about Symfony and Laravel dropping PHP 5 support is that it will send a strong message throughout the entire PHP ecosystem that you shouldn't bother with PHP 5 code anymore. When creating new projects and packages more developers will target PHP 7 as a minimum version as well.

For our PHP and Laravel packages we left PHP 5 behind as soon as PHP 7 was available. Our packages already make extensive use of return type hints, anonymous classes and the null coalescing operator to create more readable (and thus more maintainable) code.

(Fun Scary fact: Wordpress only requires PHP 5.2 ?)

Read more

Scaling Laravel Using AWS Elastic Beanstalk

Elastic Beanstalk is a service by Amazon that can automatically scale an application. Gilbert Pellegrom published a second blogpost in his series on how to get Laravel up and running on the service.

In my last article we decoupled Laravel and got it ready for deployment to the Elastic Beanstalk architecture. However, before we race ahead to actually deploying our code to Elastic Beanstalk we need to do some preparation first. Specifically we need to set up some other AWS services that will be used by our Laravel app. These include:
  • Virtual Private Cloud (VPC) to keep our infrastructure secure
  • Relational Database Service (RDS) for our MySQL database
  • ElastiCache for our Redis cache

With these “supporting” services up and running we can finally move on to deploying our Laravel app to Elastic Beanstalk.

https://deliciousbrains.com/scaling-laravel-using-aws-elastic-beanstalk-part-2-setting-up-vpc-rds-elasticache/

Read more

An easy to install uptime monitor original

by Freek Van der Herten – 4 minute read

A few weeks ago we released our uptime and ssl certificate monitor. It's written in PHP and distributed as a Laravel package. If you're familiar with Laravel that's all fine, but if you have no experience with that (kick ass) framework, it's a bit difficult to get started with using our uptime…

Read more

Improving the performance of our PHP based crawler original

by Freek Van der Herten – 2 minute read

Today a new major version of our homegrown crawler was released. The crawler is used to power our http-status-check, laravel-sitemap and laravel-link-checker packages. A new major feature is the greatly improved crawling speed. This was accomplished by leveraging multiple concurrent requests. Let's…

Read more

Some request filtering macros

In a gist on GitHub Adam Wathan shares some macros that can be used to clean up a request.

Allows you to trim things, lowercase things, whatever you want. Pass a callable or array of callables that each expect a single argument:
Request::macro('filter', function ($key, $filters) {
    return collect($filters)->reduce(function ($filtered, $filter) {
        return $filter($filtered);
    }, $this->input($key));
});

https://gist.github.com/adamwathan/610a9818382900daac6d6ecdf75a109b

If you want to hear Adam talk some more about troubles with requests (generated by webforms) and possible solutions, listen to this episode of the Full Stack Radio Podcast.

Read more

murze.be is two years old original

by Freek Van der Herten – 3 minute read

I'm happy to share that this blog now celebrates its second anniversary. Two years ago I started murze.be to share my bookmarks and interesting links I found with other developers. Along the way I started to write some articles of my own, mainly introductory posts to the now 100+ packages my team…

Read more

An uptime and ssl certificate monitor written in PHP original

by Freek Van der Herten – 9 minute read

Today we released our newest package: spatie/laravel-uptime-monitor. It's a powerful, easy to configure uptime monitor. It's written in PHP and distributed as a Laravel package. It will notify you when your site is down (and when it comes back up). You can also be notified a few days before an SSL…

Read more

An unofficial Forge API

You might not know this but Forge already has an API, it's just not a documented and feature complete one. Open up your dev tools and inspect the web requests being sent while you do various stuff on Forge.

Marcel Pociot published a new package called Blacksmith (great name Marcel) that can make calls to that API. Here are a few code examples taken from the readme:

$activeServers = $blacksmith->getActiveServers();

$server = $blacksmith->getServer(1);

$sites = $server->getSites();

$newSite = $server->addSite($site_name, $project_type = 'php', $directory = '/public', $wildcards = false);

$jobs = $server->getScheduledJobs();

$newJob = $server->addScheduledJob($command, $user = 'forge', $frequency = 'minutely');

Very cool stuff. Because the Forge API doesn't include a method to login, the package will under the hood just submit a filled in login form.

An official API for Forge has been on my wishlist for quite some time. Because Forge's code base already includes an API my guess is that it wouldn't be too work to grow it in to a full, publicly available one. Though I surely cannot read Taylors mind, I think that if there were some more indications that a Forge API would be used by enough people, there's a higher chance that an official API would be built. I think the only reason why the API hasn't been built yet is because not enough people are asking for it. It makes sense for Taylor to only work on things that would actually be used. So if you are using Forge and do want an official API go ahead and star the BlackSmith package on GitHub and make some noise about it.

Read more

Laravel service provider examples

On his blog Barry van Veen listed some examples of things you can do within a Laravel service provider.

Currently, I'm working on my first Laravel package. So, it was time to dive into the wonderful world of the service container and service providers.

Laravel has some great docs about, but I wanted to see some real-world examples for myself. And what better way than to have a look at the packages that you already depend on?

This post details the different things that a service provider can be used for, each taken from a real open-source project. I've linked to the source of each example.

https://barryvanveen.nl/blog/34-laravel-service-provider-examples

Read more

Testing interactive Artisan commands

For a new package I'm working on I had to test some Artisan commands. The commands I want to test contain calls to ask and confirm to interactively get some input by the user. I had a little trouble finding a way to tests such commands, but luckily a blogpost by Mohammed Said pointed me in the right direction, which was to leverage partial mocks.

Here's the most interesting part, Artisan Commands can ask the user to provided specific pieces of information using a predefined methods that cover all the use cases an application might need. ... So we mock the command, register the mocked version in Kernel, add our expectations for method calls, and pretend the user response in the form of return values. ...

http://themsaid.com/building-testing-interactive-console-20160409/

Read more

Some people to follow on Twitter original

by Freek Van der Herten – 2 minute read

There are a lot of developers active on Twitter. Most of them tweet out interesting links, their opinions or stuff they're working on. I think Twitter is an excellent tool to stay in touch with what's going on in the Laravel and PHP community. If you're looking for some people to follow here are…

Read more

Building a switch Blade directive

Inani El Houssain created a switch Blade directive. It's a good primer if you want to learn how to create Blade directives yourself.

One of the good points of Laravel’s framework is that it allows you to make your own components, macros and directives. so today we will make use of Laravel’s Custom Blade directives and make something good.

https://medium.com/@InaniT0/build-your-own-switch-statment-using-laravels-custom-blade-directives-218244e41a7c

Read more