A package to sync your .env file with .env.example

In a Laravel app most sensitive configuration values, like a db password, are being saved in an .env file. This file usually does not get committed in a git repo. In this way you can share the repo with collaborators without having them to know the sensitive values of your production environment.

The keys of the .env are often saved in an .env.example file that is saved in the repo. This helps you and your collaborators get up to speed quickly when installing the app locally. They can immediately see which environment variables are needed to run the app.

Over time however you might add a variable to .env and forgetting to add it to .env.example. It’s a mistake that is easily made, and I have made that mistake many times in the past (sorry co-workers).

A couple of days ago Julien Tant released laravel-env-sync. This package makes sure the .env file is in sync with .env.example. After having installed the package you can run this artisan command to perform the sync:

php artisan env:sync

Thanks Julien for that awesome little package.

Our dashboard has been updated to make use of Laravel Echo

A couple of months ago we released a dashboard powered by Laravel, Pusher and Vue.js. In tandem with Laravel 5.3 a new JavaScript library was released called Laravel Echo. This library makes it very easy to work with a service like Pusher.

This weekend I took the time to update the dashboard to make use of Laravel Echo. All the custom code handling communication an authentication with Pusher was removed and replaced by Echo.

If you want to see the updated source code head over to the dashboard repo at GitHub. I also updated the blog post about the dashboard to reflect all the code changes.

Automatically generate a sitemap in Laravel

Today my company released a package called laravel-sitemap. There are already a lot of excellent sitemap packages out there. They all have in common that you have to manually add links that must appear in the sitemap. With our new package that isn’t required. It can automatically build up a sitemap by crawling a site. In this post I’d like to explain why we built it and how it works.

Is a sitemap really needed?

In theory sitemaps helps web crawlers from search engines discover all pages of your site. Google’s own documentation has this to say about them:

If the pages of your site are properly linked, web crawlers can usually discover all links. Even so, a sitemap can improve the crawling of your site, particularly if your site meets one of the following criteria:

– Your site is really large. As a result, it’s more likely Google web crawlers might overlook crawling some of your new or recently updated pages.
– Your site has a large archive of content pages that are isolated or well not linked to each other. If you site pages do not naturally reference each other, you can list them in a sitemap to ensure that Google does not overlook some of your pages.
– Your site is new and has few external links to it. Googlebot and other web crawlers crawl the web by following links from one page to another. As a result, Google might not discover your pages if no other sites link to them.
– Your site uses rich media content, is shown in Google News, or uses other sitemaps-compatible annotations. Google can take additional information from sitemaps into account for search, where appropriate.

For bigger sites, where not all pages are not linked (for example a webshop, where not all products are linked in the dom), a sitemap is definitely needed. But for small to medium-sized sites where all url’s are linked properly, I’d conclude, when reading Google’s documentation, that a sitemap is not needed per se. When asking to peers about this and Googling around it becomes clear that there is no consensus if a sitemap is really needed for such sites. If you have an opinion on this or a link to a good blogpost on the subject, let me know in the comments below.

What often gets mentioned however is that sites will be crawled a bit faster if it has a sitemap and you submit it to the various search engines. Also heard quite often as an advantage of having a sitemap is that, in Google’s Search Console you can compare the number of pages in your sitemap versus the number of pages Google has crawled. In this way you can detect if Google is somehow failing to crawl sections of sites that you expect to be crawled.

There seem to be no disadvantages of having a sitemap and you might get, it’s not guaranteed, to enjoy at least some of it’s advantages. Google has this to say about it in their docs: I

Using a sitemap doesn’t guarantee that all the items in your sitemap will be crawled and indexed, as Google processes rely on complex algorithms to schedule crawling. However, in most cases, your site will benefit from having a sitemap, and you’ll never be penalized for having one.

So having a sitemap doesn’t look that important to me for a smaller site, so I don’t want to spend a lot of time creating a sitemap.xml. That’s why we made a package that can, in most cases, generate a sitemap with just a few lines of code.

Creating a sitemap

Imagine you have a Laravel app, running at example.com, where every page is properly linked (aka all pages appear in the dom somewhere). The app has a homepage, a contact page, some project pages and some news items. Using our package this is how you could generate a sitemap:

use Spatie\Sitemap\Sitemap;
use Spatie\Tags\Url;

$sitemap = Sitemap::create()
    ->add(Url::create('/home'))
    ->add(Url::create('/contact'));

NewsItem::all()->each(function (NewsItem $newsItem) use ($sitemap) {
    $sitemap->add(Url::create("/news/{$newsItem->slug}"));
});

Projects::all()->each(function (Project $project) use ($sitemap) {
    $sitemap->add(Url::create("/project/{$project->slug}"));
});

$sitemap->writeToFile(public_path('sitemap.xml'));

That’ll work but it’s quite verbose. If you add another content type or another loose page like /contact, you mustn’t forget to add it the sitemap.

Generating a sitemap

To avoid having to manually add links to a sitemap, the package includes a SitemapGenerator. This class can automatically crawl your site and put all the links it discovers in a sitemap.

Using a SitemapGenerator all of the code from the previous example can be replaced by this:

use Spatie\Sitemap\SitemapGenerator;

SitemapGenerator::create('https://example.com')->writeToFile(public_path('sitemap.xml'));

You can easily create an artisan command to create a sitemap and schedule it to run frequently. This will ensure that new pages and content types will be automatically picked up. Here’s how such a command could look like:

namespace App\Console\Commands;

use Illuminate\Console\Command;
use Spatie\Sitemap\SitemapGenerator;

class GenerateSitemap extends Command
{
    /**
     * The console command name.
     *
     * @var string
     */
    protected $signature = 'sitemap:generate';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Generate the sitemap.';

    /**
     * Execute the console command.
     *
     * @return mixed
     */
    public function handle()
    {
        // modify this to your own needs
        SitemapGenerator::create(config('app.url'))
            ->writeToFile(public_path('sitemap.xml'));
    }
}

It can be scheduled in the console kernel to be run daily.

// app/Console/Kernel.php
protected function schedule(Schedule $schedule)
{
    ...
    $schedule->command('sitemap:generate')->daily();
    ...
}

The best of both worlds

You can also combine the two approaches. You can manually add links to a generated sitemap. Here’s an example on how to do that:

SitemapGenerator::create('https://example.com')
   ->getSitemap()
   ->add(Url::create('/extra-page')
   ->add(...)
    ...
   ->writeToFile($path);   

Limitations

Our package is targeted at small to medium-sized apps. According to the specification a sitemap can hold up to 50 000 items (if have more links you’ll need a sitemap index). There are also specific link types for video’s, image’s, etc… The package currently does not have support for sitemap indexes and these other types of links because it’s not needed for any of our projects. I’d accept a PR that adds these things to our package.

Here are some alternatives that already support these features (but they don’t include the crawler from our package)

Further reading

If you want to know more about sitemaps in general, take a look at these posts (provided by my colleague Jef)

In conclusion

If you need a sitemap for your small to medium sized app, laravel-sitemap can probably help you. Take a look at the package on GitHub to learn all the features not mentioned in this blogpost:

Be sure to also take a look at the list of Laravel packages we’ve previously made.

Hunting for great names in programming

A great story by DHH on his quest to find good names for some functions he was working on.

One of the real delights of programming is picking great variable, method, and class names. But an even greater treat is when you can name pairs, or even whole narratives, that fit just right. And the very best of those is when you’re forced to trade off multiple forces pulling in different directions.

https://m.signalvnoise.com/hunting-for-great-names-in-programming-16f624c8fc03

Laracon EU recap day 2

Here’s Simon Nicklin‘s recap of day two of the excellent Laracon EU conference: https://www.linkedin.com/pulse/laracon-eu-2016-conference-day-2-simon-nicklin

Personally I had a great time at Laracon. I couldn’t relax that good until after I delivered my own talk. Luckily it went well and I got some good feedback. It was very good to see both new and familiar faces. Most talks were excellent, and the venue was amazing. Just look at this picture:

Laracon

I’ll be sure to attend next year’s Laracon!

Debugging collection chains

A couple of weeks ago I published a blog post on how you can easily debug collections using a dd macro. Meanwhile my company released a package that contains that macro. In this post I’d like to introduce a new dump macro, recently introduced in the package, that makes debugging collection chain even easier.

Here’s what the dump macro itself looks like.

Collection::macro('dump', function () {
    Collection::make(func_get_args())
        ->push($this)
        ->each(function ($item) {
            (new Dumper)->dump($item);
        });
    return $this;
});

So what the macro basically does is dumping any argument you give it to the screen together with the collection itself. The entire collection is returned, so you can further chain it. Sounds a little abstract, no? Easier said: this macro can be used to dump all the steps in your collection chain to the screen.

Let’s see it in action. Take a look this collection chain:

collect([1,2,3])
    ->dump('original collection')

    ->map(function(int $number) {
        return $number * 2;
    })
    ->dump('multiplied by two')

    ->filter(function(int $number) {
        return $number > 3;
    })
    ->dump('filtered higher than three')

    ->dd();

Executing that chain results in this being displayed on the screen.

dump output

Displaying every transformation in the chain will make it much easier to find a potential bug. Hope you like it!

Laravel LTS is a Trap

A couple of months ago Jason McCreary, creator of Laravel Shift, wrote down his opinion on the Laravel’s LTS release. I couldn’t agree more with this piece.

The more developers that get trapped by LTS, the more of a drag it creates on the Laravel community. Potentially having adverse affects on its growth.
Using LTS as a minimum compatibility line for a Laravel package or other third-party code is understandable. But freezing your apps to an LTS version is not. Your apps should run the latest stable version of Laravel.

https://medium.com/@jasonmccreary/laravel-lts-is-a-trap-97b1d1103961

Learn about grant types in Laravel Passport

Laravel Passport is an easy to use OAuth2 server that was released alongside Laravel 5.3. Mohamed Said wrote an excellent guest post at Laravel News about the grant types used in Passport.

OAuth2 is a security framework that controls access to protected areas of an application, and it’s mainly used to control how different clients consume an API ensuring they have the proper permissions to access the requested resources.

Laravel Passport is a full OAuth2 server implementation; it was built to make it easy to apply authentication over an API for laravel-based web applications.

https://laravel-news.com/2016/08/passport-grant-types/

Laracon EU recap day 1

The Laracon EU conference is happening right now. Talking to other developers is a joy like always, the speakers are great and the venue is amazing. Here’s a good recap written by Simon Nicklin of the first day of the Laracon EU conference.

We entered the building and joined the back of the queue. I say we, even though I travelled on my own I already felt part of something. The queue snaked around a mood light corner to the awaiting registration desk where we are split into last name lanes. A pleasant volunteer welcomed me as I showed her my ticket. After a quick flick through the name cards I’m registered. For me this was the start of Laracon EU 2016.

https://www.linkedin.com/pulse/laracon-eu-conference-2016-day-1-simon-nicklin

A package to easily work with regex in PHP

PHP offers some functions to work with regular expressions, most notably preg_match, preg_match_all and preg_replace. Unfortunately those functions are a bit hard to use. Take preg_match_all for example, it requires you to pass in an array by reference to get all the matches. When something goes wrong some of those preg_ functions return false, while others return null. To get to the actual error message some truly horrible stuff needs to be done.

To make working with regex a bit more developer-friendly my colleague Sebastian coded up a new package called regex. Here’s how you can work with it:

use Spatie\Regex\Regex;

// Using `match`
Regex::match('/a/', 'abc'); // `MatchResult` object
Regex::match('/a/', 'abc')->hasMatch(); // true
Regex::match('/a/', 'abc')->result(); // 'a'

// Capturing groups with `match`
Regex::match('/a(b)/', 'abc')->result(); // 'ab'
Regex::match('/a(b)/', 'abc')->group(1); // 'a'

// Using `matchAll`
Regex::matchAll('/a/', 'abcabc')->hasMatch(); // true
Regex::matchAll('/a/', 'abcabc')->results(); // Array of `MatchResult` objects

// Using replace
Regex::replace('/a/', 'b', 'abc')->result(); // 'bbc';
Regex::replace('/a/', function (MatchResult $result) {
    return $result->result() . 'Hello!';
}, 'abc')->result(); // 'aHello!bc';

I’m pretty sure you agree this is much easier to work with (if you’re not a regex-expert, but more of an occasional regex user). Take a look at the full documentation on GitHub to learn all the options. This isn’t the first package our team has made, head over to our company website to view a list of all previously released packages.

How to use WordPress as a backend for a Laravel Application

Recently Eric L. Barnes put a new coat of paint on Laravel News. Behind the scenes there were some changes as well. In a new post he explains how he integrated the WordPress backend with a Laravel app.

Last week I relaunched Laravel News, and the new site is running on Laravel with WordPress as the backend. I’ve been using WordPress for the past two years, and I’ve grown to enjoy the features that it provides. The publishing experience, the media manager, the mobile app, and Jetpack for tracking stats.

I wasn’t ready to give these features up, and I didn’t have the time to build my own system, so I decided to keep WordPress and just use an API plugin to pull all the content I needed out, then store it in my Laravel application. In this tutorial, I wanted to outline how I set it all up.

https://laravel-news.com/2016/08/wordpress-api-with-laravel/

Improving readability using array_filter

In this post I’d like to share a quick tip on how you can improve the readability of your code with array_filter.

Today I was working on some code that looked something like this:

class Address
{
    ...

    public function toArray()
    {
        $address = [
            'name' => $this->name,
            'street' => $this->street,
            'location' => $this->location,
        ];

        if ($this->line2 != '') {
            $address['line2'] = $this->line2;
        }

        if ($this->busNumber != '') {
            $address['busNumber'] = $this->busNumber;
        }

        if ($this->country != '') {
            $address['country'] = $this->country;
        }


        return $address;
    }
}

Did you know that you can use array_filter to clean this up? I didn’t, until today.

When that function is called without a second argument it will remove any element that contains a falsy value (so null, or an empty string) Here’s the refactored, equivalent code:

class Address
{
    ...

    public function toArray()
    {
        return array_filter([
            'name' => $this->name,
            'street' => $this->street,
            'line2' => $this->line2,
            'busNumber' => $this->busNumber,
            'location' => $this->location,
            'country' => $this->country,
        ]);
    }
}

That’s much better!

Just be careful when using this with numeric data that you want to keep in the array. 0 is considered as a falsy value too, so it’ll be removed as well.

Joind.In Needs Help

Joind.in is a website where attendees can leave feedback for speakers delivering talks and conferences and user groups. This feedback is very useful for the speakers who which improve their skills. In my mind it is an essential part of the PHP ecosystem.

For the last 6 years Lorna Jane Mitchell and Rob Allen have maintained the project. They are now looking for others to take over their duties.

This post is about the open source project, Joind.in. Joind.in is a tool to allow attendees at conferences or other events to offer immediate public feedback to speakers and organisers at those events. Joind.in is an open source project run by volunteers. For the last 6 years I’ve been a maintainer of this project, following a year or two of being a contributor. Over the last few months, myself and my comaintainer Rob Allen have been mostly inactive due to other commitments, and we have agreed it’s time to step aside and let others take up the baton.

http://lornajane.net/posts/2016/joind-in-needs-help

I Peeked Into My Node_Modules Directory And You Won’t Believe What Happened Next

Jordan Scales examined the contents of the node_modules directory a discovered a lot of junk.

While code bloat continues to slow down our websites, drain our batteries, and make “npm install” slow for a few seconds, many developers like myself have decided to carefully audit the dependencies we bring into our projects. It’s time we as a community stand up and say enough is enough, this community belongs to all of us, and not just a handful of JavaScript developers with great hair.

I decided to document my experiences in auditing my projects’ dependencies, and I hope you find the following information useful.

https://medium.com/friendship-dot-js/i-peeked-into-my-node-modules-directory-and-you-wont-believe-what-happened-next-b89f63d21558

Build a Facebook chatbot in 10 minutes with PHP

In a new post on his site, Christoph Rumpel explains how you can quickly build a Facebook chatbot with PHP.

The chatbot topic is huge right now. Finally there is something quite new again and nobody knows what’s happening next. This is the perfect time to start experimenting with chatbots and to build your own one right now. Give me 10 minutes of your time and I will give you your first chatbot!

http://christoph-rumpel.com/2016/08/build-a-php-chatbot-in-10-minutes/

moment().endOf(‘term’)

Without any doubt Tim Wood, the creator of the awesome moment.js library, has done a lot for the community. It’s really a shame that the constant pressure of maintaining the library has taken it’s toll.

The correlation between Open Source and burnout is no secret, and I am not immune to it.

Seeing bugs and issues continue to roll in and being mentally unable to address them has led to feelings of failure and depression. When looking at the moment project, I could only see the negatives. The bugs and misnomers and mistakes I had made. It let to a cycle of being too depressed to contribute, which led to being depressed because I wasn’t contributing.

https://medium.com/@timrwood/moment-endof-term-522d8965689

Practicing YAGNI

In a new post on his blog Jason McCreary, creator of Laravel Shift, wrote down the summary of his Laracon US talk.

I consider myself a searcher. On a quest to find the Holy Grail of programming practices – that single practice which instantly levels up my skills. While I know this doesn’t exist, I do believe in a set of practices. Recently, I found one to be YAGNI.

YAGNI is a principle of eXtreme Programming – something I practice daily at work. YAGNI is an acronym for You Aren’t Gonna Need It. It states a programmer should not add functionality until deemed necessary. In theory, this seems straightforward, but few programmers practice it.

http://jason.pureconcepts.net/2016/08/practicing-yagni/

Some handy collection macros

Laravel’s collection class is truly wonderful. It contains a lot of handy methods and you can create some very elegant code with it. In client projects I found myself adding the same macro’s over and over again. That’s why my colleague Seb and I took some time to create a package aptly called laravel-collection-macros that contains those macros. You can view the source code and installation instructions on GitHub.

To install the package you’ll only need to pull it via composer and register the service provider. With that out of the way the collection class in your project will gain these methods:

dd

This macro dumps the contents of the collection and terminates the script. It makes debugging a collection much easier.

collect([1,2,3])->dd();

split

Image you need to render some items in a given amount of columns. With the split macro you can split the collection into a the given number of groups.

$collection = collect(['a', 'b', 'c', 'd', 'e', 'f'])->split(3);

$collection->count(); // returns 3

$collection->first(); // returns a collection with 'a' and 'b';
$collection->last(); // returns a collection with 'e' and 'f';

validate

With this macro you can validate all items inside a collection. You can pass a validate rule to it.

collect(['sebastian@spatie.be', 'bla'])->validate('email'); // returns false
collect(['sebastian@spatie.be', 'freek@spatie.be'])->validate('email'); // returns true

//for fine grained control you may also pass a closure.
collect(['foo', 'foo'])->validate(function ($item) {
   return $item === 'foo';
}); // returns true

range

Creates a new collection instance with a range of numbers. This functions accepts the same parameters as PHP’s standard range function.

collect()->range(1, 3)->toArray(); //returns [1,2,3]

ifAny

The passed callable will only be called if the collection isn’t empty. The entire collection will be returned.

collect()->ifAny(function() { // empty collection so this won't get called
   echo 'Hello';
});

collect([1, 2, 3])->ifAny(function() { // non-empty collection so this will get called
   echo 'Hello';
});

ifEmpty

This is the opposite of ifAny.

collect()->ifEmpty(function() { // empty collection so this will called
   echo 'Hello';
});

collect([1, 2, 3])->ifEmpty(function() { // non-empty collection so this won't get called
   echo 'Hello';
});

none

Checks whether a collection doesn’t contain any occurrences of a given item, key-value pair, or passing truth test. The function accepts the same parameters as the contains collection method.

collect(['foo'])->none('bar'); // returns true
collect(['foo'])->none('foo'); // returns false

collect([['name' => 'foo']])->none('name', 'bar'); // returns true
collect([['name' => 'foo']])->none('name', 'foo'); // returns false

collect(['name' => 'foo'])->none(function ($key, $value) {
   return $key === 'name' && $value === 'bar';
}); // returns true

groupByModel

This is a very opinionated macro. It works similar to groupBy, but it’ll group the collection by an Eloquent model instead of a string. Imagine that your project contains an Article model that has a relationship with a Category model. In your view you want to render all articles grouped by category.

Sure you could to this:

Article::all()->groupBy(function(Article $article) {
  return $article->category->name;
});

That’ll work but the downside of it is that you only have the name of the category left when looping over the resulting collection.

When using the groupByModel macro you still can get to all properties of the category.


Article::all()->groupByModel('category'); //this returns something like this // [ // [ // 'category' => $category, // 'items' => [ // [ // articles models with the category], // ], // ], // [ // 'category' => $category2, // 'items' => [ // [ // article models with $category 2 ], // ], // ], // ];

Want to know more about the package, then head over to GitHub to learn all the options. We do accept new macro’s to the package, so if you’ve got a macro lying around that could be useful to your fellow artisans, send us a PR.

You can take a look at the Laravel packages we previously made on our website. If one of our packages makes it to your production environment don’t forget to send us a postcard.